September 26, 2012
On 25-Sep-12 23:29, kenji hara wrote:
> My suggestion is very simple.
> 1. Change all words "built-in tuple" in the documentation to "built-in
> sequence". Then, in the D language world, we can have clarify name for
> the built-in one.
> 2. Introduce new templates, Seq, TypeSeq, and ExpSeq.
>
>      template Seq(T...) { alias T Seq; }    // identical with
> std.typetuple.TypeTuple
>      template TypeSeq(T...) if (allSatisfy!(isType, T)) { alias T TypeSeq; }
>      template ExpSeq(T...) if (allSatisfy!(isExpression, T)) { alias T ExpSeq; }
>
>    If you really want to a sequence with heterogeneous elements, use
> Seq template. Otherwise use TypeSeq or ExpSeq based on your purpose.
>
vote++;

-- 
Dmitry Olshansky
September 26, 2012
> Also, I want to add that type declarations should be changed from statements to expressions so that we could do:
> auto tup = (3, "hello");
> (int num, string s) = tup; // num == 3, s == "hello"

+1.

or

int num;
string s;
auto tup = (3, "hello");

(num, s) = tup;

or like x++ containers http://msdn.microsoft.com/en-us/library/aa874816.aspx

auto tup = [3, "hello"];

[num, s] = tup;

In general it's very useful.
September 26, 2012
On Tuesday, 25 September 2012 at 21:02:49 UTC, Andrei Alexandrescu wrote:
>
> I agree. That's why I want to take the minimum amount of steps to make library tuples work. That minimum amount may be 1, i.e. just implement deconstruction.
>
> Andrei

Library tuples have broken semantics.
Tuples supposed to have _structural_ typing which AFAIK can only be correctly implemented in language.

import std.typecons.TypeTuple;

struct MyTuple(T...)() {}

auto libTup = tuple(123, "hello");
MyTuple myTup = libTup; // broken

This is broken cause structs in D are nominally typed and even though both pack the same inner-types, they are not equal.
The problem with the lib solution is the confusion and broken semantics, _not_ the "tuple()" syntax. Sure, it's long and annoying to type for a [should be] common construct, but tuple *is* clear and readable, as you pointed out yourself. So syntax wise, I'm fine with both tuple(...) and a shorter syntax with some sort of parens-like character. But please, let's get at least the semantics absolutely right.

I don't have a good suggestion how to fix this with no or minimal code breakage, but I don't thing that adding broken features the the mix helps any.
September 26, 2012
On Wednesday, September 26, 2012 21:54:44 foobar wrote:
> Library tuples have broken semantics.
> Tuples supposed to have _structural_ typing which AFAIK can only
> be correctly implemented in language.
> 
> import std.typecons.TypeTuple;
> 
> struct MyTuple(T...)() {}
> 
> auto libTup = tuple(123, "hello");
> MyTuple myTup = libTup; // broken
> 
> This is broken cause structs in D are nominally typed and even though both pack the same inner-types, they are not equal.

Of course, they're not equal. One is a Tuple and one is a MyTuple. Why on earth would you expect them to be considered equal? Just use Tuple. And it's not like you'd be using MyTuple if tuples were built-in. You'd just use the built-in tuples. So, this really makes no sense to me at all.

- Jonathan M Davis
September 26, 2012
Jonathan M Davis:

> So, this really makes no sense to me at all.

I agree that foobar examples aren't so good. But it's true that Tuple() gives some troubles regarding missed structural typing:


import std.stdio, std.typecons;
alias Tuple!(float, float) T1;
alias Tuple!(float,"x", float,"y") T2;
void foo1(T1 t) {}
void foo2(T2 t) {}
void main() {
    auto p1 = T1(1, 2);
    auto p2 = T2(1, 2);
    p1 = p2; // no error
    p2 = p1; // no error
    T1[] a1;
    T2[] a2;
    a1 = a2; // error
    a2 = a1; // error
    foo1(p2); // error
    foo2(p1); // error
}


Generally I think "p1 = p2;" is OK, while "p2 = p1;" is not so good, because T2 is more specialized.

There are several other more or less similar things related to structural typing of tuples that a well implemented built-in tuple type will need to address. In Bugzilla there are some open bug reports on similar matters. Fixing them with the library defined tuples is hard. Of course a possible solution is to improve the D language to allow the programmer to specify very good struct-based tuples in library code, I think but doing this is more complex than implementing good built-in tuples.

