DEV Community

Myoungjin Jeon
Myoungjin Jeon

Posted on

Power of [X]

Meanwhile I was writing Weekly Challenge #083 Task #2
...

> [X] (1,2,3).map( -> $n { $n, -$n } )
((1 2 3) (1 2 -3) (1 -2 3) (1 -2 -3) (-1 2 3) (-1 2 -3) (-1 -2 3) (-1 -2 -3))
Enter fullscreen mode Exit fullscreen mode

And I'd like to mention that how powerful this is!!!

Yet Another Permutation Story

Or if you want to see a separate flipping data we could write like below

> (1,-1) X (1,-1) X (1,-1)
((1 1 1) (1 1 -1) (1 -1 1) (1 -1 -1) (-1 1 1) (-1 1 -1) (-1 -1 1) (-1 -1 -1)
Enter fullscreen mode Exit fullscreen mode

OR

> [X] (1,-1) xx 3
((1 1 1) (1 1 -1) (1 -1 1) (1 -1 -1) (-1 1 1) (-1 1 -1) (-1 -1 1) (-1 -1 -1))
Enter fullscreen mode Exit fullscreen mode

So, we want to make -12, 2, 10 from (-1,1,1), it could be done like..

> (12,2,10) Z* (-1,1,1)
(-12 2 10)
Enter fullscreen mode Exit fullscreen mode

"[X]" is a magic! because if you want to write a subroutine does the similar task, it wasn't very happy as I introduced in Here before.

shell> cat p.raku
sub p ($len) {
    if $len == 0 { () }
    elsif $len == 1 { (1,-1) }
    else { ((1,-1) X p($len.pred).List).map(*.flat.cache) }
}

p(3).say;
shell> raku p.raku
((1 1 1) (1 1 -1) (1 -1 1) (1 -1 -1) (-1 1 1) (-1 1 -1) (-1 -1 1) (-1 -1 -1))
Enter fullscreen mode Exit fullscreen mode

πŸ“– .pred
πŸ“– .flat

If you are familiar with pattern matching in Haskell or multi method in other language previous p() can be written like this

multi sub p(0) { () }
multi sub p(1) { (1,-1) }
multi sub p ($len) {
    (p(1) X p($len.pred).List).map(*.flat.cache)
}

p(3).say;
Enter fullscreen mode Exit fullscreen mode

How about that? It's only preference problem but I can see that it will help you to make a code in manageable size πŸ˜„
And I'd like to mention that .cache and .List !!!
For saving your time, I'll summarise like below.

  1. when you are using a List or an Array returned from a subroutine and want to use on the fly, you'd better use .List; (because what you get is itemized value which is scalar. πŸ“–) or save it into another List or another Array
  2. When you return any object in subroutine and you think it's going to be used in another Sequences, you'd better return as .cache!

otherwise you'll get something like this message

... snip ...
multi sub p ($len) {
    (p(1) X p($len.pred).List).map(*.flat)
}
p(3).say;
Enter fullscreen mode Exit fullscreen mode
The iterator of this Seq is already in use/consumed by another Seq
(you might solve this by adding .cache on usages of the Seq, or
by assigning the Seq into an array)
  in block <unit> at test.raku line 7
Enter fullscreen mode Exit fullscreen mode

Zip🀐

Now we have a series of sequences, we can get flipped values
We might be familiar with zip in other language and Raku as Z operator

shell>  tail -n 5 p.raku
my @ex1 = (12, 2, 10);
p(3).map( -> \flipRule {
                flipRule Z* @ex1
            }
        ).say;
shell> raku p.raku
((12 2 10) (12 2 -10) (12 -2 10) (12 -2 -10) (-12 2 10) (-12 2 -10) (-12 -2 10) (-12 -2 -10))
Enter fullscreen mode Exit fullscreen mode

Power of [X]

Now you can see how powerful [X] is !!!

> [X] (1,2,3).map( -> $n { $n, -$n } )
((1 2 3) (1 2 -3) (1 -2 3) (1 -2 -3) (-1 2 3) (-1 2 -3) (-1 -2 3) (-1 -2 -3))
Enter fullscreen mode Exit fullscreen mode

And We are going back to Original article πŸ›«

Top comments (0)