22

I find that a huge selling point for scripting addicts to join raku would be having such constructs possible

my $w = "Hello world";

$w
  ~~ s/Hello/Hola/
  ~~ s/world/mundo/
  ;

say $w; # » Hola world

However I don't seem to be able to write something like this. As far as I know doing this with the .subst method of Str would be too ugly, and this chaining of s/// or even also tr/// basically would be a gateway drug for sed users etc.

My question is if I'm missing something, if something remotely similar to this is possible somehow in raku. I'm not a beginner and I could not figure it out.

margolari
  • 651
  • 3
  • 11
  • 2
    `$w .= subst(/Hello/, 'Hola') .= subst(/world/, 'mundo');` is the closest I could get to. But I guess you could call that too ugly. Perhaps something with [replace-with](https://docs.raku.org/routine/replace-with) ? – Elizabeth Mattijsen Nov 29 '20 at 23:55
  • Ok, I guess it's what I thought. I wanted to write a blog post where I show awk, sed, tr and python users that they can get all this in a `similar` syntax all together in raku, and the part for `awk` it is really very close to raku, so it breaks my heart that I can't do the same for `sed` ;) – margolari Nov 30 '20 at 00:09

2 Answers2

25

You could use with or given

with $w {
    s/Hello/Hola/;
    s/world/mundo/;
}

andthen

$w andthen  s/Hello/Hola/ && s/world/mundo/;

or this ugly construction

$_ := $w;
s/Hello/Hola/;
s/world/mundo/;
grg
  • 5,023
  • 3
  • 34
  • 50
wamba
  • 3,883
  • 15
  • 21
  • 4
    Using the with, you could also do a post fix to avoid the brackets: `s/Hello/Hola/ && s/world/mundo/ with $w`. – user0721090601 Nov 30 '20 at 03:37
  • 1
    I'm not sure why, but trying the `with` and `given` clauses did not work before for me, but now it does, I guess I made some silly mistake somewhere. This is awesome, this is exactly what I wanted – margolari Nov 30 '20 at 12:16
  • 2
    specially, then the following works `echo hello world | raku -ne 's/hello/hola/; s/world/mundo/; .say' ` which is just a selling point that gets understressed in the raku community, imho – margolari Nov 30 '20 at 12:17
  • 1
    `~$ echo "Hello world" | raku -pe 's/Hello/Hola/; s/world/mundo/;'` #Hola mundo – jubilatious1 Nov 30 '20 at 22:37
  • 2
    @margolari jubilatious1's suggestion is great if you can hoist the value to the main topic. But if not, you can shave off a few more characters by using the reduction operator: `[&&] s///,s///,s///,… with $foo`. – user0721090601 Dec 01 '20 at 19:11
  • This is very cool, I did not know this, I'll put this in my blog and post it on reddit. I did not know exactly what is the Type of a `s///` expression, that is why I didn't quite not how to `mconcat` or to reduce it – margolari Dec 01 '20 at 20:18
7

Some excellent answers so far (including comments).

Utilizing Raku's non-destructive S/// operator is often useful when doing multiple (successive) substitutions. In the Raku REPL:

> my $w = "Hello world";
Hello world
> given $w {S/Hello/Hola/ andthen S/world/mundo/};
Hola mundo
> say $w;
Hello world

Once you're happy with your code, you can assign the result to a new variable:

> my $a = do given $w {S/Hello/Hola/ andthen S/world/mundo/};
Hola mundo
> say $a
Hola mundo

Taking this idea a little further, I wrote the following 'baby Raku' translation script and saved it as Bello_Gallico.p6. It's fun to run!

my $caesar = "Gallia est omnis divisa in partes tres";
my $trans1 = do given $caesar {
 S/Gallia/Gaul/ andthen
 S/est/is/ andthen
 S/omnis/a_whole/ andthen
 S/divisa/divided/ andthen
 S/in/into/ andthen
 S/partes/parts/ andthen
 S/tres/three/ 
};
put $caesar;
put $trans1;

HTH.

https://docs.raku.org/language/regexes#S///_non-destructive_substitution

jubilatious1
  • 1,999
  • 10
  • 18
  • 2
    this is also very useful, and looks nice `sedish` too! – margolari Nov 30 '20 at 17:54
  • @margolari Thank you! For some reason syntax-highlighting isn't working in my browser...hopefully it is in yours...or someone can edit to correct. – jubilatious1 Nov 30 '20 at 18:01
  • 1
    @margolari just like I showed with the wamba's, with this one, because `andthen` is a infix operator and not a control word, you can also do `my $trans1 = [andthen] S///, S///, S/// … with $caesar` to be non-destructive :-) – user0721090601 Dec 01 '20 at 20:58
  • @user0721090601 Very clever! Your code worked perfectly. However I tried using `reduce &infix:,` to substitute for `[andthen]` as per the reduction metaoperator Docs page, and it didn't work. Any thoughts? See: https://docs.raku.org/language/operators#index-entry-[]_(reduction_metaoperators) – jubilatious1 Jan 01 '21 at 17:30