11

When I run this script in Raku I get the letter A with several newlines. Why do I not get the concatenated strings as expected (and as Perl5 does) ?

EDIT BTW can I compile in commaIDE the file with the Perl5 compiler, where can I change this compiler to be that of Perl5 ?

say "A";

my $string1  = "00aabb";
my $string2  = "02babe";

say join ("A", $string1, $string2);
print "\n";

my @strings = ($string1, $string2);

say join ("A", @strings);
print "\n";
user2925716
  • 949
  • 1
  • 6
  • 13
  • 1
    "can I compile in commaIDE the file with the Perl5 compiler, where can I change this compiler to be that of Perl5?" Comma is a Raku specific IDE. It won't be able to use other PLs like Perl or Python etc the same way as Raku. That said, perhaps things can be set up so it can easily invoke external scripts such as compilers for other PLs. Either way, I recommend you ask about this aspect as a new separate SO Question to bring suitable attention to it. – raiph May 31 '21 at 21:34
  • 2
    Comma is also available as a plugin for any IntelliJ JetBrains IDE version ... there is also a perl plugin https://plugins.jetbrains.com/plugin/7796-perl – librasteve Jun 08 '21 at 21:15

4 Answers4

11

The problem is the whitespace after the function name. If you leave a space there, raku will treat the expression in paranthesis as a List which is single thing. Here join will think you want to use the list as a joiner.

Observe:

>raku -e "sub foo( $arg ) { say $arg.WHAT }; foo( 'abc', )"
(Str)

>raku -e "sub foo( $arg ) { say $arg.WHAT }; foo ( 'abc', )"
(List) 

So in short, if you want to use paranthesis to call a sub, don't put a whitespace between the sub name and the opening paren.

Holli
  • 5,072
  • 10
  • 27
11

The solution I suggest is to drop the parens:

say "A";

my $string1  = "00aabb";
my $string2  = "02babe";

say join "A", $string1, $string2;     # Pass THREE arguments to `join`, not ONE
print "\n";

my @strings = $string1, $string2;

say join "A", @strings;
print "\n";

(The elements in @strings in the second call to join are flattened, thus acting the same way as the first call to join.)

The above code displays:

A
00aabbA02babe

00aabbA02babe

When I run this script in Raku I get the letter A with several newlines.

Your code calls join with ONE argument, which is the joiner, and ZERO strings to concatenate. So the join call generates null strings. Hence you get blank lines.

Why do I not get the concatenated strings

The two say join... statements in your code print nothing but a newline because they're like the third and fourth say lines below:

say join(  " \o/ ", "one?", "two?" ); # one? \o/ two?␤

say join   " \o/ ", "one?", "two?"  ; # one? \o/ two?␤

say join ( " \o/ ", "one?", "two?" ); # ␤

say join(  " \o/  one? two?"       ); # ␤

The first and second lines above pass three strings to join. The third passes a single List which then gets coerced to become a single string (a concatenation of the elements of the List joined using a single space character), i.e. the same result as the fourth line.


The my @strings = ($string1, $string2); incantation happens to work as you intended, because an assignment to a "plural" variable on the left hand side of the = will iterate the value, or list of values, on the right hand side.

But it's a good habit in Raku to err on the side of avoiding redundant code, in this instance only using parens if you really have to use them to express something different from code without them. This is a general principle in Raku that makes code high signal, low noise. For your code, all the parens are redundant.

raiph
  • 31,607
  • 3
  • 62
  • 111
  • 2
    Given that this is the accepted answer, it may be worth saying up front that the whitespace between sub name and paren is significant. – donaldh Jun 01 '21 at 18:16
  • 2
    Thx @donaldh. That's what I meant by "(with no space between the end of the name and the opening paren)" but I've already concluded my answer is sloppy in several ways that I hope to fix tomorrow, and actual code is always better for that sort of thing than prose, so I'll add code to clarify that and/or link to Holli's answer. – raiph Jun 01 '21 at 22:14
9

see Traps to avoid, try:

my @s=("00aabb", "02babe");

say join "A", @s;
say join |("A",@s);
say join("A",@s);
say @s.join: "A";

#or some crazy
say join\ ("A",@s);
say "A".&join: @s;
say join @s: "A";
say "A" [&join] @s;
say @s R[&join] "A";
#…
wamba
  • 3,883
  • 15
  • 21
3

A: "do not put whitespace between a function name and the opening paren '('" ♎️KISS

librasteve
  • 6,832
  • 8
  • 30