Dave Whipp wrote:

> When this issue has been raised in the past, the response has been that
> junctions are not really intended to be useful outside of the narrow purpose
> for which they were introduced.

Hmmmmmm. There are intentions, and then there are intentions. I know
what I intended when I invented the original idea, and it wasn't just the narrow
purpose for which they were added to Perl 6. :-)


>> Problem 2 could be solved by defining a new (and public!)
>> C<.eigenstates> method in the Junction class. [...]
>
> I think that you're proposed solution is a bit too specific:

That's because I didn't explain Part B of my nefarious plan! namely
that, if you'd only give me proper eigenstates, I'd give you an even
nicer alternative.

I actually think that the "meta" doesn't belong on the operator at all
(though I have no problem with that idea in itself).

Instead, I think the "meta" should be placed on the data (which, of
course, is what any(), all(), one(), and none() already do).

So I'm going to go on to propose that we create a fifth class of
Junction: the "transjunction", with corresponding keyword C<every>.

Then we define:

    every(@list)  <comparision-op>  <value>
    every($junction) <comparision-op>  <value>

to mean repectively:

    grep  * <comparision-op> <value>,  @list;
    grep  * <comparision-op> <value>,  $junction.eigenstates;

as well as the reverses:

    <value> <comparision-op> every(@list)
    <value> <comparision-op> every($junction)

to mean respectively:

    grep  <value> <comparision-op> *,  @list;
    grep  <value> <comparision-op> *,  $junction.eigenstates;


So then we get:

>>     sub factors (Num $n) { ( $n/any(1..$n) ).eigenstates.grep({ $^q.Int == 
>> $q }); }
>
> [which] could be:
>
> sub factors (num $n) { ^$n G[==] $n/any(1..$n) }

could instead be:

    sub factors (Num $n) {
         every( $n/any(1..$n) ) ~~ { $^q.Int == $q });
         # Every quotient of N divided by any lesser integer, where
the quotient is also an integer
    }


and:

>>        say UNACCEPTABLE.eigenstates¬».fmt("\t%s\n");
>
> [which] could be
>
>      say (::Str G[eq] UNACCEPTABLE)».fmt("\t%s\n")

could also be:

        say (every(UNACCEPTABLE) ~~ ::Str)».fmt("\t%s\n")
        # Everything unacceptable that's a string, formatted as follows...


> Operations other than equality could be used:
>
> say (^10 G[<] one(3,7));
>> 3 4 5 6

which could also be:

    say every(^10) < one(3,7);
    # Every value up to 10 that's greater than 3 or 7 but not both

And so on:

    say every(factor_of($x) & factor_of($y)) > 10;
    # Every common factor of both X and Y that's greater than 10

    say every(@coefficient) ~~ 0..1;
    # Every coefficient in the range 0 to 1

    say every(@string) ~~ /<target>/;
    # Every string that matches the target pattern

I just think those all read much better than the (otherwise excellent)
meta-operator. In much the same way that the existing junctive types
read better than their functional or operator-oriented alternatives.

I'd like these in the core language (for performance and universal
accessibility), but if not, I already have a nearly-complete
implementation of a module implementing them, which runs successfully on
the current release of Rakudo*. I append said model for your amusement
(and suggestions!).

Damian

-----cut----------cut----------cut----------cut----------cut----------cut----------cut----------cut-----

module Transjunctions;

