September 24, 2012
On Mon, Sep 24, 2012 at 12:46 PM, Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote:

> That said, I'm not necessarily opposed to the strict separation if we had a good candidate for built-in tuple literal syntax. But *if* the best we have is parens (and maybe there *is* something better?) then maybe this would be an acceptable way to achieve it?

If the problems in DIP 19 are deemed mostly syntactic (1- and 0-
element tuples), then maybe *for once* a simple syntax change could
solve them? I know syntax proposals are a dime a dozen in this
newsgroup, but why not here, to avoid the ((1)) problem?

For example choosing { 1, 2} to represent a tuple? { } blocks in D enclose semi-colon terminated declarations or expressions, but here it's enclosing comma-separated expressions. And, since { } is probably dangerous without a completly integrated type systems giving a type to all expressions (  (){} anyone?) , why not use (| 1, 2 |), or whatever syntax strikes our collective fancy? (I propose *not* to use < , >)

Then, the compiler has to change the way it prints its internal tuple, to follow the new syntax.

> Ie:
>
> // (3) is polysemous: Either int or (int)
> int   a = (3);  // Normal value
> (int) b = (3);  // One-element tuple
> auto  c = (3);  // Default to normal "int"?

For the third case, I'd say it defaults to a tuple. But then again, using another syntax solves this problem.

auto c  = (| 3 |); // or c = { 3 };
September 24, 2012
On 9/24/12 8:18 AM, Timon Gehr wrote:
> On 09/24/2012 05:25 AM, Andrei Alexandrescu wrote:
>> On 9/23/12 9:31 PM, deadalnix wrote:
>>> Le 24/09/2012 03:14, Andrei Alexandrescu a écrit :
>>>> On 9/23/12 7:20 PM, Adam D. Ruppe wrote:
>>>>> On Sunday, 23 September 2012 at 22:55:33 UTC, Timon Gehr wrote:
>>>>>> I believe it is currently left-to-right for D, in all kinds of
>>>>>> expressions, but DMD does not implement it yet.
>>>>>
>>>>> Yeah, I thought it was already defined.
>>>>
>>>> Actually it's right to left for assignments. In expr1 = expr2, expr2
>>>> gets evaluated first.
>>>>
>>>> Andrei
>>>
>>> Is it by implementation or by design ?
>>
>> Currently probably neither :o). I used to oppose it, then I figured it's
>> actually nice because of things like:
>>
>> int[int] stuff;
>> stuff[42] = stuff.length;
>>
>>
>> Andrei
>
> So you are arguing for computing the arguments for a method call before
> the receiver is computed? (What about UFCS?) Or should opAssign behave
> specially?

Ha, good point about opAssign! Probably we should go with left-to-right everywhere, including in assignment.

Andrei
September 24, 2012
>> The analysis in there fails to construct a case even half strong that deprecating the comma operator could significantly help tuples.
>
> That is because it does not base the discussion on the right
> limitations of built-in tuples:
>
> auto (a,b) = (1,"3");
> (auto a, string b) = (1, "3");

Agreed, this is the key thing missing from D.

There is also no consideration in the DIP of what I consider one of D's most confusing "features": "pre-expanded tuples" or in other words, type tuples. These beasts can be very confusing when first encountered, and they do not behave like any data type in any other language I know of:

import std.typecons; // Contains Tuple!(...), which reminds me,
// how do I know which module contains a given feature?
// http://dlang.org/phobos/index.html doesn't mention it.
void call() { humm(1, 2); }

void humm(T...)(T x)           // x, a pre-expanded tuple
{
	//auto c = [x.expand]; // ERROR, expand undefined
	                       // (it's already expanded!)
	auto a = x;            // a is also pre-expanded
	auto b = [ a, a ];     // int[], not Tuple!(int,int)[]
	//int d = derr(x);     // ERROR, have to un-expand it
	writeln(a);            // "12"
	writeln(b);            // "[1, 2, 1, 2]"
}
int derr(Tuple!(int,int) a) { return a[0] + a[1]; }

I know you guys are all used to this behavior but I'm telling you, pre-expanding is very weird. It would be nice if type tuples could somehow be unified with library tuples and behave like the latter.
September 24, 2012
On Monday, 24 September 2012 at 10:05:18 UTC, Nick Sabalausky wrote:
> On Mon, 24 Sep 2012 10:56:40 +0200
> Jacob Carlborg <doob@me.com> wrote:
>
>> On 2012-09-24 07:01, Nick Sabalausky wrote:
>> 
>> > I think one of us is missing something, and I'm not entirely sure
>> > who.
>> >
>> > As I explained (perhaps poorly), the zero- and one-element tuples
>> > *would still be* tuples. They would just be implicitly convertible
>> > to non-tuple form *if* needed, and vice versa. Do you see a reason
>> > why that would *necessarily* not be the case?
>> 
>> Would that mean you could start doing things like:
>> 
>> int a = 3;
>> int b = a[0];
>> 
>> That feels very weird.
>> 
>
> No, because there's nothing typed (int) involved there. But you could do
> this:
>
>     int a = 3;
>     (int) b = a;
>     a = b;
>
> Or this:
>
>     void foo((int) a)
>     {
>         int b1 = a[0];
>         int b2 = a;
>     }
>     int c = 3;
>     foo(c);

