Skip to content

Instantly share code, notes, and snippets.

@raiph

raiph/.md Secret

Created December 11, 2023 16:03
Show Gist options
  • Save raiph/4606e71be3e06acd5bcad01c41fa8b82 to your computer and use it in GitHub Desktop.
Save raiph/4606e71be3e06acd5bcad01c41fa8b82 to your computer and use it in GitHub Desktop.
[raku] Phaser decks?

Let me first note some key principles that you should bear in mind no matter what, which may mean you can skip reading the rest of this gist after this first section.

One is the wisdom of YAGNI -- You Ain't Gonna Need It. 9 times out of 10 anything anyone comes up with is over-engineering. So the worst thing anyone can do is go design or implement something just because it seems like a good idea. Ya gotta know in your bones it's worth doing in principle, and also know that even then it might not really be "needed", and even then -- even if it is "needed" occasionally, it might be better to get by with some other way of doing things, so that the system we're maintaining doesn't get too complex.

Another wisdom is that of itch scratch driven dev. This is what will ultimately really matter. Itch scratching is about some dev choosing to write code to implement any ideas they or anyone else has. It is the leading factor in anything getting done in FLOSS spirit software: someone wants something to work so they go write code to make it work. I don't know if you find this sufficiently itchy to write the code to implement your ideas, but it is important to consider who you think might write it, and why.

As a good example of YAGNI and itch scratch dev, it's highly likely that me writing this, and/or you thinking what I suggest below, is over-engineering because we ain't gonna need it! That said, I've scratched my itch which was that I felt someone needed to say something like what I'm writing in this gist, so I've written it to scratch that itch.


I'm thinking it might be helpful if you tried thinking about, and maybe writing a comment about, principles related to phaser deck use.

(By "deck" I mean declarator block. By "use" I mean using decks after they've already been written. By "principles" I mean how code, written related to implementing phaser decks, might make reasonably consistent decisions about how those decks get used.)

For example, consider phasers of which there can be more than one contained within a code block. Perhaps all sibling decks should be displayed as a series of paragraphs if any one of the decks is displayed? Or perhaps just one at a time? Or both, depending on scenario? (I tend to think abstractly about such things so they pop into my head; I'm not saying whether or not they matter.)


When I read Liz's point that she didn't naturally see a use case for decking of most phasers, I immediately took a look at the list of phasers, which begin with BEGIN. Perhaps you could think about just BEGIN, and see where that leads? Can you think of examples of what those comments might be about, or, better still, go find comments Rakoons have written, next to BEGIN code in existing Raku code? (Maybe use Liz's rak tool to do so.) Does any of it look like commentary it would be good to be able to see outside of reading the code in the ordinary way and seeing the comments in situ?

Or perhaps think about each of the couple dozen phasers, one at a time, for a minute or so each? Or in small groups of phasers that have affinity with one another (PRE and POST, or ones that return values vs ones that don't, or compile phase ones vs run phase, etc). Whichever way you find easier (presuming you even attempt something like I'm suggesting!).

@rcmlz
Copy link

rcmlz commented Dec 12, 2023

My use case is in education and very basic formal proves and robustnes of code.

Given the Editor/IDE used by pupils/students supports showing the declarators on e.g. PRE and POST (e.g. as tool tips when hovering over a method of an object), it might convince pupils/students that explicitly documenting the contracts of a method/sub is an added value for anyone using the object/method/sub.

I do not know whether this feature would be also usefull in commercial environment, as the time for doing such a contract documentation might not be paid.

Reading your remarks about over-engineering I realize that (except from Comma) the support for Raku in other Editors/IDE's is very basic such that a feature like that is most likely not high priority.

Anyhow, here is an example that illustrates the use case I have in mind.

#| a simple collection of sort algorithms
class Sorter {
	#| Bubble sort - the classic textbook example in classic text book example style
	method bubble($input        #= reference to a sortable data structure containing only elements which have total order defined.
		      --> Bool      #= returns True if sorting succeeded
	 ) {
		my $n = $input.elems;
		PRE { $input.elems > 0 } #= input ≠ ∅ ∧
					             #= ∀x,y. 0 ≤ x ≤ y < |input|: input[x] cmp input[y] ∈ {Less Same More}

		POST { True            } #= |input| = |output| ∧
		                         #= ∀x,y. 0 ≤ x < y < |input| ⟹ output[x] ≤ output[y]

		loop (my $i = 0; $i < $n - 1; $i++) {
			loop (my $j = 0; $j < $n - $i - 1; $j++) {
				self.swap($input, $j, $j + 1) if $input[$j] > $input[$j + 1]
			}
		}
		return True
	} #=[ use Test;
		my @data = <1 3 2 0>;
		my $sorter = Sorter.new;
		$sorter.bubble(@data);
		is @data, <0 1 2 3>, 'sort <1 3 2 0> into <0 1 2 3>';
	]

	#| swaps two entries of a data structure
	method swap($data, UInt $i, UInt $j) {
		my $t = $data[$i];
		$data[$i] = $data[$j];
		$data[$j] = $t;
	}
}

my $sorter = Sorter.new;
use Test;
plan 6;

is $sorter.WHY, 'a simple collection of sort algorithms', '$sorter.WHY';
try {
	skip-rest;
	is $sorter.bubble.WHY.leading,
		'Bubble sort - the classic textbook example in classic text book example style',
		'$sorter.bubble.WHY.leading';
	is $sorter.bubble.WHY.tailing,
		'use Test; my @data = <1 3 2 0>; my $sorter = Sorter.new; $sorter.bubble(@data); is-deeply @data, <0 1 2 3>;',
		'$sorter.bubble.WHY.tailing';
	is $sorter.bubble.PRE.WHY.tailing,
		'input ≠ ∅ ∧ ∀x,y. 0 ≤ x ≤ y < |input|: input[x] cmp input[y] ∈ {Less Same More}',
		'$sorter.bubble.PRE.WHY.tailing';
	is $sorter.bubble.POST.WHY.tailing,
		'|input| = |output| ∧ ∀x,y. 0 ≤ x < y < |input| ⟹ output[x] ≤ output[y]',
		'$sorter.bubble.POST.WHY.tailing';

	use MONKEY-SEE-NO-EVAL;
	is EVAL($sorter.bubble.WHY.tailing),
		'ok 1 - sort <1 3 2 0> into <0 1 2 3>',
		'EVAL($sorter.bubble.WHY.tailing)';	
}

done-testing;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment