{{ message }}

Instantly share code, notes, and snippets.

# wimvanderbauwhede/raku-greedy-junctions.md

Last active Oct 8, 2020
The strange case of the greedy junction

# The strange case of the greedy junction

An illustration of how Raku's junctions are greedy by design, and a proposal.

Raku has a neat feature called Junctions. In this short article I want to highlight a peculiar consequence of the interaction of junctions with functions: they are greedy, by which I mean that they inadvertently turn other arguments of functions into junctions. To illustrate this behaviour, I will create a pair data structure that can take two values of different types, using a closure.

```enum RGB <R G B>;

# Pair Constructor: the arguments of pair() are captured
# in a closure that is returned
sub pair(\x, \y) {
sub (&p){ p(x, y) }
}```

So `pair` takes two arguments of arbitrary type and returns a closure which takes a function as argument. We will use this function to access the values stored in the pair. I will call these accessor functions `fst` and `snd`:

```# Accessors to get the values from the closure
my sub fst (&p) {p( sub (\x,\y){x})}
my sub snd (&p) {p( sub (\x,\y){y})}```

The function that does the actual selection is the anonymous subroutine returned by `fst` and `snd`, this is purely so that I can apply them to the pair rather than have to pass them as an argument. Let's look at an example, a pair of an `Int` and an `RGB`:

```my \p1 = pair 42, R;

if ( 42 == fst p1) {
say snd p1;	#=> says "R"
}```

So we create a pair by calling `pair` with two values, and use `fst` and `snd` to access the values in the pair. This is an immutable data structure so updates are not possible.

Now let's use a junction for one of the arguments.

```# Example instance with a 'one'-type junction
my Junction \p1j = pair (42^43),R;

if ( 42 == fst p1j) {
say snd p1j; #=> one(R, R)
}```

What has happened here is that the original argument `R` has been irrevocably turned into a junction with itself. This happens despite the fact that we never explicitly created a junction on `R`. This is a consequence of the application of a junction type to a function, and it is not a bug, simply an effect of junction behaviour. For a more detailed explanation, see my article "Reconstructing Raku's Junctions".

The Raku documentation of junctions says that you should not really try to get values out of a junction:

"Junctions are meant to be used as matchers in Boolean context; introspection of junctions is not supported. If you feel the urge to introspect a junction, use a Set or a related type instead."

However, there is a FAQ that grudgingly shows you how to do it. The FAQ once again warns against doing this:

"If you want to extract the values (eigenstates) from a Junction, you are probably doing something wrong and should be using a Set instead."

However, as demonstrated by the example I have given, there is a clear use case for recovering values from junctions. It is of course not the intention that one of the values stored in the pair becomes inaccessible simply because the other value happens to be a junction.

I therefore propose the addition of a `collapse` function which will allow to collapse these inadvertent junction values into their original values.

```if ( 42 == fst p1j) {
say collapse(snd p1j); #=> says 'R'
}```

The implementation of this function is taken from the above-mentioned FAQ, with the addition of a check to ensure that all values on the junction are identical.

```sub collapse(Junction \j) {
my @vvs;
-> Any \s { push @vvs, s }.(j);
my \$v =  shift @vvs;
my @ts = grep {!(\$_ ~~ \$v)}, @vvs;
if (@ts.elems==0) {
\$v
} else {
die "Can't collapse this Junction: elements are not identical: {\$v,@vvs}";
}
}```

It would be nice if this functionality could be added as a `collapse` method to the `Junction` class.

### wimvanderbauwhede commented Oct 4, 2020

 Thanks a lot, this is awesome! I wrote this as a way to get discussion going to see if I maybe could create an issue for this. And you've just gone and done a PR! I had a look at the code, very interesting! I hope one day I may learn enough about Rakudo's architecture and NQP to contribute something.

### lizmat commented Oct 5, 2020

 Is there a reason to keep this just as a gist, instead of a "proper" blog post?

### wimvanderbauwhede commented Oct 5, 2020

 Not really. The gist has the advantage that people can comment, because on my blog I don't have comments. And because I had thought that this post might result in some discussion, I thought I'd try a gist. All I need to do is select a picture for each and then they can go on the blog.

### lizmat commented Oct 5, 2020

 Let me know when you do this: https://rakudoweekly.blog/2020/10/05/2020-40-manifestly/ now refers to the gists, but can be updated :-)

### wimvanderbauwhede commented Oct 6, 2020

 @lizmat I've now posted them both on my blog. I think I'll delete these gists in a few weeks.