August 20, 2013
On Tuesday, 20 August 2013 at 03:33:51 UTC, Kenji Hara wrote:
> ----
> My opinions agains various syntax proposals:
>
> #(1, "str")
> --> The character '#' is already used for the start of "Special Token
> Sequences"
> http://dlang.org/lex.html#Special Token Sequence
>
> It is recognized in lexing phase, so adding semantic meaning to the '#'
> character would be a contradict of D's principle.
>
> Quote from http://dlang.org/lex.html
> "The lexical analysis is independent of the syntax parsing and the semantic
> analysis."
>
> Kenji Hara


There are various other characters that could be substituted for #
e.g.
&(1, "string")

http://forum.dlang.org/post/cokiixatvjmngggpblma@forum.dlang.org
August 20, 2013
On 2013-08-20 05:33, Kenji Hara wrote:

> If you want to return multiple values from a function, you must always
> wrap them by std.typecons.Tuple, or other used-defined types. You cannot
> directly return built-in tuple from a function.
> (Built-in tuple return is mostly equivalent with multiple-value-return
> issue. However it would be mostly impossible that defining calling
> conversion scheme for that in portable)

If I recall correctly some ABI's passes small structs in registers, at least I think it does on Mac OS X.

> My opinions agains various syntax proposals:
>
> #(1, "str")
> --> The character '#' is already used for the start of "Special Token
> Sequences"
> http://dlang.org/lex.html#Special Token Sequence
>
> It is recognized in lexing phase, so adding semantic meaning to the '#'
> character would be a contradict of D's principle.
>
> Quote from http://dlang.org/lex.html
> "The lexical analysis is independent of the syntax parsing and the
> semantic analysis."

It depends on how it's lexed. If the compiler lexes "#line" as a single token I cannot see how it will be a problem. Then the "#" token would mean tuple literal.

-- 
/Jacob Carlborg
August 20, 2013
On Tuesday, 20 August 2013 at 03:33:51 UTC, Kenji Hara wrote:
> Sorry I cannot reply to each thread comments quickly, so I discharge my
> opinions at once.

One thing that I think does not get deserved attention is that built-in expression tuple are not limited to compile-time values. Lets consider this simple example:

void foo(T...)(T args)
{
	pragma(msg, args);
	pragma(msg, typeof(args));
}

void main()
{
	int a, b;
	foo(a, b);
}


-----------------------

/d147/f686.d(3): Error: variable _param_0 cannot be read at compile time /d147/f686.d(3): Error: variable _param_1 cannot be read at compile time tuple(_param_0, _param_1) (int, int)

-----------------------

What we have here are two completely different _built-in_ tuple types. "T" is pure template arguments list and is pretty much equal TypeTuple!(int, int). But what is "args"? It uses the very same built-in tuple syntax but it is much closer to std.typecons.Tuple in its behavior (actually, latter is implemented in terms of it as I was pointed out) - it is an entity that provides abstraction of top of group of run-time values. It does not have any binary structure on its own (built on top of existing values) but observable semantic are very "run-time'ish".

What bothers me is the question "can we clean this up and bring those two worlds together, even at cost of minor breakage?". I am not speaking about literals here or unpacking or whatever. I am speaking about re-defining semantics so that struct-based Tuple and built-in syntax sugar in form of run-time expression tuple both get merged into one built-in construct which can be used in wider variety of places.

At least right now I can't find any technical objections why expression tuple can't use std.typecons.Tuple ABI when returned from function but still be automatically expanded when passed into functions. Kenji, what is your your opinion about complexity to implement something like that in DMD?
August 20, 2013
On Tuesday, 20 August 2013 at 09:02:29 UTC, Mr. Anonymous wrote:
>
> Why not just leave an empty space, like php does:
>
> $info = array('coffee', 'brown', 'caffeine');
> // let's skip to only the third one
> list( , , $power) = $info;
> echo "I need $power!\n";

Bad idea.  It's a visual thing--  quick! How wide is this tuple!?:
#(,front,,,,var,)

How long did it take you to be SURE that it's a seven-tuple?  You probably aren't even equipped to measure that so don't worry about answering, but I'm guessing you start to appreciate why it's a fairly inhumane solution (how drearily typical for PHP).

Ah, but what if it was supposed to be #(,front,,,,,var,)?  Does that change your result, now that you're taking the sixth element rather than the seventh?  All you did was forget a comma!  By contrast:
#(?,front,?,?,?,var,?,?) //at least gives us a better chance of parsing it correctly.

My point here is we are human and we are fallible.  The sooner we acknowledge and internalise that, the better equipped we are to make systems that don't suck for humans to use.

In that sense, I don't even really like this format because it's still not especially resilient.  Walter's talk about design that eliminates patterns of human error resonated with me quite strongly, you see.  But in terms of language consistency it's not much different from array literals, so I could accept it as a compromise.

-Wyatt
August 20, 2013
On 08/20/2013 12:38 PM, eles wrote:
>
> What about:
>
> !!(a, b)
>

This already has a meaning.

August 20, 2013
This is the reason I had originally thought Kenji's DIP was about run-time tuples. If it's just syntactic sugar over std.typecons.Tuple (plus some extra destructuring/pattern matching stuff), it would require no ABI changes and no changes to TypeTuple semantics. The one thing it wouldn't do is unify Tuple and TypeTuple.

However, with compiler support, we can make this situation better. TypeTuple stays as-is, while Tuple becomes a value instead of a type, which has its own literal syntax. This means that typeof(tuple(1, "a")) is not Tuple!(int, string), as in the struct, but TypeTuple!(int, string), as in the compiler tuple.

