Not So Obvious Semantic Changes (Part 3 of 3)
Tags: perl, rakulang, programming, migration
Published: 2023-08-10 07:30:00

## No Return Context in Raku
In Perl, a subroutine can determine in what context it is being called by using the `wantarray` function.  Available contexts are `scalar`, `list` and `void`:
```
# Perl
sub say_context {
    say wantarray
      ? "list"
      : defined(wantarray)
        ? "scalar"
        : "void";
}
my $a = say_context();  # scalar
my @b = say_context();  # list
say_context();          # void
```
In Raku, there is no such thing a caller's context.  A subroutine (well, technically any block) only ever returns a **single** value.  Such a value may well be a [`List`](https://docs.raku.org/type/List), or any other object.

So you *can* simulate returning multiple values in Raku:
```
# Raku
sub return-scalar() { 42 }
sub return-list() { 42,666 }  # note the comma makes the list

my $a = return-scalar;
say $a;    # 42
my ($b,$c) = return-list;     # unpack list into variables
say $b;    # 42
say $c;    # 666
```
But you should realise that it is in fact a single `List` that is being returned by `return-list`, that will be unpacked into `$b` and `$c`.

Simulating `void` context is possible in a way in Raku, but it requires returning an object that has a specific [`sink`](https://docs.raku.org/syntax/sink%20context) method defined for it.  And that goes beyond the scope of these blog posts.

## Just Saying
In Perl, using the `print` command will stringify the given value and send this to standard output.  The `say` command will add a newline after that.

In Raku, there are basically 3 methods with which an object can be stringified: `Str`, `gist` and `raku`.  The `Str` method is supposed to return a complete stringification of the given expression.  The `gist` method is intended to provide a gist of the stringification of the given expression.  For small objects, this is usually the same as the `Str` method.  For bigger objects, the `gist` method is at liberty to drop information, or to summarise it.

The `raku` method provides basically a built-in `Data::Dumper`: the method is supposed to return a string that can be evaluated to re-create the given object.  This is of course not always 100% possible, but all effort should be taken to make it roundtrip.

So given these methods, how do these relate to outputting strings?  Well, the `print` command in Raku basically works like the `print` command in Perl: it calls the `Str` method on the given expression and sends that to standard output.

The `say` command in Perl merely adds a newline to the stringification of the expression:
```
# Perl
say $frobnicated;  # stringify and send to STDOUT with newline
```
In Raku, the `say` command first calls the `gist` method (rather than the `Str` method), and adds a newline.
```
# Raku
say $frobnicated;  # call method .gist and send to STDOUT with newline
```
In Raku, if you want to have the standard stringification happen when outputting to standard output, you can either call the `Str` method on the expression explicitly, or you can prefix the expression with a [`~`](https://docs.raku.org/language/operators#prefix_~), or you can use the `put` command:
```
# Raku
say $frobnicated.Str;  # explicit standard stringification
say ~$frobnicated;     # prefix ~ is same as .Str
put $frobnicated;      # implicit standard stringification
```
Additionally, Raku has a `note` command, that functions the same as `say`, but will send the output to standard error:
```
# Raku
note $frobnicated;  # call method .gist and send to STDERR with newline
```
Which is similar to:
```
# Perl
say STDERR $frobnicated;
```
except that method `gist` is called rather than the standard stringification.

The Rakudo implementation of the Raku Programming Language also includes a tiny `Data::Dumper` facility, so tiny it lost the t: [`dd`](https://docs.raku.org/programs/01-debugging#Dumper_function_(dd)).  This basically calls the `raku` method on the given expression, and prints that, with possibly some extra information, on standard error:
```
# Raku
dd "foo";       # "foo"
dd 5+42i;       # <5+42i>
dd now;         # Instant.from-posix(1691224400.111166001)
dd Date.today;  # Date.new(2023,8,5)
my Int $a = 42;
dd $a;          # Int $a = 42
```
Note that this feature is purely intended to facilitate debugging, and should probably not be used in any code running in production.

## Always Expression between Curlies
In Raku, something between curly braces (`{ }`) is *always* an expression, no matter where it occurs.  This applies to indexing into a hash, where this differs in semantics from Perl:
```
# Perl
%hash{a} = 42;
# the bareword "a" interpreted as a string
```
Whereas in Raku, everything between curly braces is an expression, so:
```
# Raku
%hash{a} = 42;
# bareword "a" interpreted as a call to subroutine "a"
```
Fortunately, if that subroutine does not exist in that lexical scope, there will be a compilation error that will be very clear:
```
# Raku
%hash{a} = 42;
# ===SORRY!=== Error while compiling …
Undeclared routine:    a
used at line …
```
For all other normal code uses (`if`, `for`, `while`, etc.), the curly braces act the same in Perl and Raku.

However in Raku, they can also be used inside double quoted strings:
```
# Raku
my $a = 42;
my $b = 666;
say "The sum of $a and $b is { $a + $b }";
# The sum of 42 and 666 is 708
```
Which is a lot more consistent and a lot less line-noisy than the equivalent in Perl using `@{[  ]}`:
```
# Perl
my $a = 42;
my $b = 666;
say "The sum of $a and $b is @{[ $a + $b ]}";
# The sum of 42 and 666 is 708
```
## Summary
This blog post elaborated on the absence of context in Raku, the subtle semantic differences between `say` and friends, and the fact that the contents of curlies are *always* an expression in Raku.