August 19, 2013
On Friday, 16 August 2013 at 23:48:53 UTC, bearophile wrote:
> Meta:
>
>> Andrei/Walter didn't want to merge that pull request without a full consideration of the different design issues involved, which in retrospect was a good decision.
>
> I agree that before adding some new syntax you have to think well.
>
>
>> - {a, b} is not as pretty, but it's not that bad of an alternative (though it may still have issues as well)
>
> It has technical issues, they were discussed in one of the last threads. Such problems should be added in a note in the DIP32, so they don't get lost in time.
>
>
>> - #(a, b) is unambiguous and would probably be the easiest option. I don't think it looks too bad, but some people might find it ugly and noisy
>
> It looks nice (but I don't know if it's technically usable), I have added it at the end of the list of alternative syntaxes:
> http://wiki.dlang.org/DIP32#Use_case_of_uniform_tuple_syntax
>
>
>> I personally think #(a, ?) or #(a, *) would be best, but all that's  really necessary is a symbol that cannot also be an identifier.
>
> I think ? is clear, unambiguous, etc, and I like it. The * is already used for pointers, product, dereferencing, ** is used for pow, so it's better to not add further meanings to it.
>
>
>> - Concatenating tuples with ~. This is nice to have, but not particularly important.
>
> In theory I like this operation, but in practice in my D code I don't need it often, so I think it should be left out, for later.
> In Python I sometimes concatenate tuples, but in such use cases they are essentially immutable dynamically typed arrays, losing their positional meaning.
>
>
> Tuples could also be used in switch/case statements, to support a very basic form of pattern matching. See also a standard method named "unapply" I have discussed a bit here, coming from Scala language, that is a very simple solution to solve a significant problem:
> http://d.puremagic.com/issues/show_bug.cgi?id=596
>
> Bye,
> bearophile

What about using : as people had intended to use the comma operator?
uint a, b;
(a : b) = (1 : 2);
(a : b) = tupleReturningFunction;
auto c = (1 : (2 : 3)); // A tuple containing a tuple
auto d = (1 : ((2 : 3) : (4 : 5))); // a tuple with a tuple of tuples as a member

auto assoc_array = [1 : (2 : 3)]; // A tuple associative value
auto assoc_array2 = [(1 : 2) : 3]; // A tuple associative key

auto ternary = value? (1 : 2) : (3 : 4); // tuple values in a ternary operator

It's nicer looking than #().
August 19, 2013
ixid:

> auto assoc_array = [1 : (2 : 3)]; // A tuple associative value
> auto assoc_array2 = [(1 : 2) : 3]; // A tuple associative key
>
> auto ternary = value? (1 : 2) : (3 : 4); // tuple values in a ternary operator
>
> It's nicer looking than #().

Are singleton tuples represented with (1:) ?

Bye,
bearophile
August 19, 2013
On 2013-08-19 17:04, Meta wrote:
> On Monday, 19 August 2013 at 21:03:50 UTC, Andrei Alexandrescu
> wrote:
>> b) syntactic support for ignoring certain members in a
>> destructuring - is that really needed?
>>
>> auto (a, ?, c) =
>> functionReturningTupleOrStaticArrayWith3Elements();
>
> In fairness, it is very common in other languages with pattern
> matching/destructuring. Off the top of my head I can think of
> Haskell, ML, Racket, Javascript (destructuring only) and Rust.

same in matlab. once destruction->auto assignment is available, (future) library functions will make heavy use of it, e.g. statistics functions returning lots of parameters/characteristics for a dataset. more often than not one is only interested in a few.

/det
August 19, 2013
On Monday, 19 August 2013 at 18:43:37 UTC, Meta wrote:
>> What does concatenating a tuple actually do?  That is:
>> auto a = #(1,2) ~ 3; //Result: a == #(1,2,3), right?
>> auto b = a ~ #(4,5); //Is  b == #(1,2,3,#(4,5)) or is b == #(1,2,3,4,5)?
>
> I think it should work the same as with arrays. So:
>
> auto a = #(1, 2) ~ 3; //Error: 3 is not a tuple
> auto a = #(1, 2) ~ #(3); //Result: #(1, 2, 3), just like an array
>
> auto b = a ~ #(4, 5); //Result: #(1, 2, 3, 4, 5). Again, like arrays.

I was being dumb, [1, 2] ~ 3 is of course valid for arrays, so that should work for tuples as well. Furthermore, #(1, 2) ~ "a" should be valid, and will result in #(1, 2, "a").

