I have just come across this in a few files within an eZ framework:
$ini =& eZINI::instance();
What exactly does the =& do. I've never seen it before..
I realize this thread is old, but i stumbled upon it while searching for the reference for the eZINI class so i might as well answer your question.
$a =& $b assigns $b's reference to $a. This essentially means that $a and $b will be aliases for the same memory location. Thus manipulating $a will manipulate $b as well and vice-versa.
Related
I've written a code to calculate the Fibonacci series using array variables inside the explicit generator like this:
my #fib = [0],[1],-> #a, #b {[|#a Z+ |#b]} ... Inf;
say #fib[^6];
This works as expected. But when I use scalar variables inside the same code, it works too:
my #fib_v2 = [0],[1],-> $a, $b {[|$a Z+ |$b]} ... Inf;
say #fib_v2[^6];
Could they be called scalar variables pointing to the arrays? What are they called when they are used in this manner?
Note that I've browsed the online Raku documentation but it's hard to spot that particular information i.e. if arrays can be referred using scalar variables.
You should say that "the scalar variables are bound to the arrays". Because that is what happens. You could think of:
-> $a, $b { say $a; say $b }("foo", "bar")
as:
{ my $a := "foo"; my $b := "bar"; say $a; say $b }
So, when you bind an array to a scalar, it is still an Array object. And calling methods on it, will just work. It may just make reading the code more difficult.
Note this is different from assigning an array to a scalar.
raku -e 'my $a := [1,2,3]; .say for $a'
1
2
3
versus:
raku -e 'my $a = [1,2,3]; .say for $a'
[1 2 3]
The for iterating logic sees the container in $a and takes that as a sign to NOT iterate over it, even though it contains an Iterable.
Note that I've browsed the online Raku documentation but it's hard to spot that particular information i.e. if arrays can be referred using scalar variables.
It basically falls out of correctly grokking the relation between containers and binding. About 4 years ago, I wrote a blog post about it: https://opensource.com/article/18/8/containers-perl-6 Please pardon the archaic naming :-)
Is there idiomatic way of applying and assigning object variable method call, but only if it's defined (both method and the result)?
Like using safe call operator .? and defined-or operator //, and with "DRY principle" – using the variable only once in the operation?
Like this (but using another variable feels like cheating):
my $nicevariable = "fobar";
# key step
(my $x := $nicevariable) = $x.?possibly-nonexistent-meth // $x;
say $nicevariable; # => possibly-nonexistent-meth (non-Nil) result or "foobar"
... And avoiding andthen, if possible.
Are you aware of the default trait on variables?
Not sure if it fits your use case, but $some-var.?unknown-method returns Nil, so:
my $nicevariable is default("fobar");
$nicevariable = $nicevariable.?possibly-nonexistent-meth;
say $nicevariable; # fobar
results in $nicevariable being reset to its default value;
I'm not entirely sure what you mean by "using the variable only once in the operation". If Liz's answer qualifies, then it's probably the cleaner way to go.
If not, here's a different approach that avoids naming the variable twice:
my $nicevariable = "foobar";
$nicevariable.=&{.^lookup('possibly-nonexistent-meth')($_)}
This is a bit too cryptic for my tastes; here's what it does: If the method exists, then that's similar to¹ calling &method($nicevariable), which is the same as $nicevariable.method. If the method does not exist, then it's like calling Mu($nicevariable) – that is, coercing $nicevariable into Mu or a subtype of Mu. But since everything is already a subtype of Mu, that's a no-op and just returns $nicevariable.
[1]: Not quite, since &method would be a Sub, but basically.
EDIT:
Actually, that was over-complicating things. Here's a simpler version:
my $nicevariable = "foobar";
$nicevariable.=&{.?possibly-nonexistent-meth // $_}
Not sure why I didn't just have that to begin with…
Assuming the method returns something that is defined, you could do (if I'm understanding the question correctly):
my $x = "foobar";
$x = $_ with $y.?possibly-nonexistent-meth;
$x will remain unchanged if the method didn't exist (or it did exist and returned a type object).
As of this merge you can write:
try { let $foo .= bar }
This is a step short of what I think would have been an ideal solution, which is unfortunately a syntax error (due to a pervasive weakness in Raku's current grammar that I'm guessing is effectively unsolvable, much as I would love it to be solved):
{ let $foo .?= bar } # Malformed postfix call...
(Perhaps I'm imagining things, but I see a glimmer of hope that the above wrinkle (and many like it) will be smoothed over a few years from now. This would be after RakuAST lands for Raku .e, and the grammar gets a hoped for clean up in Raku .f or .g.)
Your question's title is:
Variable re-assign method result if not Nil
My solution does a variable re-assign method if not undefined, which is more general than just Nil.
Then again, your question's body asks for exactly that more general solution:
Is there idiomatic way of applying and assigning object variable method call, but only if it's defined (both method and the result)?
So is my solution an ideal one?
My solution is not idiomatic. But that might well be because of the bug I found, now solved with the merge linked at the start of my answer. I see no reason why it should not become idiomatic, once it's in shipping Rakudos.
The potentially big issue is that the try stores any exception thrown in $! rather than letting it blow up. Perhaps that's OK for a given use case; perhaps not.
Special thanks to you for asking your question, which prompted us to come up with various solutions, which led me to file an issue, which led vrurg to both analyse the problem I encountered and then fix it. :)
If I have the following variables
my $a = 0;
my $*b = 1;
state $c = 2;
our $d = 3;
I can easily determine that $*b is dynamic but $a is not with the following code
say $a.VAR.dynamic;
say $*b.VAR.dynamic;
Is there any way to similarly determine that $c is a state variable and $d is a package-scoped variable? (I know that I could do so with a will trait on each variable declaration, but I'm hopping there is a way that doesn't require annotating every declaration. Maybe something with ::(...) interpolation?)
In the case of the package-scoped variable, not too hard:
our $foo = 'bar';
say $foo.VAR.name ∈ OUR::.keys
where we're using the OUR pseudopackage. However, there's no such thing as a STATE pseudopackage. They obviously show up in the LEXICAL pseudopackage, but I can't find a way to check if they're a state variable or not. Sorry.
To my knowledge, there is no way to recognize a state variable. Like any lexical, it lives in the lexpad. The only thing different about it, is that it effectively has code generated to do the initialization the first time the scope is entered.
As Elizabeth Mattijsen correctly noted, it is currently not possible to see whether a variable is a state variable at run time. ... at least technically at runtime.
However, as Jonathan Worthington's comment implies, it is possible to check this at compile time. And, absent deep meta-programming shenanigans, whether a variable is a state variable is immutable after compile-time. And, of course, it's possible to make note of some info at compile time and then use it at runtime.
Thus, it's possible to know, at runtime, whether a variable is a state one with (compile-time) code along the following lines, which provides a list-state-vars trait that lists all the state variables in a function:
multi trait_mod:<is>(Sub \f, :$list-state-vars) {
use nqp;
given f.^attributes.first({.name eq '#!compstuff'}).get_value(f)[0] {
say .list[0].list.grep({try .decl ~~ 'statevar'}).map({.name});
}
};
This code is obviously pretty fragile/dependent on the Rakudo implementation details of QAST. Hopefully this will be much easier with RAST, but this basic approach is already workable and, in the meantime, this guide to QAST hacking is a helpful resource for this sort of meta programming.
While trying to come up with an example of maps in sunk context, I bumped into this code:
my $a = -> { 42 };
my $b = -> { "foo" };
$a;
$a();
($a,$b).map: { $_ };
The first call to $a by itself returns:
WARNINGS for /home/jmerelo/Code/raku/my-raku-examples/sunk-map.p6:
Useless use of $a in sink context (line 6)
However, putting .() or () behind, or using them in (what I though it was) sink context in a map didn't result in any warning. Probably it's not sink context, but I would like to know why.
$a;
$a();
($a,$b).foo ...
The first call to $a by itself
That's not a "call". That's just a mention of it aka "use". (Note: this, er, use of "use" has nothing to do with the keyword use in a use statement.)
WARNINGS for /home/jmerelo/Code/raku/my-raku-examples/sunk-map.p6:
Useless use of $a in sink context (line 6)
Right. Just mentioning it like that is useless. You don't do anything with the value of $a (which has been assigned a function). You just drop it on the floor.
However, putting .() or () behind, or using them in (what I though it was) sink context in a map didn't result in any warning.
Right. Those cause .CALL-ME to be invoked on their left hand side. Those are understood to be potentially useful regardless of whether any value returned by the call is used by the code. So there's no warning despite being in sink context (though perhaps sink context is itself context dependent and at the compiler level they aren't even considered to be in sink context; I don't know).
cf my comment about a similar situation in perl.
So, from the documentation is almost clear what the three entities from the title are, but it is not very clear what their purpose is.
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.
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? Also, references are generally used in some languages to make it clear, in object construction or function calls, that you don't want to copy an object around, but why would it be useful, in the same scope, to have
$number_of_cakes = 4;
$also_the_number_of_cakes := $number_of_cakes;
?
Finally, the documentation explains how one can define a sigilless variable (that cannot be varied, so, actually, yet another kind of constant) but not why one would do that. 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?
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.
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.