The following arose out of a discussion on #perl6. Junctions are new and
different from anything I have encountered, but I cant get rid of the
feeling that there needs to be some more flexibility in their use to
make them a common programming tool.
Background: Imagine a hand of cards. Cards may be Ace, Two, Three. Ace
having either the values 1 or 11, depending on context, the other cards
their face value. Sums of a hand over 21 are invalid.
Hands with multiple junctions become interesting, eg.,
p: Ace, Two, Ace
d: Ace, Three, Ace
Given that Ace has a value of 1 or 11 depending on context, it would
seem natural to use a junction. Hence the two hands can be expressed as:
@p = 1|11, 2, 1|11;
@d = 1|11, 3, 1|11;
If we use [+] to add these, we get
$p = [+] @p; say $p.perl; # any(any(4,14),any(14,24))
$d = [+] @d; say $d.perl; #any(any(5,15),any(15,25))
Since the values of 24 & 25 are greater than 21, they must be eliminated
from consideration.
What we want is for hand @d to beat hand @p because 15 > 14
On #perl6, rouso, masak and moritz_ explained that I am incorrectly
thinking about junctions as sets and that for this task I should be
using another perl idiom, namely lists. Something like:
moritz_ rakudo: ([1,11], 3, [1,11]).reduce({@($^a) X+ @($^b)})
p6eval rakudo bb22e0: RESULT«[5, 15, 15, 25]»
Then the out-of-limit values (in the above case 25) can be stripped off
using grep, viz.,
# here we have ([1,11],3,[1,11]) instead of (1|11, 3, 1|11)
my @dlist = grep { $_ < 21 } ([1,11], 3, [1,11]).reduce({@($^a) X+ @($^b)});
Then the two lists (do the same for @p) can be compared by a junction
comparison of the form
if any(@plist) > all(@dlist) { say 'p wins' };
The problem is not just that [+] @p produces a junction with undesired
(>21) eigenstates, but that the [+] @d produces a junction of the form
any(any(5,15),any(15,25)) which should collapse to any(5,15,25)
whereas we want a junction of the form
all(5,15,25)
After the #perl6 conversation, I thought some more. A junction is a neat
way of expressing the hand, but the junction needs to be converted to a
list to do some processing, and then the lists are compared using junctions.
I think (I might be wrong) that the conversion from a junction to a list
is specified by the .eigenstates method, but it doesn't seem to
completely flatten a junction yet - it produces the
any(any(4,14),any(14,24)) output shown above.
So my questions to the language list are:
a) Am I trying to fit a square peg in a round hole by applying junctions
to this sort of problem? If so, would it be possible to explain what the
limits are to the junction approach, or another way of expressing this
question: what sort of problems should junctions be applied to?
b) Why would it be "wrong" to have a method for eliminating eigenstates
from a junction? (The answer to this might naturally arise out of the
answer to a). However, ...
In a wider context, I would conjecture that some algorithms to which
junctions could be applied would be optimised if some states could be
eliminated, a bit like tree-pruning optimisations that eliminate paths
which can never produce a correct answer. Consequently, providing a
filtering method would increase the usefulness of the junction as a
programming tool. Perhaps
$new-junction = $old-junction.grep({ $_ <= 21 }); # not sure if the
parens are needed here
c) On junction algebra, am I wrong or is always true that a junction of
the form
any('x','y','z', any('foo','bar'), 1, 2, 3) should collapse to
any('x','y','z','foo','bar',1,2,3)
In other words, if an 'any' junction is contained in an outer 'any', the
inner 'any' can be factored out?
This would eliminate the nested junctions produced by .eigenstates
d) Am I right in thinking this is also true for nested 'all' junctions? viz.
all(1,2,3,all('foo', 'bar')) collapses to all(1,2,3,'foo','bar')
e) Conjecture: This true of all junction types, eg.,
junc(..., junc(...)) == junc(..., ...)
f) Would it be possible to have a means to coerce an 'any' junction into
an 'all' junction or vice versa? eg.
my $old-junction = 1|2|3; my $new-junction = all{$old-junction}; say
$old-junction.perl
# all(1,2,3)
Using () creates a new junction all(any(1,2,3))
{} are undefined for junctions.
If my suggestions prove acceptable, then for my problem I would have:
# @p & @d get defined as arrays of junctions, eg.
my @p=1|11,2,1|11;
my @d=1|11,3,1|11;
#later
my $p = ([+] @p).grep { $_ < 21 };
my $d = ([+] @d).grep { $_ < 21 };
if $p > all{$d} { say 'p wins' } else { say 'd wins' };
Richard (finanalyst)