Persistent list

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Mon Nov 16 10:33:04 PST 2015


On 11/16/15 1:15 PM, Dmitry Olshansky wrote:
> On 16-Nov-2015 19:44, Steven Schveighoffer wrote:
>> On 11/14/15 3:42 AM, Dmitry Olshansky wrote:
>>> On 14-Nov-2015 02:10, Andrei Alexandrescu wrote:
>>
>>>> * Lines 141-152: I couldn't make tail() work with inout. Generally I'm
>>>> very unhappy about inout. I don't know how to use it. Everything I read
>>>> about it is extremely complicated compared to its power. I wish we
>>>> removed it from the language and replaced it with an understandable
>>>> idiom.
>>>>
>>>
>>> I can't agree more. Every time dealing with inout when I finally think I
>>> grok how it works the next instant I see that it doesn't do what I
>>> expect.
>>>
>>> For me inout inevitably stops at the boundary of being unnable to have
>>> List!(inout(T)) and the like.
>>
>> One thing we could allow is types that contain inout member variables,
>> but ONLY in the context of inout functions. In other words, you can
>> create a type for it, but can only use it in the context of an inout
>> function.
>
> inout should be indistinguishable of const but the moment you pass
> inout(T) to a template it becomes murky.
>
> Appender!(inout(int)) - which qualifier to instantiate?

The idea is, you would instantiate Appender!(inout(int)) :) Should be 
fine to use inside an inout function.

The problem is, you couldn't use it outside inout, so you couldn't use 
this as the return type. But inside the function, you could use it.

Right now, you can effectively do this with arrays, since inout(T)[] 
works fine, and this can essentially map to some fictional template 
instantiation ArrayStruct!(inout(T)) (or some other way to instantiate 
ArrayStruct!T and wrap this in an attribute that means tail). But arrays 
enjoy both auto casting that tail member to other flavors, and also the 
compiler allows you to create inout arrays inside an inout function.

We can at least solve the latter pretty easily. The closer we can move 
to have an actual ArrayStruct template that works just like a real 
array, the closer we are to having a complete solution.

>
>>
>> A List!(inout(T)) outside an inout function has no meaning. This is why
>> we disallowed it.
>>
>> However, my belief is that it's the lack of a mechanism to apply an
>> attribute to the tail of some struct that prevents the most utility
>> here. If you returned a List!(inout(T)) there is no way to magically
>> convert it to a List!(const(T)) or List!(immutable(T)).
>>
>> Consider that Node in this code has a "const(Node)* next" as its tail.

Note, I think I was wrong with this. The Node has a Node *next, but root 
is labelled as const.

In the end, this code is a bad example of what is wrong with inout, 
because inout shouldn't be used on it anyway.

> Looks a lot like tail-const problem. That is immutable T!E has no way to
> convert to T!(immutable E) and similarly to T!(const E).

It all depends on how E is used in T. Tail-const is a specific problem 
that *could* be solved if we could provide a mechanism to do this, but 
providing the mechanism isn't *required*.

-Steve


More information about the Digitalmars-d mailing list