# Add missing public method (and equivalent function) to junctions
#  Call them .eigenvalues(), so as not to clash with existing misnamed
!eigenstates()...
use MONKEY_TYPING;
augment class Junction {
    method eigenvalues (Junction $j:) {
        my @values = $j.eigenstates;
        @values .= map({ $^val.?eigenstates // $^val }) while
@values.grep(Junction);
        return uniq(@values).grep($j) does ::Transjunction;
    }

    sub eigenvalues (Junction $j) is export { $j.eigenvalues }
}


# Transjunctions are just lists that autofilter when matched...
role Transjunction {
    method ACCEPTS (Mu $filter) { self.grep($filter) }
}


# Convenient functions to build transjunctions...
multi sub every (*...@list is copy) returns Transjunction is export {
    return @list does Transjunction;
}

multi sub every (Junction $j) is export {
    return eigenvalues($j) does Transjunction;
}


# Comparing against a transjunction filters it with the comparison
# Rakudo star seems to require we provide two versions, though
# I had expected the Mu version ought to handle both Junctions and Anys...
multi sub infix:«<»  (Transjunction $list, Mu $n) is export
    { $list.grep( * <  $n ) does Transjunction }
multi sub infix:«<»  (Transjunction $list,    $n) is export
    { $list.grep( * <  $n ) does Transjunction }
multi sub infix:«>»  (Transjunction $list, Mu $n) is export
    { $list.grep( * >  $n ) does Transjunction }
multi sub infix:«>»  (Transjunction $list,    $n) is export
    { $list.grep( * >  $n ) does Transjunction }
multi sub infix:«<=» (Transjunction $list, Mu $n) is export
    { $list.grep( * <= $n ) does Transjunction }
multi sub infix:«<=» (Transjunction $list,    $n) is export
    { $list.grep( * <= $n ) does Transjunction }
multi sub infix:«>=» (Transjunction $list, Mu $n) is export
    { $list.grep( * >= $n ) does Transjunction }
multi sub infix:«>=» (Transjunction $list,    $n) is export
    { $list.grep( * >= $n ) does Transjunction }
multi sub infix:«==» (Transjunction $list, Mu $n) is export
    { $list.grep( * == $n ) does Transjunction }
multi sub infix:«==» (Transjunction $list,    $n) is export
    { $list.grep( * == $n ) does Transjunction }
multi sub infix:«!=» (Transjunction $list, Mu $n) is export
    { $list.grep( * != $n ) does Transjunction }
multi sub infix:«!=» (Transjunction $list,    $n) is export
    { $list.grep( * != $n ) does Transjunction }
multi sub infix:«lt» (Transjunction $list, Mu $n) is export
    { $list.grep( * lt $n ) does Transjunction }
multi sub infix:«lt» (Transjunction $list,    $n) is export
    { $list.grep( * lt $n ) does Transjunction }
multi sub infix:«gt» (Transjunction $list, Mu $n) is export
    { $list.grep( * gt $n ) does Transjunction }
multi sub infix:«gt» (Transjunction $list,    $n) is export
    { $list.grep( * gt $n ) does Transjunction }
multi sub infix:«le» (Transjunction $list, Mu $n) is export
    { $list.grep( * le $n ) does Transjunction }
multi sub infix:«le» (Transjunction $list,    $n) is export
    { $list.grep( * le $n ) does Transjunction }
multi sub infix:«ge» (Transjunction $list, Mu $n) is export
    { $list.grep( * ge $n ) does Transjunction }
multi sub infix:«ge» (Transjunction $list,    $n) is export
    { $list.grep( * ge $n ) does Transjunction }
multi sub infix:«eq» (Transjunction $list, Mu $n) is export
    { $list.grep( * eq $n ) does Transjunction }
multi sub infix:«eq» (Transjunction $list,    $n) is export
    { $list.grep( * eq $n ) does Transjunction }
multi sub infix:«ne» (Transjunction $list, Mu $n) is export
    { $list.grep( * ne $n ) does Transjunction }
multi sub infix:«ne» (Transjunction $list,    $n) is export
    { $list.grep( * ne $n ) does Transjunction }

# Arguments to comparator can be either way round...
multi sub infix:«<»  (Mu $n, Transjunction $list) is export
    { $list.grep( $n <  * ) does Transjunction }
multi sub infix:«<»  (   $n, Transjunction $list) is export
    { $list.grep( $n <  * ) does Transjunction }
multi sub infix:«>»  (Mu $n, Transjunction $list) is export
    { $list.grep( $n >  * ) does Transjunction }
multi sub infix:«>»  (   $n, Transjunction $list) is export
    { $list.grep( $n >  * ) does Transjunction }
multi sub infix:«<=» (Mu $n, Transjunction $list) is export
    { $list.grep( $n <= * ) does Transjunction }
multi sub infix:«<=» (   $n, Transjunction $list) is export
    { $list.grep( $n <= * ) does Transjunction }
multi sub infix:«>=» (Mu $n, Transjunction $list) is export
    { $list.grep( $n >= * ) does Transjunction }
multi sub infix:«>=» (   $n, Transjunction $list) is export
    { $list.grep( $n >= * ) does Transjunction }
multi sub infix:«==» (Mu $n, Transjunction $list) is export
    { $list.grep( $n == * ) does Transjunction }
multi sub infix:«==» (   $n, Transjunction $list) is export
    { $list.grep( $n == * ) does Transjunction }
multi sub infix:«!=» (Mu $n, Transjunction $list) is export
    { $list.grep( $n != * ) does Transjunction }
multi sub infix:«!=» (   $n, Transjunction $list) is export
    { $list.grep( $n != * ) does Transjunction }
multi sub infix:«lt» (Mu $n, Transjunction $list) is export
    { $list.grep( $n lt * ) does Transjunction }
multi sub infix:«lt» (   $n, Transjunction $list) is export
    { $list.grep( $n lt * ) does Transjunction }
multi sub infix:«gt» (Mu $n, Transjunction $list) is export
    { $list.grep( $n gt * ) does Transjunction }
multi sub infix:«gt» (   $n, Transjunction $list) is export
    { $list.grep( $n gt * ) does Transjunction }
multi sub infix:«le» (Mu $n, Transjunction $list) is export
    { $list.grep( $n le * ) does Transjunction }
multi sub infix:«le» (   $n, Transjunction $list) is export
    { $list.grep( $n le * ) does Transjunction }
multi sub infix:«ge» (Mu $n, Transjunction $list) is export
    { $list.grep( $n ge * ) does Transjunction }
multi sub infix:«ge» (   $n, Transjunction $list) is export
    { $list.grep( $n ge * ) does Transjunction }
multi sub infix:«eq» (Mu $n, Transjunction $list) is export
    { $list.grep( $n eq * ) does Transjunction }
multi sub infix:«eq» (   $n, Transjunction $list) is export
    { $list.grep( $n eq * ) does Transjunction }
multi sub infix:«ne» (Mu $n, Transjunction $list) is export
    { $list.grep( $n ne * ) does Transjunction }
multi sub infix:«ne» (   $n, Transjunction $list) is export
    { $list.grep( $n ne * ) does Transjunction }

# These should be infix:<~~>, but that doesn't seem to work (yet?)
# And I can't find any other way to let the every(...) come before the ~~
# (suggestions most welcome!)
multi sub infix:<:~~> (Transjunction $list, Mu $filter) is export
    { $list.grep($filter) does Transjunction }
multi sub infix:<:~~> (Transjunction $list,    $filter) is export
    { $list.grep($filter) does Transjunction }

Reply via email to