13

Raku sigils denote the nature of the underlying variable (e.g., $scalar, @positional, %associative, &code).

It's possible to declare a variable as sigil-less with a backslash (e.g., \some-variable) and then later refer to it without a sigil (i.e., some-variable).

Just wondering in what circumstance it's preferred to use a sigil-less variable?

user2145475
  • 657
  • 3
  • 11

2 Answers2

11

Declarations of the form my \a = expr introduce an alias a to the expression expr without enforcing any kind of context on it, as assignment into a sigiled variable would. Thus their primary use is when you don't want to have any of the semantics associated with any sigil.

Personally, I use them most when I am building up lazy processing pipelines and want to name the parts. As a simple example:

my $fh = open 'somefile';
my \no-comments = $fh.lines.grep({ not /^\s*'#'/ });
for no-comments -> $sig-line {
    ...
}

A grep returns a Seq that, if iterated, will perform the operation. If I were to instead use an @-sigil variable:

my $fh = open 'somefile';
my @no-comments = $fh.lines.grep({ not /^\s*'#'/ });
for @no-comments -> $sig-line {
    ...
}

Then while the results would be the same, the memory performance would be very different: assignment is eager unless it encounters something explicitly marked lazy, and so this would store all the non-comment lines into @no-comments and then iterate over them. Thus all those lines stay around in memory, whereas in the sigilless version then processed lines - so long as they are not stored elsewhere - can be garbage collected.

I could use a $ sigil, but that implies a single item, meaning that if I do this:

my $fh = open 'somefile';
my $no-comments = $fh.lines.grep({ not /^\s*'#'/ });
for $no-comments -> $sig-line {
    ...
}

It won't work (it would do one iteration of the loop, binding the Seq into $sig-line); I'd have to overcome the item nature of it somehow:

my $fh = open 'somefile';
my $no-comments = $fh.lines.grep({ not /^\s*'#'/ });
for $no-comments<> -> $sig-line {
    ...
}

A related use is when writing generic code that does not want to enforce any context:

sub log-and-call(&foo, \value) {
    note(value.raku);
    foo(value)
}

Again, if we used $ we could add an item wrapper and potentially impact upon the behavior of foo.

Other uses I've seen:

  • Since you can't rebind such a declaration, one can use it to convey the immutability to the reader. That said, it's not deep immutability, just immutability of what that symbol references.
  • Some folks just really don't like sigils, so use this to avoid them. Certainly not the most natural way to use Raku, but each to their own. :-)
Jonathan Worthington
  • 29,104
  • 2
  • 97
  • 136
  • Gee, this seems really the only place to ask such an obvious question: if you declare a variable such as `my \sigil-less;` are there any inherent/performance benefits if later in your code you coerce to $scalar or @positional or %associative or &code ?? To my eyes, coercion via the constructs `$(sigil-less)`, `@(sigil-less)`, `%(sigil-less)`, and `&(sigil-less)` look completely natural and intuitive, although the `Rakudo` compiler might complain otherwise. – jubilatious1 Nov 25 '22 at 05:22
  • There are places where the compiler uses the sigil to optimize, for example assignment is case analyzed, parameter binding compilation uses it, and I think there are sigil-based optimizations around interpolation in regexes. However, since a `Scalar` is a container - and thus an object - then use of a `$` sigil variable together with assignment implies an extra allocation. However `Scalar` containers are also often possible for the JIT to eliminate via escape analysis and scalar replacement optimizations. In conclusion, it's not all that obvious! – Jonathan Worthington Nov 28 '22 at 00:15
3

Since they are constants, I like to use them when copying algorithms and formulae from text books.

It makes it easier to check for errors.

tbrowder
  • 65
  • 5