You could still do all the stuff that can be done with TypeTuple currently, but it should be strongly discouraged to mix types and values within TypeTuple, or even limited by the compiler. This creates a clear distinction between runtime tuples and TypeTuple. It becomes much easier to reason about their semantics, as we can think of TypeTuple as a type, just like int, string, double, etc., and Tuple as a value, just like 1, "a", 2.3, etc. The only difference between TypeTuple and regular types is that there are a few special static operations that can be used to manipulate it. Otherwise it behaves as a type.
August 20, 2013
On Tuesday, 20 August 2013 at 13:17:44 UTC, Meta wrote:
> This is the reason I had originally thought Kenji's DIP was about run-time tuples. If it's just syntactic sugar over std.typecons.Tuple (plus some extra destructuring/pattern matching stuff), it would require no ABI changes and no changes to TypeTuple semantics. The one thing it wouldn't do is unify Tuple and TypeTuple.

Syntax sugar will only hide and eventually increase confusion, it won't solve the semantical issue. This is why we are having this topic IMHO, bunch of quite experienced D developers can't even agree on how existing feature behaves :) Including those who is it all the time! It is clear indicator that syntax is not the one to blame.

> However, with compiler support, we can make this situation better. TypeTuple stays as-is, while Tuple becomes a value instead of a type, which has its own literal syntax. This means that typeof(tuple(1, "a")) is not Tuple!(int, string), as in the struct, but TypeTuple!(int, string), as in the compiler tuple.

I am proposing something more radical. Deprecate _both_ TypeTuple and Tuple. Clearly define the difference between built-in type tuple and expression tuple (latter being instance of former). Preserve auto-expansion. Provide two different literals to remove ambiguity between referencing symbol as a value and referencing it as an alias. Make compiler auto-generate Tuple-like struct type for expression tuples that need to be returned from functions. Create some new type in std.typecons for those who don't want auto-expansion.

It won't even break stuff.
August 20, 2013
On Tuesday, 20 August 2013 at 13:57:49 UTC, Dicebot wrote:
> Syntax sugar will only hide and eventually increase confusion, it won't solve the semantical issue. This is why we are having this topic IMHO, bunch of quite experienced D developers can't even agree on how existing feature behaves :) Including those who is it all the time! It is clear indicator that syntax is not the one to blame.

My suggestions are predicated on the fact that I think tuples are more or less fine as-is. They just need some syntactic sugar for literals and destructuring/pattern matching to make them more usable. Built-in tuples are confusing, I think, because they're named TypeTuple, which makes people conflate them with std.typecons.Tuple.

Another reason is that TypeTuple can contain both values and types at the same time, so it's confusing as to what you can do with them.

"Why can you only assign a TypeTuple to a variable if it contains values but not types? Why, then, can't you return TypeTuple!(1, 2.3) from a function? Is it not really a variable? Why does `alias t = TypeTuple!(1, 2.3)` work, but `alias n = 3` not work? Is this f*$#ing thing a value or a type?" - D Newbie

Everything else aside, I think the best possible change that would make the whole tuple situation better is to limit or outright ban the mixing of values and types within TypeTuple. Even better is to always treat TypeTuple as a type, and not a value. That ship has already sailed, but we can at least try to enforce it through convention.

> I am proposing something more radical. Deprecate _both_ TypeTuple and Tuple. Clearly define the difference between built-in type tuple and expression tuple (latter being instance of former). Preserve auto-expansion. Provide two different literals to remove ambiguity between referencing symbol as a value and referencing it as an alias. Make compiler auto-generate Tuple-like struct type for expression tuples that need to be returned from functions. Create some new type in std.typecons for those who don't want auto-expansion.
>
> It won't even break stuff.

I think my position has changed to suggest nearly the same thing. There needs to be a clear separation between built-in tuples and tuple values. A runtime tuple literal syntax helps with that. Making typeof(tuple(1, 2.3)) == TypeTuple!(int, double) helps as well, because it is now clear that one is a value and one is a type. Limiting the mixing of values and types within TypeTuple helps with that.

This would allow both Tuple and TypeTuple to be deprecated. Tuple wouldn't be needed anymore, because we would have a literal syntax to replace it. It would only be there for backwards compatibility. With Tuple deprecated, std.typetuple.TypeTuple could be renamed Tuple, and we would then have only one thing with the name Tuple in the language.
August 20, 2013
On Mon, Aug 19, 2013 at 09:41:24PM -0700, Jonathan M Davis wrote:
> On Monday, August 19, 2013 13:45:33 Andrei Alexandrescu wrote:
> > but once the bikeshed is up for painting, the
> > rainbow won't suffice.
> 
> LOL! I'm going to have to remember that one.
[...]

That's a classic. I'm st^H^H borrowing that for my random signatures file. :)


T

-- 
There's light at the end of the tunnel. It's the oncoming train.
August 20, 2013
On 20 August 2013 16:39, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 08/20/2013 02:18 AM, Andrei Alexandrescu wrote:
>
>>
>> Why would it be necessary to return an object of type TypeTuple (i.e.
>> template tuple)?
>>
>
> - ABI
>
> Multiple return values could use a more efficient ABI than struct instances because they do not have an address.
>

*** this

I've been banging this drum for years!

However this discussion resolves, I just hope it allows for convenient and
efficient MRV's.
Obviously it should be syntactically convenient, and assignment of MRV to
callee locals should be convenient too.
But more importantly, I'd like to see ALL the argument registers re-used to
return multiple values, rather than just the first one. They're just
sitting there begging to be used, and in many cases, would lead to some
great efficiency improvements across function calls/returns. Especially on
non-x86 architectures.

Perhaps one of the most common causes for (otherwise unnecessary) inlining of functions is because of the terrible legacy ABI for returning multiple values from functions.