Skip to content

Conversation

ghost
Copy link

@ghost ghost commented Sep 19, 2013

@bearophile
Copy link

This is yet another way/syntax to build a tuple in D+Phobos. Instead of piling more make-up layers on the library tuples, it's better to add good built-in tuples to D... sorry.

@ghost
Copy link
Author

ghost commented Sep 19, 2013

Well by the time the language syntax is finished and tuples become a first-class feature another year will pass, and then another extra year will pass before the bugs are ironed out.

Anywho, I thought improving the usability of the library tuple with a 12-line diff would give us something that's neat and usable today. It's already been 6 months (Edit: Excuse me, it's actually been 2 years since the pull was even made) since the last attempt at a language tuple implementation (pull), and there's still no signs of a decision on the syntax of tuples.

Meanwhile we currently have to live with:

return Tuple!(int, "x", string "y", int delegate(int), "square")(x, y, square);

And a 12-line diff changes that to:

return tuple!(x, y, square);

Edit: Yeah, you can also use cast(typeof(return)) and aliases, but it's still ugly and requires more typing.

while retaining the names of the symbols. The symbols can be accessed via
their original names as they become members of a struct.
*/
auto tuple(syms...)()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tuple.parseSpecs takes care of more detailed errors, but NameTypePairs will give a poor error when given types, so this overload should probably be constrained with isExpressionTuple!syms (assuming that isExpressionTuple is false if there are any types mixed in with any expressions; the documentation doesn't say).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need an isVariable trait. isExpressionTuple will also pass for tuple!("foo"), but this code won't work.

@JakobOvrum
Copy link
Contributor

Words and phrases like "you" and "this is" is generally a good indication that it's not a good description for documentation purposes.

How about something like:

Constructs a tuple from the given variables, where each variable in the tuple is accessible through its original variable name as named members of the tuple. Members can still be accessed by indexing.

@ghost
Copy link
Author

ghost commented Sep 19, 2013

Words and phrases like "you" and "this is" is generally a good indication that it's not a good description for documentation purposes.

Agreed, I've updated the docstring with your suggestion. Thanks.

@MartinNowak
Copy link
Member

This is pretty different from a tuple declaration where the caller would name the elements of a returned tuple. Here the callee names the elements. It's also problematic to return such a tuple in an auto function, because the names aren't documented anywhere but in the implementation.

@ghost
Copy link
Author

ghost commented Sep 19, 2013

Fair point. Although naming them at the call site could be just as dangerous. For example, if you write:

auto (a, b) = get();

And later someone changes get to return the arguments in the opposite order, you will have no clue that the behavior changed. Hence why I think tuples are a little bit overrated, they enable a sort of dynamic-style typing but at the cost of safety.

@w0rp
Copy link
Contributor

w0rp commented Sep 20, 2013

I think I originally started this discussion, but I'm not sure how I feel about it now. I agree that the names should be documented somewhere, so that forces you to write the names in the function's interface, instead of auto. This works with phobos today.

Tuple!(int, "x", int, "y") foo() {
    return typeof(return)(1, 2);
}

I think the observation I make is that it's not possible to move a Tuple!(int, int) into a Tuple!(int, "x", int, "y"), or a Tuple!(int, "a", int, "b") into a Tuple!(int, "x", int, "y"). Maybe if this were possible, interesting things could happen, like this.

Tuple!(int, "x", int, "y") bar() {
    // Cannot be done today.
    return tuple(1, 2);
}

Tuple!(int, int) baz() {
    // Fine today, as the types match.
    return tuple(1, 2);
}

Personally though, for reasons mentioned above, I think I prefer the typeof(return) solution which exists today. The names are documented, you could re-order the tuple values without breaking code, (so long as everyone only uses the names), it's probably less problematic with the types, and there's no extra work needed to implement it. Capturing values is out of scope for this issue, so I won't discuss it here.

I don't tend to agree with making language changes for this kind of thing. D is a powerful enough language such that it should be possible to implement interesting things like this without making language changes. I don't tend to think of implementing features through libraries as a work-around, but more how it should be. Plus, I think tuples are already part of the language. That's what variadic templates are.

@JakobOvrum
Copy link
Contributor

I agree that the names should be documented somewhere, so that forces you to write the names in the function's interface, instead of auto.

What exactly is the return type inference argument about? Return type inference is not required with the proposed tuple overload:

Tuple!(int, "x", int, "y") foo()
{
    int x, y;
    return tuple!(x, y);
}

Plus, I think tuples are already part of the language. That's what variadic templates are.

They are related in name only. std.typecons.Tuple and the in-built "parameter packs" are fundamentally different.

@w0rp
Copy link
Contributor

w0rp commented Sep 20, 2013

What exactly is the return type inference argument about?

I'm suggesting that it's a way to accomplish this kind of thing today, only the names of variables inside the function matter less, because you can do this:

Tuple!(int, "x", int, "y") foo() {
    int a, b;
    return typeof(return)(a, b);
}

@JakobOvrum
Copy link
Contributor

I'm suggesting that it's a way to accomplish this kind of thing today, only the names of variables inside the function matter less, because you can do this:

I agree that there is no benefit to using the proposed tuple overload in situations where typeof is a reasonable alternative (which is not limited to typeof(return)).

@ghost ghost closed this Oct 18, 2013
@ghost
Copy link
Author

ghost commented Oct 18, 2013

Well, it was a cute experiment anyway. :)

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants