Malfunction Junction, what's your function?

4 views
Skip to first unread message

Joshua Gatcomb

unread,
Apr 27, 2005, 8:46:53 AM4/27/05
to perl6-l...@perl.org
Ok - sorry for the cheesy subject line but I couldn't resist.

So I am working on porting some interesting pieces of code I wrote in
p5 at the Monastery to p6 for the benefit of others - primarily to
show how easy the transition can be.

Since Pugs doesn't have p6 rules yet I wanted to show off the power of
junctions instead of using the pcre support. Basically I need to know
if any character in string x matches any character in string y - easy
right: $str =~ /[chars]/ becomes any( @x_chars ) eq any( @y_chars ).
The problem is that in the regex version I use capturing parens to
identify the character matched. For the purposes of the problem I
don't need to rely on the first character matched I just need to know
1.

Without doing a lot of research into junctions, I thought the
following would work:

my $matches = any( @x_chars ) eq any( @y_chars );
my $match = $matches.pick;

Ok - so maybe not - perhaps I should just change .pick to .values

hmmm - still not working - perhaps I need to give the junctions more
information as to what I am after

all( any() eq any() );

Hmmm - perhaps the problem isn't with junctions but with Pugs but to
know for sure I need to find out what, if anything, is the proper way
to do what I want. The worst that could happen is that I find out
there isn't a way to get a what matched from an any() eq any()
comparison.

Cheers,
Joshua Gatcomb
a.k.a. L~R

Patrick R. Michaud

unread,
Apr 27, 2005, 11:41:54 AM4/27/05
to Joshua Gatcomb, perl6-l...@perl.org
On Wed, Apr 27, 2005 at 08:46:53AM -0400, Joshua Gatcomb wrote:
> The problem is that in the regex version I use capturing parens to
> identify the character matched. For the purposes of the problem I
> don't need to rely on the first character matched I just need to know
> 1.
>
> Without doing a lot of research into junctions, I thought the
> following would work:
>
> my $matches = any( @x_chars ) eq any( @y_chars );
> my $match = $matches.pick;

Perhaps the easiest way to explain the difficulty here is to note that
executing a relational op (i.e. returning a boolean) value on a junction
argument returns a junction of boolean values. So, the C<eq> expression
above doesn't contain the intersection of chars that match, it's just
a junction of the (boolean) values returned by &infix:<eq> on each
pair of arguments from @x_chars and @y_chars. Actually, since
there's two junction arguments, the result will be an C<any> junction
of C<any> junctions.

> The worst that could happen is that I find out
> there isn't a way to get a what matched from an any() eq any()
> comparison.

Not using the standard &infix:<eq>, no. But I suppose one could get
close to what you're wanting with something like:

sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a : ''; }

and then

my $matches = any( @x_chars ) myeq any( @y_chars );
my $match = $matches.pick;

although since $match is any( any( ... ), any( ... ), any( ... ) )
I'm not sure if C<.pick> would end up "picking" a junction as opposed
to one of the inner values, or if it could "pick" one of the empty
string values.

Anyway, hope this helps clear up why the original wasn't working.

Pm

Thomas Sandlaß

unread,
Apr 27, 2005, 12:29:46 PM4/27/05
to perl6-l...@perl.org
Patrick R. Michaud wrote:
> On Wed, Apr 27, 2005 at 08:46:53AM -0400, Joshua Gatcomb wrote:
>
>>The problem is that in the regex version I use capturing parens to
>>identify the character matched. For the purposes of the problem I
>>don't need to rely on the first character matched I just need to know
>>1.
>>
>>Without doing a lot of research into junctions, I thought the
>>following would work:
>>
>>my $matches = any( @x_chars ) eq any( @y_chars );
>>my $match = $matches.pick;
>
>
> Perhaps the easiest way to explain the difficulty here is to note that
> executing a relational op (i.e. returning a boolean) value on a junction
> argument returns a junction of boolean values.

Is that so? Does Perl6 have some fundamental law of junction preservation?
I would expect $matches to be either false or true---the junction values
are garbage collected.


>... or if it could "pick" one of the empty
> string values.

That's my understanding. The junctive value is lazily evaluating the
list of all permutations from @x_chars and @y_chars one at a time.
The myeq is called once for .pick and the result goes into $match.

But if you could use 'permute( @x_chars ) »myeq« permute( @y_chars )'
after writing the permute function ;)

And I wonder if

permute( @x_chars ) »{ $^a eq $^b ?? $^a :: ''}« permute( @y_chars )

would do the same?
--
TSa (Thomas Sandlaß)


Jonathan Scott Duff

unread,
Apr 27, 2005, 12:40:48 PM4/27/05
to Paul Seamons, perl6-l...@perl.org
On Wed, Apr 27, 2005 at 10:30:35AM -0600, Paul Seamons wrote:
> Minor note.
>
> Would you want this:

>
> > sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a : ''; }
>
> to be:
>
> sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a but bool::true:
> ''; }
>
> (Is that the right way to do it ?)

Firstly, everybody needs to remember that ?: is now ??:: :-)

And yes, if $a and $b are equal but evaluate to a false value, you
probably want to attach some truthfulness to the value for boolean
sake. I wonder if you shouldn't also return a bool::false for the
other case just to be explicit:

sub &infix:<myeq>(Str $a, Str $b) {

return ($a eq $b) ?? $a but bool::true :: bool::false
}

Suddenly I'm suffering a visual overload of colons though.

-Scott
--
Jonathan Scott Duff
du...@pobox.com

Paul Seamons

unread,
Apr 27, 2005, 12:30:35 PM4/27/05
to perl6-l...@perl.org
Minor note.

Would you want this:

> sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a : ''; }

to be:

sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a but bool::true:
''; }

(Is that the right way to do it ?)

Paul

Luke Palmer

unread,
Apr 27, 2005, 11:28:59 AM4/27/05
to Thomas Sandlaß, perl6-l...@perl.org
Thomas Sandlaß writes:
> Patrick R. Michaud wrote:
> >On Wed, Apr 27, 2005 at 08:46:53AM -0400, Joshua Gatcomb wrote:
> >
> >>The problem is that in the regex version I use capturing parens to
> >>identify the character matched. For the purposes of the problem I
> >>don't need to rely on the first character matched I just need to know
> >>1.
> >>
> >>Without doing a lot of research into junctions, I thought the
> >>following would work:
> >>
> >>my $matches = any( @x_chars ) eq any( @y_chars );
> >>my $match = $matches.pick;
> >
> >
> >Perhaps the easiest way to explain the difficulty here is to note that
> >executing a relational op (i.e. returning a boolean) value on a junction
> >argument returns a junction of boolean values.
>
> Is that so? Does Perl6 have some fundamental law of junction preservation?
> I would expect $matches to be either false or true---the junction values
> are garbage collected.

Nope, not unless we give comparitors special junctive semantics (which
may end up being a good idea). Consider:

my $match = any(<a b c>) eq any(<c d e>);
my $weird = $match + 1;
say "Ok" if $weird == 2;

This program does not say Ok if the junction "garbage collects" its
states.

Indeed, the junction doesn't preserve under boolean context.

my $match = ?(any(<a b c>) eq any(<c d e>));
# $match is now 1 or 0

Quantum::Superpositions made comparitors special.

my $match = any(<a b c>) eq 'b'; # $match is 'b'

There's something eerie and inconsistent about that, mostly that you
have to mark your functions as comparitors when you want them to do
that. But it is vastly less a pain in this case than having to write
Patrick's myeq.

The more I think about junctions, the less nice they seem to be. Not to
say that they don't kick ass still.

Luke

Patrick R. Michaud

unread,
Apr 27, 2005, 1:27:12 PM4/27/05
to Paul Seamons, perl6-l...@perl.org
On Wed, Apr 27, 2005 at 10:30:35AM -0600, Paul Seamons wrote:
> Minor note.
>
> Would you want this:
> > sub &infix:<myeq>(Str $a, Str $b) { return ($a eq $b) ? $a : ''; }
> to be [corrected]:

> sub &infix:<myeq>(Str $a, Str $b)
> { return ($a eq $b) ?? $a but bool::true :: ''; }

Perhaps, but I don't know that it makes much difference for the
example given. I probably should've chosen a name other than "myeq"
so that we aren't fooling ourselves into believing we're returning
booleans when we're really returning strings that match.

Pm

Patrick R. Michaud

unread,
Apr 27, 2005, 1:18:07 PM4/27/05
to Thomas Sandlaß, perl6-l...@perl.org
On Wed, Apr 27, 2005 at 06:29:46PM +0200, Thomas Sandlaß wrote:
> Patrick R. Michaud wrote:
> >>my $matches = any( @x_chars ) eq any( @y_chars );
> >>my $match = $matches.pick;
> >
> >Perhaps the easiest way to explain the difficulty here is to note that
> >executing a relational op (i.e. returning a boolean) value on a junction
> >argument returns a junction of boolean values.
>
> Is that so? Does Perl6 have some fundamental law of junction preservation?
> I would expect $matches to be either false or true---the junction values
> are garbage collected.

I would certainly expect $matches to be false or true if the
expression was invoked in a boolean context, but I'm not certain
it can "auto-collapse" outside of that. In particular, we know that

$x = any(0, 1);
$y = $x + 1; # $y == any(1, 2)

so a slightly different formulation of this would be:

$w = any('a', 'b');
$x = $w eq 'b'; # $x == any(0, 1)
$y = $x + 1; # $y == any(1, 2)

I think the assignment to $x above shouldn't be collapsed directly
to a simple false or true value until it's evaluated in a boolean
context.

Pm

Rod Adams

unread,
Apr 27, 2005, 1:23:37 PM4/27/05
to perl6-l...@perl.org
Thomas Sandlaß wrote:

> Patrick R. Michaud wrote:
>
>> On Wed, Apr 27, 2005 at 08:46:53AM -0400, Joshua Gatcomb wrote:
>>
>>> The problem is that in the regex version I use capturing parens to
>>> identify the character matched. For the purposes of the problem I
>>> don't need to rely on the first character matched I just need to know
>>> 1.
>>>
>>> Without doing a lot of research into junctions, I thought the
>>> following would work:
>>>
>>> my $matches = any( @x_chars ) eq any( @y_chars );
>>> my $match = $matches.pick;
>>
>>
>>
>> Perhaps the easiest way to explain the difficulty here is to note that
>> executing a relational op (i.e. returning a boolean) value on a junction
>> argument returns a junction of boolean values.
>
>
> Is that so? Does Perl6 have some fundamental law of junction
> preservation?
> I would expect $matches to be either false or true---the junction values
> are garbage collected.

You're both right.

The junction of junctions of bools gets created from the threading...
and then gets collapsed into a single bool, based on the predicates.
("any" in all cases here).

>
>> ... or if it could "pick" one of the empty
>> string values.
>
>
> That's my understanding. The junctive value is lazily evaluating the
> list of all permutations from @x_chars and @y_chars one at a time.
> The myeq is called once for .pick and the result goes into $match.
>

I'm pretty sure the ".pick" would return one of the junctions of
chars/empty strings. You could do a ".pick.pick" to get a single result
back out. However, you'd be stuck with all the empty strings again. I
think you'd likely want something like

$matches.values».values.grep:{$_ ne ''}

but if you're going through that much trouble, just do:

@matches = @x_chars.grep:{$_ ~~ @y_chars};

and be done with it.

It's been established before that getting at _which_ values in a
junctions made the evaluation turn one way or the other is _not_
something that will be readily supported.

-- Rod Adams

Rod Adams

unread,
Apr 27, 2005, 4:30:30 PM4/27/05
to perl6-l...@perl.org
Luke Palmer wrote:

>Rod Adams writes:
>
>
>>>>Perhaps the easiest way to explain the difficulty here is to note that
>>>>executing a relational op (i.e. returning a boolean) value on a junction
>>>>argument returns a junction of boolean values.
>>>>
>>>>
>>>Is that so? Does Perl6 have some fundamental law of junction
>>>preservation?
>>>I would expect $matches to be either false or true---the junction values
>>>are garbage collected.
>>>
>>>
>>You're both right.
>>
>>The junction of junctions of bools gets created from the threading...
>>and then gets collapsed into a single bool, based on the predicates.
>>
>>
>

>Except that it doesn't. Not until it is evaluated in boolean context.
>
>any(0, 1) does not immediately collapse to 1. Without any other
>context, any(0, 1) means "any value which is either zero or one" and
>interprets the boolean value of nothing. You wouldn't expect perl to
>try to evaluate something as a boolean unless it's in some sort of
>boolean context, would you? The same holds for junctions.
>
>
Hmm. I was thinking that the "eq" made it boolean context, but you're
right, it doesn't collapse in this case.

>>It's been established before that getting at _which_ values in a
>>junctions made the evaluation turn one way or the other is _not_
>>something that will be readily supported.
>>
>>
>

>I don't think that's been established. I think that's been stated as a
>consequence of the current semantics. I don't see any linguistic reason
>why junctions /should not/ support that. It's just that they don't
>(right now).
>
>

I remember the topic coming up before during the "junction wars" of a
few months ago. It was one of those things that separated junctions from
sets in a rather dramatic way. And as you said, currently, they do not.

If you wish to propose syntax and semantics to make it happen, go for
it. But the way I see it, in order to make that happen, you'd have to
"remember" what value was threaded to generate each resulting value, and
have that essentially be a property of that value. Then the return of a
junction threading would be a rather more complex object, with possible
chaining of these properties, if the junction goes through several
iterations of evaluation. If you have that, it would be straightforward
to write functions that inspect these properties, and grep out what you
wanted.

