Hi Damian —

I'm assuming that in the example you're asking about, you're calling it with real values like:

        var r1 = 1.2,
            r2 = 3.4;

        var x = max(r1, r2);

??

In general, when given a choice between a precise routine:

        proc foo(x: real) { ... } // x must be a real (real(64))

And a generic one:

        proc foo(x: ?t) { ... } // x can be any type

The first overload is chosen because it's a more precise match. This also extends to families of built in scalar types like:

        proc foo(x: real(?w)) { ... } // x can be real(32) or real(64)

because it's still a more precise match than the fully generic one. One other way in which things can go wrong is if your call was actually:

        max(1.2, 3.4);

since 1.2 and 3.4 are param values (known to the compiler), an overload like:
        proc foo(param x: real, param y: real) param { ... }

would be a better match since it takes param values and yours doesn't.

Note that in the routine you show below, the use of ': ?Real' on the first argument says "I don't know what type 'x' will be, but whatever it is, let's call it 'Real' for the rest of this routine." So it's very generic rather than being very precise (you could pass in two ints, two strings, two records of type 'R', etc.) I.e., your routine is identical to:

        proc max(x: ?t, y: t): t { ... } // x can be any type, y must
                                         // be a compatible type; the
                                         // routine will return x's type

So the built-in version that takes two reals is still a better match / more precise since it's specific to reals and this one is not.

If you were to create a function that was an equally good match (or better) yet was "lexically closer" to your call, you could override the built-in version as shown in the following example:

        
https://tio.run/##VY1BCsIwFET3OcXQVVJLaerO4AE8RghRA@lv@VRNEM8eGwqCqxmGNzPubhcfS3EzXcMNT8tgjTN0P3TgcXNDr40QC88Ok00yncDexg55N2oXvAXw4rD6SLK5EKZc8UaZLWe/PpgwtgkHHNtsxOe3GEiqv3I9YV3PlapgKV8

Also, when reasoning about cases like this when it's unclear why the compiler is choosing a particular overload the --explain-call flag can be very useful. As an example, for the program at the TIO link above, if I saved the code and compiled it as:

        chpl --explain-call=max:8 myProgram.chpl

the option says "explain how you resolved the call named 'max' at line 8 in my source" (there's also a format to name the file in case multiple files have a call named max at line 8, but in practice this doesn't happen often, so I usually skip the filename for simplicity; the 'chpl' man page should have more details).

Hope this helps,
-Brad

Brad Chamberlain  Principal Engineer
Cray, a Hewlett Packard Enterprise company
901 Fifth Ave, Suite 1000 | Seattle, WA 98164
+1-206-701-2077  [email protected]  www.cray.com


On Sat, 14 Mar 2020, Damian McGuckin wrote:


I noticed that when I defined my own generic routine


        proc max (x : ?Real, y : Real) : Real

and then called in it a 'proc main', Chapel ignored my routine and used the generic routine from the Math module to create a real(64) routine which it then proceeded to call rom my 'proc main'. Mine got lost.

Is this deliberate?

Regards - Damian

Pacific Engineering Systems International, 277-279 Broadway, Glebe NSW 2037
Ph:+61-2-8571-0847 .. Fx:+61-2-9692-9623 | unsolicited email not wanted here
Views & opinions here are mine and not those of any past or present employer


_______________________________________________
Chapel-developers mailing list
[email protected]
https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.sourceforge.net_lists_listinfo_chapel-2Ddevelopers&d=DwICAg&c=C5b8zRQO1miGmBeVZ2LFWg&r=QUQW-BniEL_d2a7btR4rP5TPiNmpm1pG-Qa_xXzGVKc&m=OGTIQF6QKKiLQaaKkCrBnFSaiJLR5udFPW2uHyRfNUY&s=MR_w1kItGECbIX7wp3KZYfJNVM9hFG0R1eMEjIZzHu0&e=
_______________________________________________
Chapel-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-developers

Reply via email to