FYI: The support for variant function (aka polymorphic overloading) has now reached a semi-useable state in Pike 7.9:
| Pike v7.9 release 5 running Hilfe v3.5 (Incremental Pike Frontend) | > class foo { | >> variant int bar(int a) { return a*2; } | >> variant string bar(string s) { return "FOO" + s + "FOO"; } | >> variant string bar() { return "FOO"; } | >> } | > typeof(foo()->bar); | (1) Result: function( : string) | function(int : int) | function(string : string) | > foo()->bar(17); | (2) Result: 34 | > foo()->bar("BAR"); | (3) Result: "FOOBARFOO" | > foo()->bar(); | (4) Result: "FOO" | > foo()->bar(1.2); | Compiler Error: 1: Bad argument 1 to bar. | Compiler Error: 1: Expected: string | int. | Compiler Error: 1: Got : float. | > foo()->bar((mixed)1.2); | Invalid arguments to bar()! | HilfeInput:1: HilfeInput()->foo()->bar(1.2) | HilfeInput:1: HilfeInput()->___HilfeWrapper()
I would appreciate feedback especially regarding the expected semantics for:
* When the variants have different modifiers (protected, private, etc).
* When there's a function without the variant keyword.
* When the types for the variants aren't disjunct.
* When overriding X from an inherit with a variant function.
- A non-variant function.
- A variant function with a new definition with the same type.
- A variant function with a new definition with a different type.
* Should the previous definition be accessible in any of the above cases, or only if there's an explicit trampoline?
* Multiple inherits of variant functions.
- With the same types.
- With different types.
I've probably forgotten or not thought of some cases, please mention the expected semantics for these as well.
/grubba
First of all: thanks for the cool feature!
On Sun, 26 May 2013, Henrik Grubbstr�m (Lysator) @ Pike (-) developers forum wrote:
- When the types for the variants aren't disjunct.
What other options are there except for not allowing ambiguities? In saying that, it would be nice to have some kind of catch-all, e.g.
variant void foo(int a); variant void foo(mixed a); // effectively mixed - int
arne
Yeah, for two non-disjoint types T and U with T<U it should be possible. But it soon turns ugly (see C++ :) when you have multiple parameters...
On Mon, May 27, 2013 at 02:55:02PM +0000, Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum wrote:
Yeah, for two non-disjoint types T and U with T<U it should be possible. But it soon turns ugly (see C++ :) when you have multiple parameters...
this for example: variant void foo(int a, mixed b); variant void foo(mixed a, int b);
it will work fine unless it is called with (int, int)
if it is possible to detect these than i think an error would be ok: "types are ambiguous" to force the user to qualify which one of these takes (int, int)
on the other hand: the ambiguity would be gone as soon as variant void foo(int a, int b); is added.
On Sun, May 26, 2013 at 03:40:02PM +0000, Henrik Grubbstr�m (Lysator) @ Pike (-) developers forum wrote:
- When the variants have different modifiers (protected, private, etc).
it could be useful to make public and private versions of a function. if the call comes from outside, then less variants are available to choose from.
- When there's a function without the variant keyword.
that should be an error if we don't want to loose the benefit of an error telling us that a function was defined twice. otherwise, why even use a variant keyword at all.
- When overriding X from an inherit with a variant function.
- A non-variant function.
- A variant function with a new definition with the same type.
- A variant function with a new definition with a different type.
if the overriding function is not variant then it should just mask all variants. likewise if it is variant but the inherit is not.
this is the same case as the missing variant keyword above: unless all functions involved are variant the behaviour ought to be as if none are variant, which above leads to an error, and here it leads to overriding.
while i can see a theoretical use to make a variant of inherited functions, i think it's better to keep things simple.
what about for example the case that a non-disjunkt variant function is added in a newer version of the parent class? suddenly my functions are no longer called.
- Should the previous definition be accessible in any of the above cases, or only if there's an explicit trampoline?
what is an explicit trampoline in this context? (what is the difference to an implicit trampoline?)
- Multiple inherits of variant functions.
- With the same types.
- With different types.
the behaviour of one parent should not depend on other parents i think. so variants should have no effect here.
for disjunct types it could be interesting to choose the matching one instead of failing. however i'd see this as a seperate feature because i think it would be beneficial to make this work without needing the variant keyword.
if that is a bad idea without a variant keyword, then it is probably also a bad idea with a variant keyword because i think definitions in the parents should not influence the resolution order in the child. (unless it is something like final (or private, but private is equivalent to removing the function from the parent))
greetings, martin.
pike-devel@lists.lysator.liu.se