defining "in" What is the proper way in D2?

Steven Schveighoffer schveiguy at yahoo.com
Mon Sep 12 08:32:13 PDT 2011


On Mon, 12 Sep 2011 11:23:36 -0400, Timon Gehr <timon.gehr at gmx.ch> wrote:

> On 09/12/2011 05:16 PM, Steven Schveighoffer wrote:
>> On Mon, 12 Sep 2011 11:02:20 -0400, Timon Gehr <timon.gehr at gmx.ch>  
>> wrote:
>>
>>> On 09/12/2011 04:34 PM, Steven Schveighoffer wrote:
>>>> On Mon, 12 Sep 2011 10:24:52 -0400, Timon Gehr <timon.gehr at gmx.ch>
>>>> wrote:
>>>>
>>>>> On 09/12/2011 04:17 PM, Steven Schveighoffer wrote:
>>>>>> On Mon, 12 Sep 2011 10:10:35 -0400, Simen Kjaeraas
>>>>>> <simen.kjaras at gmail.com> wrote:
>>>>>>
>>>>>>> On Mon, 12 Sep 2011 00:11:11 +0200, Timon Gehr <timon.gehr at gmx.ch>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> I think the fact that "in" for AAs returns a pointer is a mistake
>>>>>>>> and
>>>>>>>> ugly in the first place and any generic code that relies on any
>>>>>>>> container to return a raw internal pointer is flawed by itself  
>>>>>>>> imho.
>>>>>>>
>>>>>>> If D had a Nullable struct, that would likely be a much better  
>>>>>>> return
>>>>>>> type for 'in'. The thing is, we do have a nullable!T type: T*.
>>>>>>>
>>>>>>> This is simply a case of having a wrench and needing a hammer.
>>>>>>
>>>>>> No, the advantage of using a pointer is, you can change the value
>>>>>> without incurring another lookup. A nullable struct does not have  
>>>>>> that
>>>>>> advantage.
>>>>>
>>>>> A decent compiler has that advantage without requiring programmers to
>>>>> abuse the 'in' operator.
>>>>>
>>>>>> I think the correct return type for that should be a cursor (i.e. a
>>>>>> single-element range which can be used to refer to that element at a
>>>>>> later time). This allows even more functionality, such as removing  
>>>>>> the
>>>>>> element, or referring to both the key and value.
>>>>>>
>>>>>
>>>>> The correct return type for 'in' is bool. But the functionality you
>>>>> propose could be quite useful indeed.
>>>>
>>>> I agree the term 'in' doesn't accurately describe the function I
>>>> propose. But then again, AA doesn't provide any other means to avoid
>>>> double-lookup.
>>>
>>> The compiler could do it, because most cases of double-lookup are
>>> recognized trivially.
>>>
>>>> I think having a different member function to do the same
>>>> thing, and re-purposing 'in' to just return bool would be fine. This
>>>> should be entirely possible, since AA's are now at least extendable by
>>>> the library.
>>>>
>>>> -Steve
>>>
>>> +1. That would be great, because it would eliminate a case of operator
>>> overloading abuse sitting right in the language's core. Also, it would
>>> open up opportunities to reuse the operator for other built-in types.
>>>
>>> if(a in [1,5,7,11]){}
>>>
>>> is so much better and DRYer than
>>>
>>> if(a==1 || a==5 || a==7 || a==11) {}
>>
>> That still would need special treatment, because in should be fast
>> (O(lgn) or better), and in on any array is O(n).
>
> O(n) is just fine, because that is the fastest way of searching an  
> arbitrary array.

No it's not fine.  Even if you think it is, you will never get this past  
Andrei (or me).

a in b should be fast, it's already associated with efficiency.

>> I'd say the array had to be a literal, or guaranteed sorted to support
>> in. I'm not sure that's a great thing.
>>
>> But in order to do all this, we have to consider that a *lot* of code
>> relies on a in AA returning a pointer.
>
> What code? I think many people don't notice that it returns a pointer,  
> because they expect it to return bool.

I use it whenever I use AA's to avoid double lookup.  Look in any code  
that uses AA's and cares about efficiency:

if(auto v = a in b)
{
    *v = newval;
}
else
{
    b[a] = newval;
}

>
>>
>> I almost think it's too late to make that kind of change (have a in AA
>> return bool instead of a pointer).
>>
>> One more point: it's technically not abuse, since a in AA does evaluate
>> to a bool value meaning "a is in the AA". It's overloading :)
>>
>> -Steve
>
> auto foo(){
>      auto x=a in aa;
>      return x;
> }

if(foo())

works just fine ;)

-Steve


More information about the Digitalmars-d-learn mailing list