Multi-dispatch to candidate with native parameters not working

125 views Asked by At

I am trying to use multi in my Raku code that wraps a function in C. Here I am calling lchoose function in shared libray Rmath. This is my code which works:

use NativeCall;

constant RMATH = "./Rmath"; # shared library
sub lchoose(num64, num64) returns num64 
        is native( RMATH ) { * };

# The C function signature is 
# double    lchoose(double, double);

sub r_lchoose($n,$r) {
        return lchoose($n.Num, $r.Num)
}

say r_lchoose(9,8) # 2.1972245773362196

But this does not work. The code keeps on running/hanging. Neither dies nor throws any output:


use NativeCall;

constant RMATH = "./Rmath"; # shared library
multi lchoose(num64, num64) returns num64 
        is native( RMATH ) { * };

multi lchoose($n,$r) {
        lchoose($n.Num, $r.Num)
}

say lchoose(9,8) # Neither dies nor throws any output

My expectation is when I call lchoose(9,8) it should call second multi as the arguments are definitely not num64. If it had used second function, then it would have called the first function and given the output.

Or atleast I expected the program to throw error rather than hang.

OS information

Windows 11 64-bit

Raku information

Welcome to Rakudo™ v2022.04.0000.1.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2022.04-3-ga9fcd5a74.
1

There are 1 answers

4
Elizabeth Mattijsen On BEST ANSWER

A num64 in a signature indicate that it MUST have a num64 for a multi dispatch to work. Otherwise you could not set up candidates for a Num:D and have a candidate for num64 or num32.

And because there is no candidate for Num in your example, it will dispatch back to the original candidate, causing the infiniloop.

I would therefore write the "catch-all" lchoose candidate as:

multi lchoose(Num() $n, Num() $r) {
    lchoose(my num64 $ = $n, my num64 $ = $r)
}

In the signature we convert everything to Num, and then we assign these to nameless native num64 variables in the call the other candidate (which will now dispatch correctly).