Power of [X]
Tags: raku, productivity
Published: 2020-10-21 05:53:58

  *Meanwhile I was writing [Weekly Challenge #083 Task #2](/jeongoon/weekly-challenge-083-task-2-raku-2cjm)*
...

```perl
> [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))
```
  *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)
```
  OR

```perl
> [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))
```

  So, we want to make -12, 2, 10 from (-1,1,1), it could be done like..
```perl
> (12,2,10) Z* (-1,1,1)
(-12 2 10)
```
  "[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] (/jeongoon/weekly-challenge-081-task-2-elm-raku-p92#permutation) before.

```perl
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))
```
📖 *[.pred](https://docs.raku.org/routine/pred)*
📖 *[.flat](https://docs.raku.org/routine/flat)*

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

```perl
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;
```
  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*](https://docs.raku.org/routine/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. [📖](https://docs.raku.org/language/mop#index-entry-is_itemized%3F)) 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](https://docs.raku.org/language/list#Sequences)*, you'd better return as .cache!

  otherwise you'll get something like this message
```perl
... snip ...
multi sub p ($len) {
    (p(1) X p($len.pred).List).map(*.flat)
}
p(3).say;
```
```
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
```

## **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*](https://docs.raku.org/language/operators#index-entry-Z_(zip_metaoperator))

```perl
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))
```

# **Power of [X]**

Now you can see how powerful [X] is !!!
```perl
> [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))
```

### *And We are going back to [Original article](/jeongoon/weekly-challenge-083-task-2-raku-2cjm)* 🛫