Search code examples
rakusyntactic-sugar

Variable re-assign method result if not Nil


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.


Solution

  • 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…