I'm trying to address this issue, which was actually raised by this other stackoverflow question related to the different behavior of callwith
and samewith
. The latter seems to be clearly defined, however, it's not so clear with callwith
.
Check out this example:
proto how-many(|) {*}
multi sub how-many( Pair $a, Pair $b ) {
say "Int $a and $b";
return "There are $a and $b"
}
multi sub how-many( $a, $b ) {
say "Not int $a and $b";
my $calling = callwith( 1 => $a, 2 => $b );
return $calling;
}
say how-many( "little piggie","littler piggie" );
According to the documentation, callwith
should call the next matching candidate. However, this is the output:
Not int little piggie and littler piggie
(Any)
So it's calling the second version of how-many
, then calling a non-existing function (apparently) and returning Nil
, which is passed as Any
to the calling routine.
I have also tried with using different signatures, but that does not work either. The example in the documentation apparently indicates that it will work only if the variables belong to the same class hierarchy. Is that the case? It might not be, since changing the positional signature to Any $a, Any $b
does not work either, neither changing the order of declaration.
Above, changing
callwith
withsamewith
will obviously work, but I'm trying to understand howcallwith
works, not make the code above work.
Besides, it seems to be going down the class hierarchy, but not up. This example in roast, the Perl 6 test suite, works:
my $tracker = '';
multi d($x) { $tracker ~= 'Any' ~ $x };
multi d(Int $x) { $tracker ~= 'Int'; callwith($x+1); $tracker ~= 'Int' };
lives-ok { d(3) }, 'can call callwith inside a multi sub';
However, if we change it so that the we use callwith
from the bottom of the hierarchy like this:
my $tracker = '';
multi d($x) { $tracker ~= 'Any' ~ callwith( "called-with" => $x) };
multi d(Pair $x) { $tracker ~= "Pair $x" };
say d( 3 );
It fails with
Use of Nil in string context in sub d at rewrite-test-callwith.p6 line 6
Is this intended behavior?
Likely, the mention of other candidates is only a request to be patient, or it's just the interviewer's way of ending the conversation. It's normal to be anxious about your chances after an interview , but try to think about the interview experience itself and the signs that you did well.
Things that interviewers say that mean you won't get the offer might include "We are interviewing a number of other candidates," or "Competition for this position is very tough," or "We will reach out with next steps when we finish interviewing all other candidates." If the interviewer response is vague or non- ...
All of callwith
, nextwith
, callsame
, and nextsame
walk through the set of candidates determined by the original arguments. Thus while callwith
can be used to replace an argument, that's all it is doing. It is not going to cause a change in the pre-determined list of candidates to iterate through.
Consider these three candidates:
multi foo(Any $x) { say "In Any case with $x" }
multi foo(Real $x) { say "In Real case with $x"; callwith($x.Int); }
multi foo(Int $x) { say "In Int case with $x"; callsame(); }
We can ask which candidates apply using .cando
and passing it a Capture
. Thus:
.say for &foo.cando(\(42));
Will produce the following output:
sub foo (Int $x) { #`(Sub|78402328) ... }
sub foo (Real $x) { #`(Sub|78412816) ... }
sub foo ($x) { #`(Sub|78412968) ... }
Since all 3 candidates match. Calling foo(42)
will result in the following output:
In Int case with 42
In Real case with 42
In Any case with 42
By contrast, with:
.say for &foo.cando(\(4.2));
The output is:
sub foo (Real $x) { #`(Sub|78412816) ... }
sub foo ($x) { #`(Sub|78412968) ... }
And calling foo(4.2)
has the callwith
iterate through those candidates:
In Real case with 4.2
In Any case with 4
A callwith
or similar in the most general candidate will not have any effect, and will evaluate to Nil
.
While the example here is with multi subs, the same applies to wrappers and non-multi methods, which also walk a predetermined list.
Finally, it's also worth observing that if there was a fresh dispatch every time, the example I gave would end up as an infinite recursion. By walking the pre-determined candidate list, that can never happen.
Note that none of this applies to samewith
, which exists precisely to do a completely fresh dispatch.
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