Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callwith not calling other candidates? What are "other candidates"? Is it exhausting the list of other candidates? Is that list available?

Tags:

dispatch

raku

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 with samewith will obviously work, but I'm trying to understand how callwith 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?

like image 256
jjmerelo Avatar asked Jul 09 '18 07:07

jjmerelo


People also ask

What does it mean when interviewer says there are other candidates?

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.

What things do interviewers say that let you know you won't get an offer?

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- ...


1 Answers

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.

like image 68
Jonathan Worthington Avatar answered Sep 28 '22 00:09

Jonathan Worthington