October 07, 2010
On 7/10/2010 5:04 PM, Walter Bright wrote:
> There have been a couple of looong threads about tuples:
>
> http://www.digitalmars.com/d/archives/digitalmars/D/Reddit_why_aren_t_people_using_D_93528.html
>
> http://www.digitalmars.com/d/archives/digitalmars/D/Should_the_comma_operator_be_removed_in_D2_101321.html
>
> A lot of it foundered on what the syntax for tuple literals should be.
> The top of the list is simply enclosing them in ( ). The problem with
> this is

Walter, please define exactly what a tuple is as being, both
in the context of your post and (presumably) in the D type system.

Without a precise definition of exactly what a tuple is,
your post will at best elucidate responses that also lack a
precise understanding of a tuple is (supposed to be).

There are already a number of responses to your post that focus
on syntax and without any semantic foundation.

Regards,
Justin Johansson
October 07, 2010
retard Wrote:


> Why do tuple fields need a name? Isn't this a new ad-hoc way to introduce structural typing in D? I often start with tuples, but if it turns out that the value is used in many places, it will be eventually replaced with a struct (e.g. coordinates in a gui / gamedev) for better type safety. Even with structs the need for field names is very rare. The real need for tuples is in very special cases where the syntax needs to be light.

I found they are useful for callbacks, when you can put, in a tuple, the delegate or function to the callback
 and in another nested tuple the delegate/function parameters.

This way you can define the callbacks to be used along with their parameters, even if their signature is different.

You could do the same with the callbacks having variable number and types of args, using a template, but I like this way more.

October 07, 2010
I might be missing something, but how does this proposal get around the ambiguity in

(a,b,c)[0]

?

Currently, it's valid C syntax and valid D syntax. In your proposal it would be valid tuple syntax too.

On 10/07/2010 01:04 AM, Walter Bright wrote:
> There have been a couple of looong threads about tuples:
>
> http://www.digitalmars.com/d/archives/digitalmars/D/Reddit_why_aren_t_people_using_D_93528.html
>
>
> http://www.digitalmars.com/d/archives/digitalmars/D/Should_the_comma_operator_be_removed_in_D2_101321.html
>
>
> A lot of it foundered on what the syntax for tuple literals should be.
> The top of the list is simply enclosing them in ( ). The problem with
> this is
>
> (expression)
>
> Is that a parenthesized expression, or a tuple? This really matters,
> since (e)[0] means very different things for the two. Finally, I got to
> thinking, why not just make it a special case:
>
>
> ( ) == tuple
> (a) == parenthesized expression
> (a,b) == tuple
> (a,b,c) == tuple
> (a,b,c,d) == tuple
>
> etc.
>
> No ambiguities! Only one special case. I submit this special case is
> rare, because who wants to define a function that returns a tuple of 1?
> Such will come about from generative programming, but:
>
> (a,b,c)[0]
>
> may be how the generative programming works, and that suggests:
>
> (a,0)[0]
>
> as how a user could generate a tuple of 1. Awkward, sure, but like I
> said, I think this would be rare.
October 07, 2010
On 8/10/2010 12:23 AM, Ellery Newcomer wrote:
> I might be missing something, but how does this proposal get around the
> ambiguity in
>
> (a,b,c)[0]
>
> ?
>
> Currently, it's valid C syntax and valid D syntax. In your proposal it
> would be valid tuple syntax too.

Sorry Ellery but you, as others, are also focusing on syntax and not
a semantic foundation for what tuples are.  I note that bearophile
makes similar points about the meaning of tuples in a latter post.

Without understanding what the meaning of tuples is and what they
might be good for, it (imho) doesn't make sense to enter into
syntactic arguments.

Justin

October 07, 2010
Walter Bright <newshound2@digitalmars.com> wrote:

> (a,b,c)[0]
>
> may be how the generative programming works, and that suggests:
>
> (a,0)[0]
>
> as how a user could generate a tuple of 1. Awkward, sure, but like I said, I think this would be rare.

Wouldn't (a,0)[0] currently return a, not (a)? The syntax that behaves
as you describe would be slicing: (a,0)[0..1].

This said, read bearophile's post "Re: Tuple literal syntax + Tuple
assignment". It seems well thought-out, and I agree with all his
points.