My gut reaction though is that is gets expensive, and it seems odd to
support this "value history" on only junctions. For instance, if you do
"$x = isprime(4);", do you expect the resulting $x to have a property
saying it was "derived from 4"? That's a philosophical matter. It would
have some real nasty side effects on performance if done large scale,
but could prove invaluable for debugging and some specific problems.


I think that if you want to know what matched, you should be using
arrays and grep/map, not junctions.

-- Rod Adams

Luke Palmer

unread,
Apr 27, 2005, 2:21:34 PM4/27/05
to Rod Adams, perl6-l...@perl.org
Rod Adams writes:
> >>Perhaps the easiest way to explain the difficulty here is to note that
> >>executing a relational op (i.e. returning a boolean) value on a junction
> >>argument returns a junction of boolean values.
> >
> >
> >Is that so? Does Perl6 have some fundamental law of junction
> >preservation?
> >I would expect $matches to be either false or true---the junction values
> >are garbage collected.
>
> You're both right.
>
> The junction of junctions of bools gets created from the threading...
> and then gets collapsed into a single bool, based on the predicates.

Except that it doesn't. Not until it is evaluated in boolean context.

any(0, 1) does not immediately collapse to 1. Without any other
context, any(0, 1) means "any value which is either zero or one" and
interprets the boolean value of nothing. You wouldn't expect perl to
try to evaluate something as a boolean unless it's in some sort of
boolean context, would you? The same holds for junctions.

> It's been established before that getting at _which_ values in a

> junctions made the evaluation turn one way or the other is _not_
> something that will be readily supported.

I don't think that's been established. I think that's been stated as a


consequence of the current semantics. I don't see any linguistic reason
why junctions /should not/ support that. It's just that they don't
(right now).

Luke

Thomas Sandlaß

unread,
Apr 28, 2005, 11:49:18 AM4/28/05
to perl6-l...@perl.org
I wrote:
> permute( @x_chars ) »{ $^a eq $^b ?? $^a :: ''}« permute( @y_chars )

Permutation is the wrong thing here, sorry. It's just:

( @x_chars »xx« @y_chars.elems ) # or was that .size?


»{ $^a eq $^b ?? $^a :: ''}«

( @y_chars xx @x_chars.elems ) # note: no hypering

e.g. <a b c> and <x y> give <a a b b c c> »{...}« <x y x y x y>
and finally a list of six empty strings.

And look Mami, all without junctions!
Lots of french ... ehm, freedom quotes involved, though :)
--
TSa (Thomas Sandlaß)


Joshua Gatcomb

unread,
Apr 28, 2005, 12:08:10 PM4/28/05
to Thomas Sandlaß, perl6-l...@perl.org
On 4/28/05, Thomas Sandlaß <Thomas....@orthogon.com> wrote:
> I wrote:
> > permute( @x_chars ) »{ $^a eq $^b ?? $^a :: ''}« permute( @y_chars )
>
> Permutation is the wrong thing here, sorry. It's just:

I want to preface again that I have only recently started giving the
language aspect of p6 serious focus. Without doing any digging into
junctions and pretty much just listening to the buzz, I not only think
of things like being able to verify that a userid isn't on a
blacklist, I also think of the ability to do things like:

1. Give me all the items in list A that match any of the items in list B
2. Give me all the items in list A that aren't in list B
3. well - you get the idea

I don't want to have to invent some special purpose infix operation to
do it nor should do I believe it should require much thinking. That
doesn't mean it needs to be in the core. If not in the core, I think
it should be generalized and included in one of the first available
modules. FAQs such as union, difference, intersection of lists are
FAQs for a reason.

Of course, it is real easy for me to say "it should 'just work'" from
where I am sitting - you all are the ones that have done the hard
work. Having answered the questions enough times in p5 circles
though, it would be nice to have a real simple easy answer for p6.

Thomas Sandlaß

unread,
Apr 28, 2005, 12:24:45 PM4/28/05
to perl6-l...@perl.org
Joshua Gatcomb wrote:
> ... FAQs such as union, difference, intersection of lists are
> FAQs for a reason.
> ... it would be nice to have a real simple easy answer for p6.

And indeed it could be:

use Sets;

my @a is Set = (1,2,3);
my @b is Set = (2,3,4);

say @a + @b; # (1,2,3,4)
say @a / @b; # (2,3)

etc. Possibly with nice Unicode equivalents.
--
TSa (Thomas Sandlaß)

Reply all
Reply to author
Forward
0 new messages