equivariant functions

Denis Koroskin 2korden at gmail.com
Tue Oct 14 11:57:56 PDT 2008


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.

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



More information about the Digitalmars-d mailing list