Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raku zip operator & space

Tags:

raku

I found this one liner which joins same lines from multiple files. How to add a space between two lines?

If line 1 from file A is blue and line 1 from file B is sky, a get bluesky, but need blue sky.

say $_ for [Z~] @*ARGS.map: *.IO.lines;

like image 400
Jan Bodnar Avatar asked Sep 01 '21 14:09

Jan Bodnar


People also ask

What is the output of the @alphabet operator in raku?

*].raku; # OUTPUT: «("x", "y", "z")␤» @alphabet[1, 2] = "B", "C"; say @alphabet[0..3].raku; # OUTPUT: «("a", "B", "C", "d")␤» See Subscripts, for a more detailed explanation of this operator's behavior and for how to implement support for it in custom types.

What is precedence and associativity of Raku operators?

Operator precedence The precedence and associativity of Raku operators determine the order of evaluation of operands in expressions. Where two operators with a different precedence act on the same operand, the subexpression involving the higher-precedence operator is evaluated first.

How to check if an array is itemized in raku?

Check this: say .raku for [3,2,[1,0]]; # OUTPUT: «3␤2␤$[1, 0]␤» This array is itemized, in the sense that every element constitutes an item, as shown by the $preceding the last element of the array, the (list) item contextualizer.

Do non-infix operators have the same associativity in raku?

However, for operators built in to Raku, all operators with the same precedence level also have the same associativity. Setting the associativity of non-infix operators is not yet implemented. In the operator descriptions below, a default associativity of leftis assumed. Operator classification


2 Answers

This is using the side-effect of .Str on a List to add spaces between the elements:

say .Str for [Z] @*ARGS.map: *.IO.lines

The Z will create 2 element List objects, which the .Str will then stringify.

Or even shorter:

.put for [Z] @*ARGS.map: *.IO.lines

where the .put will call the .Str for you and output that.

If you want anything else inbetween, then you could probably use .join:

say .join(",") for [Z] @*ARGS.map: *.IO.lines

would put comma's between the words.

like image 139
Elizabeth Mattijsen Avatar answered Nov 05 '22 06:11

Elizabeth Mattijsen


Note: definitely don't do this in anything approaching real code. Use (one of) the readable ways in Liz's answer.

If you really want to use the same structure as [Z~] – that is, an operator modified by the Zip meta-operator, all inside the Reduce meta-operator – you can. But it's not pretty:

say $_ for [Z[&(*~"\x20"~*)]] @*ARGS.map: *.IO.lines

Here's how that works: Z can take an operator, so we need to give it an operator that concatenates two strings with a space in between. But there's no operator like that built in. No problem – we can turn any function into an infix operator by surrounding it with [ ] (the infix form).

So all we need is a function that joins two strings with a space between them. That also doesn't exist, but we can create one: * ~ ' ' ~ *. So, we should be able to shove that into our infix form and pass the whole thing to the Zip operator Z[* ~ ' ' ~ *].

Except that doesn't work. Because Zip isn't really expecting an infix form, we need to give it a hint that we're passing in a function … that is, we need to put our function into a callable context with &( ), which gets us to Z[&(* ~ ' ' ~ *)].

That Zip expression does what we want when used in infix position – but it still doesn't work once we put it back into the Reduce/[ ] operator that we want to use. This time, the problem is due to something that may or may not be a bug – even after discussing it with jnthn on github, I'm still not sure whether this behavior is intended/correct.

Specifically, the issue is that the Reduction meta-operator doesn't allow whitespace – even in strings. Thus, we need to replace * ~ ' ' ~ * with *~"\c[space]"~* or *~"\x20"~* (where \x20 is the hex value of in Unicode/ASCII). Since we've come this far into obfuscated code, I figure we might as well go all the way. And that gets us back to

say $_ for [Z[&(*~"\x20"~*)]] @*ARGS.map: *.IO.lines

Again, I'm not recommending that you do this. (And, if you do, you could at least make it slightly more readable by saving the * ~ ' ' ~ * function as a named variable in the previous line, which at least gets you whitespace. But, really, just use one of Liz's suggestions).

I just thought this gives a useful window into some of the darker and more interesting corners of Raku's strangely consistent behavior.

like image 31
codesections Avatar answered Nov 05 '22 07:11

codesections