What's the point than?
here's equivalent code without this "feature":

int a = 3;
(int) b = (a); // explicitly make 1-tuple
(a) = b; // unpacking syntax

void foo((int) a) {
  int b1 = a[0];
  (int b2) = a; // one possible syntax
}
int c = 3;
foo ((c));
September 24, 2012
On Mon, 24 Sep 2012 01:01:29 -0400, Nick Sabalausky <SeeWebsiteToContactMe@semitwist.com> wrote:

> On Sun, 23 Sep 2012 18:48:22 -0400
> Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>> Once a one-element tuple becomes equivalent to the actual item,
>> there's an explosion of trouble and special cases in the language and
>> in code that uses it. For example, divide and conquer code that
>> manipulates tuples and takes t[0 .. $/2] and t[$/2+1 .. $] would
>> suddenly get to cases in which the slices are no longer tuples, and
>> so on. And that's only the beginning.
>>
>
> I think one of us is missing something, and I'm not entirely sure
> who.
>
> As I explained (perhaps poorly), the zero- and one-element tuples *would
> still be* tuples. They would just be implicitly convertible to
> non-tuple form *if* needed, and vice versa. Do you see a reason why
> that would *necessarily* not be the case?

(int[]) x;

int a = x.length;

is a == 0 or 1?

I agree with Andrei, we need something different.

I don't profess to be even close to an expert on tuples, but I feel they should be built-in to the language, since they are actually language constructs that we are declaring types for.

Without any research or investigation, what about using a different set of delimiters for tuples?  Like {1,2,3}

Right now, I think that is reserved for static struct initializers.  But can't those be considered a tuple also?  Someone will probably destroy this 10 milliseconds after I send it :)

-Steve
September 24, 2012
On Monday, 24 September 2012 at 10:20:01 UTC, Nick Sabalausky wrote:
> On Mon, 24 Sep 2012 10:47:38 +0200
> "foobar" <foo@bar.com> wrote:
>> 
>> Nope.
>> One of the ways in math to "build" the positive numbers based on set theory is via singletons:
>> n := |tuple of empty tuples|
>> so "1" is defined as { {} } whereas "0" is simply {}. That does not work with the above suggestion. Now, I realize this is an arguably convoluted math example but it does show that the treating { {} } as {} is limiting the expressive power of tuples.
>> 
>
> And int's are limiting compared to mathematical integers. So what?
> So ok, maybe this is limiting from a theoretical standpoint. But
> practically speaking? I dunno. We're not making tuples to emulate
> set theory here, we're just looking for ad-hoc anonymous structs.
>
> Besides, I only said they were logically the same thing, not
> mechanically. I'm only suggesting that a one-element tuple be implicitly
> convertible to/from the type of its element. So there would likely
> still be the different types, it just makes sense that you should be
> able to use one as the other.

I'm a bit confused about what is specifically proposed here:
- Is the suggestion to limit tuples to >1 elements? *This* I'm against for practical as well as completeness reasons. Andrei already provided one example, and another would be a proper unit type. e.g.
void foo(int a) {}
void bar (int b) { return foo(b); }
- Is the suggestion to allow implicit conversion between (T) and T?
This brings almost no benefit - (you save two keystrokes?) and adds a special case to the language. The added complexity really does not justify this.
September 24, 2012
On 9/24/12 1:01 AM, Nick Sabalausky wrote:
> On Sun, 23 Sep 2012 18:48:22 -0400
> Andrei Alexandrescu<SeeWebsiteForEmail@erdani.org>  wrote:
>>
>> Once a one-element tuple becomes equivalent to the actual item,
>> there's an explosion of trouble and special cases in the language and
>> in code that uses it. For example, divide and conquer code that
>> manipulates tuples and takes t[0 .. $/2] and t[$/2+1 .. $] would
>> suddenly get to cases in which the slices are no longer tuples, and
>> so on. And that's only the beginning.
>>
>
> I think one of us is missing something, and I'm not entirely sure
> who.
>
> As I explained (perhaps poorly), the zero- and one-element tuples *would
> still be* tuples. They would just be implicitly convertible to
> non-tuple form *if* needed, and vice versa. Do you see a reason why
> that would *necessarily* not be the case?

