The following &greet function is pure, and can appropriately be marked with the is pure trait.
sub greet(Str:D $name) { say "Hello, $name" }
my $user = get-from-db('USER');
greet($user);
This one, however, is not:
sub greet {
my $name = get-from-db('USER');
say "Hello, $name"
}
greet($user);
What about this one, though?
sub greet(Str:D $name = get-from-db('USER')) { say "Hello, $name" }
greet();
From "inside" the function, it seems pure – when is parameters are bound to the same values, it always produces the same output, without side effects. But from outside the function, it seems impure – when called twice with the same argument, it can produce different return values. Which prospective does Raku/Rakudo take?
There are at least two strategies a language might take when implementing default values for parameters:
With its dynamic nature, only the second of these really makes sense for Raku, and so that is what it does.
In a language doing strategy 1 it could arguably make sense to mark such a function as pure, insofar as the code that calculates the default lives at each callsite, and so anything doing an analysis and perhaps transformation based upon the purity will already be having to deal with the code that evaluates the default value, and can see that it is not a source of a pure value.
Under strategy 2, and thus Raku, we should understand default values as an implementation detail of the block or routine that has the default in its signature. Thus if the code calculating the default value is impure, then the routine as a whole is impure, and so the is pure
trait is not suitable.
More generally, the is pure
trait is applicable if for a given argument capture we can always expect the same return value. In the example given, the argument capture \()
contradicts this.
An alternative factoring here would be to use multi
subs instead of parameter defaults, and to mark only one candidate with is pure
.