September 09, 2008
Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
>> Steven Schveighoffer wrote:
>>> "Andrei Alexandrescu" wrote
>>> I thought you stated that 'pointers' shouldn't be allowed, only ranges? In general, I agree with that, but I think the ability to use a pointer type instead of ranges has advantages in some cases.
>> I think there's a little confusion. There's three things:
>>
>> 1. Ranges
>> 2. Iterators
>> 3. Pointers, e.g. the exact address where the object sits in memory
> 
> Yes, I have been using the terms iterator and pointer interchangably, my bad :)  I look at pointers as a specialized type of iterator, ones for which only 'dereference' is defined (and on contiguous memory types such as arrays, increment and decrement).
> 
>> My address uses 1 and drops 2. You still have access to 3 if you so need.
>>
>> void showAddresses(R)(R r)
>> {
>>     for (size_t i = 0; !r.isEmpty; r.next, ++i)
>>     {
>>         writeln("Element ," i, " is sitting at address: ", &(r.first));
>>     }
>> }
> 
> Let me explain by example:
> 
> HashMap!(uint, myResource) resources;
> 
> ....
> 
> // returns something that allows me to later remove the element
> auto r = resources.find(key);
> 
> useResource(r);
> 
> resources[newkey] = new myResource;
> 
> resources.erase(r);
> 
> Now, assuming that adding the new resource rehashes the hash map, what is in r such that it ONLY points to the single resource?  A marker saying 'only one element'?  Perhaps you just deleted a range you didn't mean to delete, when you only wanted to delete a single resource.  Perhaps r is now considered 'invalid'.  Granted, this example can be fixed by reordering the lines of code, and perhaps you don't care about the penalty of looking up the key again, but what if I want to save the iterator to the resource somewhere and delete it later in another function?  And what if the cost of lookup for removal is not as quick?
> 
> I think with a range being the only available 'iterator' type for certain containers may make life difficult for stuff like this.  I really don't think iterator is the right term for what I think is needed, what I think is needed is a dumbed down pointer.  Something that has one operation --  opStar.  No increment, no decrement, just 'here is a reference to this element'  that can be passed into the container to represent a pointer to a specific element.

I understand. My design predicates that you can't model such non-iterable iterators. Either you can use it to move along, in which case ranges will do just fine, or you can't, in which case my design doesn't support it.

Note that the STL does not have non-iterable iterators. I think constructing cases where they make sense are tenuous.


Andrei
September 09, 2008
On Tue, 9 Sep 2008 18:28:34 -0400, Steven Schveighoffer wrote:

> It means 'left-most element in the range'.  It gets you the first element in the range (i.e. the next element to iterate) without modifying the range.
> 
> I agree that it is very misleading, but I think Andrei is exploring other possibilities (see other threads).

Thanks. I was playing at "devil's advocate" as my real point was that "left" is way too overloaded with different meanings and is thus not a suitable choice. We already have this problem a few times in D (eg. 'static')

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/09/2008 9:56:09 AM
September 10, 2008
"Andrei Alexandrescu" wrote
> Steven Schveighoffer wrote:
>> Let me explain by example:
>>
>> HashMap!(uint, myResource) resources;
>>
>> ....
>>
>> // returns something that allows me to later remove the element
>> auto r = resources.find(key);
>>
>> useResource(r);
>>
>> resources[newkey] = new myResource;
>>
>> resources.erase(r);
>>
>> Now, assuming that adding the new resource rehashes the hash map, what is in r such that it ONLY points to the single resource?  A marker saying 'only one element'?  Perhaps you just deleted a range you didn't mean to delete, when you only wanted to delete a single resource.  Perhaps r is now considered 'invalid'.  Granted, this example can be fixed by reordering the lines of code, and perhaps you don't care about the penalty of looking up the key again, but what if I want to save the iterator to the resource somewhere and delete it later in another function?  And what if the cost of lookup for removal is not as quick?
>>
>> I think with a range being the only available 'iterator' type for certain containers may make life difficult for stuff like this.  I really don't think iterator is the right term for what I think is needed, what I think is needed is a dumbed down pointer.  Something that has one operation -- opStar.  No increment, no decrement, just 'here is a reference to this element'  that can be passed into the container to represent a pointer to a specific element.
>
> I understand. My design predicates that you can't model such non-iterable iterators. Either you can use it to move along, in which case ranges will do just fine, or you can't, in which case my design doesn't support it.
>
> Note that the STL does not have non-iterable iterators. I think constructing cases where they make sense are tenuous.

Well, STL happens to use iterators to specify elements.  It doesn't mean that the iterators are used as iterators in that context, it's just that it's easier to specify one type that does iteration AND represents position :)

For example, std::list defines multiple erase functions:

iterator erase(iterator first, iterator last);
iterator erase(iterator position);

In the second case, the iterator need not support incrementing or decrementing (to the user anyway), just referencing.  They just used iterator because it's already there :)

