Sigilless variables, constants, bindings: when to choose what

That's not one but at 5 questions?

If I bind a variable to 3.14, isn't it the same as defining a PI constant?

Well, technically it would be except for the fact that 3.14 is a Rat, and pi (aka π) is a Num.

Is $a := $b actually defining $a as an alias to $b or, as some other languages call it, a reference?

It's an alias.

$number_of_cakes = 4; $also_the_number_of_cakes := $number_of_cakes;

There would be little point. However, sometimes it can be handy to alias something to an element in an array, or a key in a hash, to prevent repeated lookups:

my %foo;
my $bar := %foo<bar>;
++$bar for ^10;

What problems do sigilless variables solve?

Sigilless variables only solve a programming style issue, as far as I know. Some people, for whatever reason, prefer sigilless varriables. It makes it harder to interpolate, but others might find the extra curlies actually a good thing:

my answer := my $ = 42;
say "The answer is {answer}";

What's a practical scenario when a variable, a constant, a binding variable do not solve the problem that a sigilless variable solve?

In my view, sigilless variables do not solve a problem, but rather try to cater different programming styles. So I'm not sure what a correct answer to this question would be.


Also constant is our scoped by default.


Constants are common in many languages. You don't want to write 3.14 all over your code and that's why you define a constant PI that, by the nature of the thing it represents, cannot be changed and that's why its value is constant in time.

For that you use constant.

A constant is only initialized once, when first encountered during compilation, and never again, so its value remains constant throughout a program run. The compiler can rely on that. So can the reader -- provided they clearly understand what "value" means in this context.1

For example:

BEGIN my $bar = 42;

loop {
  constant foo = $bar;
  $bar++;
  last if $++ > 4;
  print foo; # 4242424242
}

Note that if you didn't have the BEGIN then the constant would be initialized and be stuck with a value of (Any).

I tend to leave off the sigil to somewhat reinforce the idea it's a constant but you can use a sigil if you prefer.

Defining a variable bound to another entity with := is also almost clear but not really. If I bind a variable to 3.14, isn't it the same as defining a PI constant? Is $a := $b actually defining $a as an alias to $b or, as some other languages call it, a reference?

Binding just binds the identifiers. If either changes, they both do:

my $a = 42;
my $b := $a;
$a++;
$b++;
say $a, $b; # 4444

Finally, the documentation explains how one can define a sigilless variable (that cannot be varied, so, actually, another kind of constant) but not why one would do that.

It can be varied if the thing bound is a variable. For example:

my $variable  = 42;        # puts the value 42 INTO $variable
my \variable  = $variable; # binds variable to $variable
say ++variable; # 43
my \variable2 = 42;        # binds variable2 to 42
say ++variable2;           # Cannot resolve caller prefix:<++>(Int:D);
                           # ... candidates ... require mutable arguments

I personally prefer to slash sigils if an identifier is bound to an immutable basic scalar value (eg 42) or other entirely immutable value (eg a typical List) and use a sigil otherwise. YMMV.

What problems do sigilless variables solve? What's a practical scenario when a variable, a constant, a binding variable do not solve the problem that a sigilless variable solve?

Please add comments if what's already in my answer (or another; I see someone else has posted one) leaves you with remaining questions.

Foonotes

1 See my answer to JJ's SO about use of constant with composite containers.

Tags:

Raku