-- 
Simen
October 07, 2010
On 10/7/10 5:39 CDT, retard wrote:
> Thu, 07 Oct 2010 03:20:23 -0500, Andrei Alexandrescu wrote:
>
>> Sorry for being Debbie Downer in this thread, but I'm not seeing a lot
>> of progress here. This is nothing but a syntax cutesy that helps
>> Tuple!(A, B) and tuple(a, b) and leaves all other issues related to
>> tuples unresolved (I'm actually afraid that it exacerbates them).
>>
>> One good thing about Tuple is that it allows names of fields, so
>> functions can return tuples with conveniently named fields, e.g.
>> Tuple!(bool, "found", size_t, "position") etc. without having to define
>> little structs everywhere and fostering simple, clear code on the caller
>> side.
>
> Why do tuple fields need a name?

They don't always need, but oftentimes names are better than numeric constants.

> Isn't this a new ad-hoc way to introduce
> structural typing in D?

Well what is the old ad-hoc way? Anyhow, tuples are a prime candidate for structural typing. Currently Tuple does not support it.

> I often start with tuples, but if it turns out
> that the value is used in many places, it will be eventually replaced
> with a struct (e.g. coordinates in a gui / gamedev) for better type
> safety.

I don't see

struct Coord
{
    int x, y, z;
}

one iota typesafer than

alias Tuple!(int, "x", int, "y", int, "z") Coord;

Clearly if you want to introduce protection, methods etc. then struct/class is the way to go. Tuples have their charter.

> Even with structs the need for field names is very rare.

I don't know how to define a struct without naming its fields in C, C++, C#, or D. If I could, I'd seldom want to use magic indexes instead of descriptive names.

> The real
> need for tuples is in very special cases where the syntax needs to be
> light.

auto r = fun(42);
writeln(r.foo, ": ", r.bar);

On the client side the syntax is very light. The definition of the function would need to specify the type name:

Tuple!(int, "foo", string, "bar") fun(int) {
    ...
}

I think much of the list of grievances against tuple limitations stems from a feeling that doing tuples without special syntax is "cheating". For my money, library tuples are eminently usable, and once we fix a couple of compiler bugs, they will be as good as (if not simpler, richer, and clearer than) a built-in facility. I do want to introduce syntax for expansion a la

auto (a, b) = foo(42);

because that's a common need that's not satisfiable via a library. But then I want to define the syntax in a general way so it works not only with tuples, but also with arrays and types that implement opIndex.


Andrei
October 07, 2010
Le 07/10/2010 09:44, Juanjo Alvarez a écrit :
> On Wed, 06 Oct 2010 23:04:35 -0700, Walter Bright
> <newshound2@digitalmars.com> wrote:
>> (a,0)[0]
>
>
>
>
>> as how a user could generate a tuple of 1. Awkward, sure, but like
> I said, I
>> think this would be rare.
>
> Python uses:
>
> (5,)
> Which is a lot better IMHO

Vote++;
October 07, 2010
On 10/7/10 7:23 CDT, Justin Johansson wrote:
> On 7/10/2010 5:04 PM, Walter Bright wrote:
>> There have been a couple of looong threads about tuples:
>>
>> http://www.digitalmars.com/d/archives/digitalmars/D/Reddit_why_aren_t_people_using_D_93528.html
>>
>>
>> http://www.digitalmars.com/d/archives/digitalmars/D/Should_the_comma_operator_be_removed_in_D2_101321.html
>>
>>
>> A lot of it foundered on what the syntax for tuple literals should be.
>> The top of the list is simply enclosing them in ( ). The problem with
>> this is
>
> Walter, please define exactly what a tuple is as being, both
> in the context of your post and (presumably) in the D type system.
>
> Without a precise definition of exactly what a tuple is,
> your post will at best elucidate responses that also lack a
> precise understanding of a tuple is (supposed to be).
>
> There are already a number of responses to your post that focus
> on syntax and without any semantic foundation.

Wise words! It was exactly what I protested against. It discusses syntax without attacking any of the actual issues.

Andrei
October 07, 2010
On 2010-10-07 04:20:23 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said:

> Sorry for being Debbie Downer in this thread, but I'm not seeing a lot of progress here. This is nothing but a syntax cutesy that helps Tuple!(A, B) and tuple(a, b) and leaves all other issues related to tuples unresolved (I'm actually afraid that it exacerbates them).
> 
> One good thing about Tuple is that it allows names of fields, so functions can return tuples with conveniently named fields, e.g. Tuple!(bool, "found", size_t, "position") etc. without having to define little structs everywhere and fostering simple, clear code on the caller side.

I've always found tuples with named arguments awkward. I mean, a tuple is a list of


> Also, obviously, empty tuples and tuples with one element are self-explanatory (Tuple!() and Tuple!(int) for types, tuple() and tuple(4) for values).

And then you have TypeTuple!(...) for tuples of types or statically-known values. The basic problem is that all these different syntaxes define slight variations of the same core tuple concept.

Giving a true syntax for tuples makes things *simpler* by reducing these variations. For instance, a TypeTuple!(int, int) isn't the same thing as Tuple!(int, int). Why is it so? Because of an implementation detail: one defines the core language tuple and the other defines a wrapper struct around the core tuple that implements what's basically missing in the core tuple implementation (returning from a function).

With Walter changes I expect you'll be able to call a function this way (simply because this is actually what happens when you use a real tuple in D):

	auto a = (1, 2);
	func(a); // same as func(a[0], a[1]);

Or you could have some kind of filter function that takes arbitrary arguments and transform them somehow before passing them to another function. For instance:

	auto square(T...)(T tuple) {
		foreach (ref element; tuple)
			element ^= 2;
		return tuple;
	}

	writefln("%d %d %d %d %d", square(1,2,3,4,5)); // prints "1 4 9 16 25"

I'm not inventing anything. This is exactly how the core language tuples work today in D. It's already possible to have core language tuples in variables (try creating a variable of type TypeTuple!(int, int), it works!). The only two things Walter is proposing to implement is tuple literals and tuple returns for functions.

And, if I'm guessing right, this syntax will also work:

	int a;
	float b;
	(a, b) = func(); // func returns a (int, float) which is directly
	                 // stored in the right variables

This has been proven very useful in languages that supports it; heck, even C++ has this feature with boost::tie. I assume it'll work because, well, it already works if the tuple isn't the return value of a function call:

	TypeTuple!(a, b) = TypeTuple!(1, 2);
	TypeTuple!(a, b) = tuple(1, 2).fields;


> Up until recently the syntax t[i] didn't work for tuples, forcing t.field[i]. This marginally improves usage of tuples. There are still other issues left due to compiler bugs; for example slicing t[a .. b] is supposed to work but it doesn't. But my question is, do we need more notation, more special cases, more ambiguities, more solution to ambiguities, more corner cases (there's already a request for handling void in a particular way)...? And for what? Quite literally because we refuse to call a tuple a tuple? I'm not seeing much gain here. Syntactic sugar is good in moderate quantities, but in Perlis' words this is bound to cause cancer of the semicolon.

I find it hard to see how obsoleting one of the two tuple concepts (the one in Phobos) and keeping only the core language tuple will introduce more bugs. The tuple concept is already at the core of the language, and it is quite needed there too for metaprogramming an other stuff. We can't remove it, so let's improve it instead of layering a wrapper over it, giving it same name, and making things more confusing for everyone.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

October 07, 2010
Thu, 07 Oct 2010 09:46:59 -0500, Andrei Alexandrescu wrote:

> On 10/7/10 5:39 CDT, retard wrote:
>> Thu, 07 Oct 2010 03:20:23 -0500, Andrei Alexandrescu wrote:
>>
>>> Sorry for being Debbie Downer in this thread, but I'm not seeing a lot
>>> of progress here. This is nothing but a syntax cutesy that helps
>>> Tuple!(A, B) and tuple(a, b) and leaves all other issues related to
>>> tuples unresolved (I'm actually afraid that it exacerbates them).
>>>
>>> One good thing about Tuple is that it allows names of fields, so functions can return tuples with conveniently named fields, e.g. Tuple!(bool, "found", size_t, "position") etc. without having to define little structs everywhere and fostering simple, clear code on the caller side.
>>
>> Why do tuple fields need a name?
> 
> They don't always need, but oftentimes names are better than numeric constants.

If some compile time voodoo isn't used, the names have an effect on the performance (runtime lookups).

> 
>> Isn't this a new ad-hoc way to introduce structural typing in D?
> 
> Well what is the old ad-hoc way? Anyhow, tuples are a prime candidate for structural typing. Currently Tuple does not support it.

I have nothing against the structural typing of tuples, per se. I meant structural typing in the sense that Scala implements it -- a set of name- value pairs constructs a new type. It seems to require runtime dictionaries in their implementation.

> 
>> I often start with tuples, but if it turns out that the value is used in many places, it will be eventually replaced with a struct (e.g. coordinates in a gui / gamedev) for better type safety.
> 
> I don't see
> 
> struct Coord
> {
>      int x, y, z;
> }
> 
> one iota typesafer than
> 
> alias Tuple!(int, "x", int, "y", int, "z") Coord;

I meant the naming of the aggregate vs not naming it. Passing around n- tuples without any name associated for the concept allows mixing n-tuples if the internal type structure matches. Sometimes I want to distinguish between the uses. Clearly some coordinate in the game world shouldn't automatically be applicable in the GUI context:

struct GameCoord {
  int x,y,z;
}

struct GUICoord {
  int x,y,z;
}

// void drawOval(GUICoord); // fun prototype

GameCoord a;
drawOval(a); // bang

This might lead to bugs if the compiler silently accepts a wrong aggregate.

>> Even with structs the need for field names is very rare.
> 
> I don't know how to define a struct without naming its fields in C, C++, C#, or D. If I could, I'd seldom want to use magic indexes instead of descriptive names.

I didn't know what the template creates. I had an impression that it creates an array of strings for some runtime purposes, like:

foreach(value; tuple) {
  writefln("%s is %s", value.name, value);
}

So I was just refering to those runtime string literals. Maybe I confused this with some enum related template.


>> The real
>> need for tuples is in very special cases where the syntax needs to be
>> light.
> 
> auto r = fun(42);
> writeln(r.foo, ": ", r.bar);
> 
> On the client side the syntax is very light. The definition of the function would need to specify the type name:
> 
> Tuple!(int, "foo", string, "bar") fun(int) {
>      ...
> }

We have an issue with terminology here. To me that isn't a *tuple*, it's a record! A tuple would let you choose the variable names on the client side:

auto (foo, bar) = fun(42);

writeln(foo, ": ", bar);