But in your proposed scenario, I can't have the second function, only the first.  My example shows a case where I'd want the second function.  What I basically want is a range type where the upper limit is specified as 'always null', so that iterating the range once always results in an empty range, even if the container has changed topology.

-Steve


September 10, 2008
On Tue, 09 Sep 2008 18:04:12 -0500, Andrei Alexandrescu wrote:

> But yes... first and last are in I guess.
Yes, I understand this. I am just raking old coals to stress the importance of choosing the "right" (or is that "correct") word; one that promotes least synaptic double-takes.

> Finally the coin dropped on the Arabic/Hebrew cultural thing. I don't think they'd be offended.

I wasn't thinking about offense, just cultural assumptions.

> This is not writing. Left is left and right is right in math.

Well, I beg to differ. I believe that programming languages are closer to prose than they are to maths. Even if 'left' and 'right' have specific meanings in maths, people reading someone else's code and seeing r.left might not know that they are reading "maths". I'm sure most readers (at least while learning) will apply their cultural bias when interpreting the written text, and all I'm saying is that r.left may very well mean different things to different people.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/09/2008 9:58:38 AM
September 10, 2008
On Tue, 09 Sep 2008 18:13:08 -0500, Andrei Alexandrescu wrote:


> Previous is confusing as it suggest I'm moving back where I came from.

Ah... how confusing is this English language! ;-)

> In reality I shrink the range from the other end. So we need:
> 
> "Shrink the range from the left end"
> "Shrink the range from the right end"

And I'm sure you really mean ...

 "Shrink the range from the front"
 "Shrink the range from the back"

because "left" does not always mean "front" etc ... but we've been over
this.

> The first will be used much more often than the second.

If the concept and the implementation involves changing the size (shrinking), shouldn't the words used somehow invoke this idea?

trim? strip? slice? cut? ... just thinking out loud ... nothing too serious.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/09/2008 10:10:32 AM
September 10, 2008
On Mon, 08 Sep 2008 16:50:54 -0500, Andrei Alexandrescu wrote:

> Hello,

By the way, I meant to say this earlier, but I'm very glad that you have presented something for us to discuss with you. I really appreciate this.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
10/09/2008 10:18:23 AM
September 10, 2008
Derek Parnell wrote:
> If the concept and the implementation involves changing the size
> (shrinking), shouldn't the words used somehow invoke this idea?
> 
> trim? strip? slice? cut? ... just thinking out loud ... nothing too
> serious.

Consume?
September 10, 2008
Steven Schveighoffer wrote:
> "Andrei Alexandrescu" wrote
> For example, std::list defines multiple erase functions:
> 
> iterator erase(iterator first, iterator last);
> iterator erase(iterator position);
> 
> In the second case, the iterator need not support incrementing or decrementing (to the user anyway), just referencing.  They just used iterator because it's already there :)
> 
> But in your proposed scenario, I can't have the second function, only the first.  My example shows a case where I'd want the second function.  What I basically want is a range type where the upper limit is specified as 'always null', so that iterating the range once always results in an empty range, even if the container has changed topology.

I understand. That can't be had in my design. You'd have:

List.Range List.erase(Range toErase);

and you'd model erasure of one element through a range of size one. I understand how that can be annoying on occasion, but I consider that a minor annoyance and do not plan to allow bare iterators for such cases. I think the absence of naked iterators has huge cognitive and safety advantages.


Andrei

September 10, 2008
Derek Parnell wrote:
> On Mon, 08 Sep 2008 16:50:54 -0500, Andrei Alexandrescu wrote:
> 
>> Hello,
> 
> By the way, I meant to say this earlier, but I'm very glad that you have
> presented something for us to discuss with you. I really appreciate this.

Thanks.

chop?


Andrei
September 10, 2008
On Wed, Sep 10, 2008 at 8:04 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Finally the coin dropped on the Arabic/Hebrew cultural thing. I don't think they'd be offended. This is not writing. Left is left and right is right in math.

Also the direction in which D code is written does not depend on the
language of the speaker.  It's always left to right.
So I think there's no real argument on linguistic grounds.

On the other hand, a quick google for "left right confusion" turns up a fair number of relevant hits.  There's enough people out there who have trouble keeping those directions straight for it to get discussed.  Searches for "begin end confusion", "front back confusion", "first last confusion" predictably turned up no relevant hits I could find.

> But yes... first and last are in I guess. I'd also like *r as a shortcut for r.first, as it will be no doubt used very intensively.

Recognizing that the typical usage for these things will be that "first" is the current value and "last" is actually a bogus sentinel, I guess I would rather see something like .value or .item for the current value.  I can understand the pull to try to make the names symmetric, but in fact the things they represent are not really symmetric, so I don't see it as a  requirement that the names be symmetric.

And opStar is hard to search for so I'd rather not see that at all. Note also that if you declare that * is an alias for .first in the ranges interface that means that every implementor of a range will have to remember include that alias.

--bb