Bye,
bearophile
September 26, 2012
On Thursday, September 27, 2012 00:05:41 bearophile wrote:
> Jonathan M Davis:
> > So, this really makes no sense to me at all.
> 
> I agree that foobar examples aren't so good. But it's true that Tuple() gives some troubles regarding missed structural typing:
> 
> 
> import std.stdio, std.typecons;
> alias Tuple!(float, float) T1;
> alias Tuple!(float,"x", float,"y") T2;
> void foo1(T1 t) {}
> void foo2(T2 t) {}
> void main() {
> auto p1 = T1(1, 2);
> auto p2 = T2(1, 2);
> p1 = p2; // no error
> p2 = p1; // no error
> T1[] a1;
> T2[] a2;
> a1 = a2; // error
> a2 = a1; // error
> foo1(p2); // error
> foo2(p1); // error
> }
> 
> 
> Generally I think "p1 = p2;" is OK, while "p2 = p1;" is not so good, because T2 is more specialized.
> 
> There are several other more or less similar things related to structural typing of tuples that a well implemented built-in tuple type will need to address. In Bugzilla there are some open bug reports on similar matters. Fixing them with the library defined tuples is hard. Of course a possible solution is to improve the D language to allow the programmer to specify very good struct-based tuples in library code, I think but doing this is more complex than implementing good built-in tuples.

It sounds to me like the reason that structural typing is needed is because Tuple allows you to name its fields, which I've always thought was a bad idea, and which a built-in tuple definitely wouldn't do. If you couldn't name its fields, then any Tuple containing the same sequence of types would be the same type. So, the problem is caused by a feature that built-in tuples wouldn't even have.

- Jonathan M Davis
September 26, 2012
Jonathan M Davis:

> It sounds to me like the reason that structural typing is needed is because
> Tuple allows you to name its fields, which I've always thought was a bad idea,

I have appreciated named fields of D tuples since the beginning, I have found them quite handy. With them sometimes you don't need to unpack a tuple, you can just access its fields with a nice name, avoiding to move around more than one variable.

In Python there are build-in tuples, and there is a library-defined tuple type that supports names for its fields, it even contains its name, so when you print one of them, it's able to offer a nice textual representation:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', 'x y')
>>> Point(5, 10)
Point(x=5, y=10)

Bye,
bearophile
September 26, 2012
> I have appreciated named fields of D tuples since the beginning, I have found them quite handy. With them sometimes you don't need to unpack a tuple, you can just access its fields with a nice name, avoiding to move around more than one variable.

In Haskell to solve this problem there is the @ syntax for tuples. As an example usage, this Haskell function vNorm normalizes a Vec (a 2D vector). Its input is a Vec, that is unpacked in its x and y fields, but vNorm al gives a name to the whole input Vec, naming it 'v'. So you are able to call the other function vLen with no need to pack again x and y in a Vec:

vLen :: Vec -> Double
vLen x = sqrt $ vDot x x

vNorm :: Vec -> Vec
vNorm v@(Vec x y) = Vec (x / l) (y / l) where l = vLen v

(In my first post in this thread I have not listed such extra features for tuples because I think they are less important than a good unpacking syntax in those four cases.)

Bye,
bearophile
September 26, 2012
Jonathan M Davis wrote:
> It sounds to me like the reason that structural typing is needed is because
> Tuple allows you to name its fields, which I've always thought was a bad idea,
> and which a built-in tuple definitely wouldn't do. If you couldn't name its
> fields, then any Tuple containing the same sequence of types would be the same
> type. So, the problem is caused by a feature that built-in tuples wouldn't
> even have.

Exactly my PoV. I think that "tuples with named fields" should be anonymous structs and pure tuples shouldn't have named fields.
September 27, 2012
On 2012-09-27 00:38, bearophile wrote:

> I have appreciated named fields of D tuples since the beginning, I have
> found them quite handy. With them sometimes you don't need to unpack a
> tuple, you can just access its fields with a nice name, avoiding to move
> around more than one variable.

If you could do something like this:

auto x, y = tuple(1, 2);

Wouldn't that be an acceptable solution instead?

-- 
/Jacob Carlborg