It just creates endless little problems and confusion coming outta the woodwork, as others have pointed out in response to this. There are languages that have also explored a similar approach - a value can be automatically converted to a one-element array and vice versa. It's problematic, especially in a language with generics and function overloading.

>> I think it's safe to just not even discuss it.
>
> A nice way to put it :/  Part politician perhaps? ;)

I meant it in a simple and forward way - all I want is to save time and trouble in exploring a no-win design. From sheer experience gathered from years at hacking at this stuff I know this can be done but is not worth the trouble. Since it can be done, there's no argument that would definitively close the discussion, and that demotivates me from coming up with explanations.


Andrei
September 24, 2012
On 9/24/12 4:17 AM, Don Clugston wrote:
> Regarding the comma operator: I'd love to deprecate it, but even if we
> don't, could we at least ensure that this kind of rubbish doesn't compile:
>
> void main()
> {
> int x;
> x > 0, x += 5;
> }
>
> At present, because comma expressions are expressions, not statements,
> the "x > 0" doesn't generate a "statement has no effect" error, despite
> the fact that it is meaningless and gets completely discarded.

Interesting. The comma operator is probably the only one in which an expression is evaluated only for the sake of its side effects. So eliminating the comma operator would just get rid of that case by design.

Of course, there's always the option of adding more checks or rewriting the comma operator from "expr1, expr2, expr3" to "{ expr1; expr2; return expr3; }()".


Andrei
September 24, 2012
On Monday, 24 September 2012 at 14:52:21 UTC, Steven Schveighoffer wrote:
>
> (int[]) x;
>
> int a = x.length;
>
> is a == 0 or 1?
>
> I agree with Andrei, we need something different.


This is exactly the question I was going to ask ...

>
> I don't profess to be even close to an expert on tuples, but I feel they should be built-in to the language, since they are actually language constructs that we are declaring types for.
>
> Without any research or investigation, what about using a different set of delimiters for tuples?  Like {1,2,3}

... and exactly the syntax I was going to propose! {} is already used in C languages for heterogeneous data structures(structs/classes, JSON etc). Using () creates too many special cases, especially in generic programming and seeing how other languages are dealing with them we'd rather avoid them from the very beginning.

> Right now, I think that is reserved for static struct initializers.  But can't those be considered a tuple also?  Someone will probably destroy this 10 milliseconds after I send it :)
>
> -Steve

It would be awesome if we could make tuples generic initializers for various data types in D. Not just structs but for instance arrays:

int[] a = {1, 2, 3, 4};

Compiler possesses enough type information to know that this tuple could be converted to the int[].

P.S. The only collision I see with {} is a delegate literal, but to be honest it's not worth the merit and quite confusing in fact. There are 3 other ways to define a delegate in D which will cover all of the user's needs.
September 24, 2012
On 9/24/12 9:27 AM, Philippe Sigaud wrote:
> On Mon, Sep 24, 2012 at 12:46 PM, Nick Sabalausky
> <SeeWebsiteToContactMe@semitwist.com>  wrote:
>
>> That said, I'm not necessarily opposed to the strict separation if we
>> had a good candidate for built-in tuple literal syntax. But *if* the
>> best we have is parens (and maybe there *is* something better?) then
>> maybe this would be an acceptable way to achieve it?
>
> If the problems in DIP 19 are deemed mostly syntactic (1- and 0-
> element tuples), then maybe *for once* a simple syntax change could
> solve them? I know syntax proposals are a dime a dozen in this
> newsgroup, but why not here, to avoid the ((1)) problem?
>
> For example choosing { 1, 2} to represent a tuple? { } blocks in D
> enclose semi-colon terminated declarations or expressions, but here
> it's enclosing comma-separated expressions. And, since { } is probably
> dangerous without a completly integrated type systems giving a type to
> all expressions (  (){} anyone?) , why not use (| 1, 2 |), or whatever
> syntax strikes our collective fancy? (I propose *not* to use<  ,>)
>
> Then, the compiler has to change the way it prints its internal tuple,
> to follow the new syntax.
>
>> Ie:
>>
>> // (3) is polysemous: Either int or (int)
>> int   a = (3);  // Normal value
>> (int) b = (3);  // One-element tuple
>> auto  c = (3);  // Default to normal "int"?
>
> For the third case, I'd say it defaults to a tuple. But then again,
> using another syntax solves this problem.
>
> auto c  = (| 3 |); // or c = { 3 };

I think my main problem with this is that I'm perfectly happy with the baseline, which has "tuple(" as the left delimiter and ")" as the right delimiter. I'd be more excited to invent notation if there was overwhelming or at least considerable evidence that the notation considerably helps certain use cases, or is very frequent. As things are, I'd be quite "meh" about suddenly adding lenses.

Andrei