简体   繁体   中英

When does it make sense to use a sigil-less variable in Raku?

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

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

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

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. :-)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM