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.
Use the nullish coalescing operator to reassign a variable if it's equal to null or undefined, e.g. myVar = myVar ?? 'new value'. The nullish coalescing operator returns the right-hand side operand if the left-hand side evaluates to null or undefined, otherwise it returns the left-hand side operand.
the variable can be reassigned with a new value, even a value of another type; the value, if it’s an array or an object, can be mutated. Knowing that both things are possible makes you think, every time you see pizza in the code, which value it has now. That’s a huge and unnecessary cognitive load that we should avoid.
A COM or P/Invoke method that returns a HRESULT or error code that is never used. A language-integrated query (LINQ) method that returns a result that is never used.
Or remove the call if it is unnecessary. If method A calls method B, but does not use the HRESULT or error code that the method returns, use the result in a conditional statement, assign the result to a variable, or pass it as an argument to another method.
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With