Should the comma operator be removed in D2?

Bill Baxter wbaxter at gmail.com
Tue Nov 17 15:04:01 PST 2009


On Tue, Nov 17, 2009 at 2:53 PM, Robert Jacques <sandford at jhu.edu> wrote:
> On Tue, 17 Nov 2009 15:20:06 -0500, Yigal Chripun <yigal100 at gmail.com>
> wrote:
>
>> Robert Jacques wrote:
>>>
>>> On Tue, 17 Nov 2009 11:38:19 -0500, Bill Baxter <wbaxter at gmail.com>
>>> wrote:
>>>
>>>> On Tue, Nov 17, 2009 at 7:09 AM, Robert Jacques <sandford at jhu.edu>
>>>> wrote:
>>>>>
>>>>> On Tue, 17 Nov 2009 05:44:31 -0500, downs <default_357-line at yahoo.de>
>>>>> wrote:
>>>>>
>>>>>> Robert Jacques wrote:
>>>>>>>
>>>>>>> On Tue, 17 Nov 2009 00:06:27 -0500, Yigal Chripun
>>>>>>> <yigal100 at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Robert Jacques wrote:
>>>>>>>>>
>>>>>>>>> On Mon, 16 Nov 2009 17:53:45 -0500, Stewart Gordon
>>>>>>>>> <smjg_1998 at yahoo.com> wrote:
>>>>>>>>>
>>>>>>>>>> dsimcha wrote:
>>>>>>>>>> <snip>
>>>>>>>>>>>
>>>>>>>>>>> Axe.  Looks like the only things it's good for are making code
>>>>>>>>>>> undreadable and
>>>>>>>>>>> abusing for loop syntax to...
>>>>>>>>>>>  Make code unreadable.
>>>>>>>>>>
>>>>>>>>>> <snip>
>>>>>>>>>>
>>>>>>>>>> Suppose you want the increment of a for loop to change two
>>>>>>>>>> variables
>>>>>>>>>> in parallel.  I don't call that making code unreadable.
>>>>>>>>>>
>>>>>>>>>> Stewart.
>>>>>>>>>
>>>>>>>>>  Yes the classic use case of the comma operator is multi-variable
>>>>>>>>> declarations/increments in a for loop.
>>>>>>>>
>>>>>>>> This was argued before and as I and others said before, this is
>>>>>>>> *not*
>>>>>>>> a use case for the comma separator.
>>>>>>>>
>>>>>>>> e.g.
>>>>>>>> for (int a = 0, b = 1; condition(); a++, b++) {...}
>>>>>>>>
>>>>>>>> int a = 0, b = 1 // this is a declaration and not an expression
>>>>>>>>
>>>>>>>> a++, b++ // isn't assigned to any variable and can be treated as a
>>>>>>>> tuple
>>>>>>>>
>>>>>>>> the only use case that will break is if the two increments are
>>>>>>>> dependent on the order (unless tuples are also evaluated from left
>>>>>>>> to
>>>>>>>> right):
>>>>>>>> e.g.
>>>>>>>> a + 5, b + a //
>>>>>>>>
>>>>>>>> I doubt it very much that anyone ever uses this, it's too unreadable
>>>>>>>> to be useful.
>>>>>>>
>>>>>>> However, I imagine tuple(a++,b++) would have some overhead, which is
>>>>>>> exactly what someone is trying to avoid by using custom for loops.
>>>>>>>
>>>>>>> Personally, I like using a..b => tuple(a,b), since it also solves the
>>>>>>> multi-dimensional slicing and mixed indexing and slicing problems.
>>>>>>
>>>>>> Zero overhead. Tuples are flat compile-time entities.
>>>>>
>>>>> There are compile time tuples and runtime tuples. D already has a form
>>>>> of
>>>>> compile-time tuples. This discussion seems to be about runtime tuples
>>>>> which
>>>>> currently don't have a nice syntax: you have to use tuple(a,b). And
>>>>> tuple(a,b) does have runtime overhead.
>>>>
>>>> I think the point is that in something like this:
>>>>   auto foo = (a,b);
>>>>   foo.a += 2;
>>>>   foo.b += foo.a;
>>>>   // etc
>>>>
>>>> The tuple foo is allocated on the stack and the compiler knows where
>>>> the a part and b part are, so the code generated should be absolutely
>>>> no different from the code generated for:
>>>>
>>>>   auto foo_a = a;
>>>>   auto foo_b = b;
>>>>   foo_a += 2;
>>>>   foo_b += foo_a;
>>>>   // etc
>>>>
>>>> So there doesn't need to be any "tuple overhead".
>>>> --bb
>>>
>>>  But that isn't the expansion:
>>> for (int a = 0, b = 1; condition(); a++, b++) =>
>>>  int a = 0;
>>> int b = 0;
>>> while(condition) {
>>>    auto temp = tuple(a++,b++); // creation of a struct on the stack
>>> }
>>>  Now the optimizer might get rid of that temporary struct. Then again it
>>> might not (or its presence interferes with other optimizations). At the very
>>> least, some amount of code profiling or disassembly needs to be done.
>>
>> why would it create a struct?
>>
>> it would probably do:
>> int a = 0, b = 0;
>> while (condition) {
>>   int temp_a = (a++); // temp_a == a + 1
>>   int temp_b = (b++);
>> }
>>
>> the above would most like be optimized by away.
>>
>> you can also take advantage of tuples with for loops, something like:
>> for ( auto t = (0, 0); condition(); (t[1]++, t[2]++) ) {...}
>>
>> this is more flexible since you can't do with the current system:
>> for (int a = 0, char b = 'a'; ; ) {...}
>>
>> because "int a = 0" is a declaration and not an expression.
>>
>> with tuples:
>> for (auto t = (0, 'a'); ; ) {...}
>
> *sigh* The reason the compiler would have to create a temporary struct, is
> because that's what a tuple is at runtime. Tuples need to be compact (like
> structs) so that they can be passed to functions, etc.

Sigh back at ya.  I think all of us are just assuming that the
compiler will be smart enough to realize that the tuple value is not
being used and optimize it away.
It should be fairly trivial to detect and handle appropriately.  At
least in the case of that for loop there.  I think unused value
elimination is probably one of the first things you study in compiler
classes on optimization.  It must be because even *I* know about it
and I've only taken one compiler class that barely touched on
optimization at all.  :-)

--bb



More information about the Digitalmars-d mailing list