Wow, that's a very comprehensive explanation. I've just found out that I couldn't even comprehend the first reduction operator. I was thinking it was doing some magic operations. All it did was enable the cross op to act on the 2 lists without having to be  between   them. As simple as that. And surely I mis-took the second bracket as a second reduction. Now it's clear that it's for Nesting of metaoperators  Actually I was guessing this fine detail must have been documented in the Raku docs but I hadn't the faintest idea how to search for it in the huge docs of Raku :)
 
The custom operator definition to separate the Cross from the Op is very welcome too. I haven't written any custom op in Raku so far and it's good to see it in action.
 
Thank you for your time. Very much appreciated.


11.10.2020, 21:31, "Bruce Gray" <robertbrucegr...@gmail.com>:

NOTE: 30 minutes from now is the start of the Raku Study Group of the San Francisco Perl Mongers.
We can offer a "deep dive" into how the Leyland code works, if that would be helpful.
Zoom details here: https://mail.pm.org/pipermail/sanfrancisco-pm/2020-October/004726.html


 On Oct 11, 2020, at 10:39 AM, Cezmi Pastirma <cezmisi...@yandex.com> wrote:
 
 I've got a question about a Leyland-numbers-listing Raku code which I saw at codegolf.stackexchange.com at https://codegolf.stackexchange.com/a/83013/98132
  
 I've slightly rearranged the code to make it print Leyland numbers up to 1 Billion:
 .say for grep {$_ < 1E11}, squish(sort [X[&({$^a**$^b+$b**$a})]] 2..32,2..32)
  
 The question in short is:
  
 How does the cross reduce work there?


The reduction is a red herring to our understanding here.
Note that, when you are only [reducing] on two lists, `[any_op_here] @a, @b` is the same as `@a any_op_here @b`.
These are equivalent:
        say [X+] 2..4, 1..5;
        say 2..4 X+ 1..5;
The operator need not be a meta-operator:
        say [*] 3, 5;
        say 3 * 5;

 Extra info:
  
 That cross reduce section surely does what this half-pseudo code tries to do:
 map { $^a ** $^b + $b ** $a }, 2..32,32…2


If @c has 20 elements, and @d has 30 elements, then `@c X+ @d` has 600 elements.
You cannot produce the equivalent with a simple `map`.
(You could with a flattened map-within-a-map)


Simplifying your "slightly rearranged” code:
        .say for grep {$_ < 1E11}, squish(sort [X[&({$^a**$^b+$b**$a})]] 2..32,2..32)

...to just the part you are curious about, we get:
        say [X[&({$^a**$^b+$b**$a})]] 2..4,2..4;
                (8 17 32 17 54 145 32 145 512)

We are only [reducing] on two lists, so we can remove the reduction, and just use the Xop:
        say 2..4 X[&({$^a**$^b+$b**$a})] 2..4;
                (8 17 32 17 54 145 32 145 512)


 The tricky part here is the use of reduce operators two times in a row, once before the cross operator, once before the & operator, which I guess donates a closure. How to interpret this usage of operators?
  


The square brackets after the X, I think you mis-took as a second reduction.

Those brackets are just there to disambiguate the `op` that the `X` is crossing on.
    See: https://docs.raku.org/language/operators#Nesting_of_metaoperators

These are equivalent:
    .say for ^2 X+ ^2;
    .say for ^2 X[+] ^2;


We can create our own operator, to further separate the Cross from the Op:
        multi infix:<⨁> ($a, $b) {
                   $a ** $b
                + $b ** $a
        };
        say 2 ⨁ 3;
        say 2..4 X⨁ 2..4;
                17
                (8 17 32 17 54 145 32 145 512)

The `X` itself is the operator-form of the `cross` routine, well-documented here:
        https://docs.raku.org/routine/cross
        https://docs.raku.org/language/operators#index-entry-X_(cross_metaoperator)
        https://docs.raku.org/language/operators#index-entry-cross_product_operator

If any part of this was lacking in clarity, please let me know where to focus, and I will be glad to expound.

--
Hope this helps,
Bruce Gray (Util of Perlmonks)

Reply via email to