equivariant functions
Simen Kjaeraas
simen.kjaras at gmail.com
Tue Oct 14 12:12:43 PDT 2008
On Tue, 14 Oct 2008 20:57:56 +0200, Denis Koroskin <2korden at gmail.com>
wrote:
> On Tue, 14 Oct 2008 22:38:58 +0400, Simen Kjaeraas
> <simen.kjaras at gmail.com> wrote:
>
>> On Tue, 14 Oct 2008 18:51:56 +0200, Andrei Alexandrescu
>> <SeeWebsiteForEmail at erdani.org> wrote:
>>
>>> Steven Schveighoffer wrote:
>>>> "Andrei Alexandrescu" wrote
>>>>> Steven Schveighoffer wrote:
>>>>>> "Andrei Alexandrescu" wrote
>>>>>>> I discussed with Walter a variant that implements equivariant
>>>>>>> functions without actually adding an explicit feature to the
>>>>>>> language. Consider:
>>>>>>>
>>>>>>> typeof(s) stripl(const(char)[] s);
>>>>>> As another point on this, I think someone else mentioned it, but I
>>>>>> can't find the post.
>>>>>>
>>>>>> I don't like the way this looks. The way it reads is 'stripl
>>>>>> returns the same type as s', but really, the typeof(s) is actually
>>>>>> modifying the type of the argument also. This seems very
>>>>>> unintuitive.
>>>>> I agree. We need to look for a better notation.
>>>>>
>>>>>> I understand the need to not change the language, but I think most
>>>>>> would prefer a syntax where the type modifier is specified on at
>>>>>> least the argument. People are going to be extremely confused when
>>>>>> they can't treat 's' like a normal const(char)[].
>>>>>>
>>>>>> If the ultimate result is that no intuitive syntax can be made
>>>>>> without changing the language, then I think it is more important to
>>>>>> have this feature than to not change the language.
>>>>>>
>>>>>> One other syntax that Janice proposed (and I later put into a
>>>>>> bugzilla), is to use the dead keyword inout. Meaning, what you
>>>>>> send in is what you get out. ref already completely replaces
>>>>>> inout, so there is no need to keep it under its current meaning:
>>>>>>
>>>>>> inout(char)[] stripl(inout(char)[] s);
>>>>>>
>>>>>> I'm not in love with this completely, but it has the benefit of not
>>>>>> requiring a new keyword.
>>>>> Also I guess:
>>>>>
>>>>> class C
>>>>> {
>>>>> Range!(inout(C)) foo() inout;
>>>>> }
>>>>>
>>>>> And also:
>>>>>
>>>>> class Base {}
>>>>> class Derived : Base {}
>>>>> inout foo(inout Base b);
>>>> In this last example, what does the inout mean at the front?
>>>
>>> Accept and return any subtype of Base.
>>>
>>> Andrei
>>
>> I was first wondering how this would treat things like
>>
>> inout foo(Base b, int n);
>>
>> But then I noticed it saying "inout Base b", so only the argument(s)
>> marked
>> inout are considered for the return type?
>
> Yes
>
>> Also, this means a maximum of one
>> inout argument type per function, right?
>>
>
> No, there were many example of multiple (and even none) inout function
> arguments.
I said argument types, as inout(MyClass) in inout foo(inout(MyClass) a,
inout(MyClass) b).
>> As for the keyword, I feel inout is better than typeof, and good
>> enough. Not perfect, but good enough.
>>
>
> My concern is that it than 'inout' doesn't express that all the
> arguments marked as inout as bound to each other and actual type is
> deduced from them all. There is a relationship between their types.
>
> inout(A) min(inout(A1) a1, inout(A2) a2);
>
> A1 a1;
> A2 a2;
>
> const(A1) ca1;
> const(A2) ca2;
>
> invariant(A1) ia1;
> invariant(A1) ia2;
>
> auto a = min(a1, ia2); // typeof(a) == const(A) even though neither a1
> nor ia2 of that type
> auto a = min(a1, a2); // typeof(a) == A
>
> You see, in the example above the return type is changed because type of
> 2nd argument is changed. Not only the return type but types of all the
> arguments, too.
>
> auto a = min(ia1, ia2); // typeof(a) == invariant(A). Now return type
> is changed per 1st argument type change.
I don't really see this as a problem. Returning mutable or invariant would
be worse. Anyways, if you need the two arguments to be of the same type,
I'd prefer this syntax:
inout min(inout(A) a1, typeof(a1) a2){}
--
Simen
More information about the Digitalmars-d
mailing list