> I think keeping the same semantics as arrays would be the best way to do it. I think it nicely follows the principle of least astonishment. If you wanted to explicitly append a tuple and have it nested, you'd need to do:
>
> auto b = a ~ #(#(4, 5));
>
> Which is messy, but at least it's explicit about what is going on.

The tricky part of this that I forgot to mention is that you can't do this with arrays, so we're in unknown territory, but I think this is sensible. Again, it's quite ugly, but oh well.
August 19, 2013
On Monday, 19 August 2013 at 22:36:34 UTC, bearophile wrote:
> ixid:
>
>> auto assoc_array = [1 : (2 : 3)]; // A tuple associative value
>> auto assoc_array2 = [(1 : 2) : 3]; // A tuple associative key
>>
>> auto ternary = value? (1 : 2) : (3 : 4); // tuple values in a ternary operator
>>
>> It's nicer looking than #().
>
> Are singleton tuples represented with (1:) ?
>
> Bye,
> bearophile

Sure, why not? It looks happy enough. :) Are singleton tuples actually useful for anything?
August 19, 2013
ixid:

> Are singleton tuples actually useful for anything?

They are not much useful, but unless you want to outlaw them, you have to keep them in account when you design a syntax.

Bye,
bearophile
August 19, 2013
On Monday, 19 August 2013 at 18:40:58 UTC, H. S. Teoh wrote:
> Case in point. :)
>
> So we're actually talking at cross purposes here. Bearophile & Meta et
> al want native syntax for *runtime* tuples (i.e. std.typecons.Tuple --
> sorry for the mixup with std.range in my earlier posts), but you're
> talking about native syntax for alias tuples (aka TypeTuples). Two
> completely different things.

Now that I reread Kenji's DIP for a third time, I see/recall that his intention was for this syntax to be for alias tuples. In that case, wouldn't this necessitate a change in semantics? Will these alias tuples using built-in syntax still auto-expand?

> I agree that we shouldn't be making built-in syntax for a library type.
> If anything, any dedicated syntax should be reserved for alias tuples
> (aka std.typetuple.Typetuple). Or, at the very least, rename TypeTuple
> to AliasTuple.

I don't necessarily want built-in syntax for a library type, but making tuples first-class would be nice. I mean, it's a bummer that they can't be returned from functions. That should definitely be changed.

> Conflating these two concepts has led to endless confusion, which is why
> I insisted on addressing this issue before we even begin to talk about
> syntax. Otherwise we're going nowhere.
>
>
> T

August 19, 2013
On Monday, 19 August 2013 at 23:48:36 UTC, Meta wrote:
> ...

An addendum:

void main()
{
	//Prints 1
	writeln(func(TypeTuple!(1, 2)));
}

int func(int i, int j)
{
	return i;
}

This is bad and should never be allowed with some hypothetical tuple literal syntax. The desired behaviour is:

void main()
{
    //Error: func is not callable using argument types (#(int, int))
    writeln(func(#(1, 2));
}

*Unless* you use .expand/[] (pick your poison):

void main()
{
    writeln(func(#(1, 2).expand)); //Or #(1, 2)[]
}
August 20, 2013
On 8/19/13 4:48 PM, Meta wrote:
> I don't necessarily want built-in syntax for a library type, but making
> tuples first-class would be nice. I mean, it's a bummer that they can't
> be returned from functions. That should definitely be changed.

return tuple(1, "a");


Andrei

August 20, 2013
On Monday, 19 August 2013 at 23:55:32 UTC, Meta wrote:
> On Monday, 19 August 2013 at 23:48:36 UTC, Meta wrote:
>> ...
>
> An addendum:
>
> void main()
> {
> 	//Prints 1
> 	writeln(func(TypeTuple!(1, 2)));
> }
>
> int func(int i, int j)
> {
> 	return i;
> }
>
> This is bad and should never be allowed with some hypothetical tuple literal syntax. The desired behaviour is:
>
> void main()
> {
>     //Error: func is not callable using argument types (#(int, int))
>     writeln(func(#(1, 2));
> }
>
> *Unless* you use .expand/[] (pick your poison):
>
> void main()
> {
>     writeln(func(#(1, 2).expand)); //Or #(1, 2)[]
> }

No. No. Absolutely no. What you want is simply syntax sugar for std.typecons.Tuple - it is not worth any language change, contrary to semantical issues with built-in tuples. Auto-expansion and integration with function/template parameter lists is what makes D built-in tuple that useful and it should stay so with hypothetical tuple literals.