August 20, 2013
On Tuesday, 20 August 2013 at 01:06:28 UTC, H. S. Teoh wrote:
> Actually, reading through DIP32 again, it sounds like Kenji is proposing
> the *same* syntax for both built-in tuples and std.typecons.Tuple. In
> the code example under "Generic type/expression tuple syntax", he refers
> to them respectively as "tuple type" and "tuple value". Mixing is also
> allowed (e.g., in the "alias Fields" line).

Maybe mixing should be disallowed, then, unless your tuple was constructed from a variadic template argument list.

auto tup = #(1, int); //ERROR

template TMP(T...)
{

    auto tup = T;
}

> So it sounds like this is similar to what bearophile was suggesting --
> the unification of built-in tuples and Phobos Tuples. I suppose the
> intention is that if a built-in tuple like (1, "a", 1.0) is used as a
> value, it would be automatically translated into a runtime tuple value.
> I'm not sure if the reverse is possible, though, since if the tuple
> contains some runtime values, then it's not possible to translate it
> back into a built-in tuple.
>
> Actually, going in either direction requires some restrictions; for
> example, if a tuple contains a type, like (1, int), then it's impossible
> to translate it into a runtime tuple (types have no runtime value in and
> of themselves). Similarly, if a tuple contains a runtime variable, then
> it's impossible to use it as a compile-time tuple. But if a tuple
> contains only compile-time known values, then it's in theory usable both
> as a built-in tuple and a runtime tuple.
>
> There might be some areas where this conflation may cause trouble,
> though; for example, if you have a tuple (1, x) where x is a runtime
> variable, then should it be treated as (1, {alias of x}) or (1, {runtime
> value of x})? The former would happen if you pass it to a template that
> expects an int and and alias parameter, for example, and the latter if
> you try to store this tuple into a variable. It may lead to this weird
> situation:
>
> 	template Tmpl(int x, alias y) { ... }
> 	int x=123;
> 	auto tup = {1; x};
> 	alias T = Tmpl!tup;	// OK, 1 -> int x, x -> alias y
> 	auto tup2 = tup;	// store {1;123} into variable
> 	alias U = Tmpl!tup2;	// ERROR: cannot instantiate template with runtime variable
>
> Actually, looking at this again, it seems the problem is with the "tup =
> {1; x}" line. Does {1; x} in the above code mean {1; 123}, or does it
> mean {1; {alias of x}}? For example, if you wrote this:
>
> 	int x=123;
> 	auto tup = {1; x};
> 	x++;
> 	writeln(tup);
>
> What should be the output? Should the output change if the second line
> is changed to:
>
> 	alias tup = {1; x};
>
> ?
>
>
> T

August 20, 2013
Aggh, misposted. Let's try that again.

On Tuesday, 20 August 2013 at 02:51:20 UTC, Meta wrote:
> On Tuesday, 20 August 2013 at 01:06:28 UTC, H. S. Teoh wrote:
>> Actually, reading through DIP32 again, it sounds like Kenji is proposing
>> the *same* syntax for both built-in tuples and std.typecons.Tuple. In
>> the code example under "Generic type/expression tuple syntax", he refers
>> to them respectively as "tuple type" and "tuple value". Mixing is also
>> allowed (e.g., in the "alias Fields" line).

Maybe mixing should be disallowed, then, unless your tuple was
constructed from a variadic template argument list.

//Error. Tuple containing types
//at runtime doesn't make any sense
auto tup = #(1, int);
//Error
auto tup = #(int, string);
//Ok
auto tup = #(1, "a", true);

T[0] Test(T...)(T ts)
{
    //Okay, each element of T can
    //be statically inspected to ensure
    //that you don't do something weird
    auto tup = T;
    //Also okay
    alias tup = T;
    //Error
    auto tup = #(int, string, bool);
    //Ok
    alias tup = #(int, string, bool);
}

>> There might be some areas where this conflation may cause trouble,
>> ...
>>
>> Actually, looking at this again, it seems the problem is with the "tup = {1; x}" line. Does {1; x} in the above code mean {1; 123}, or does it mean {1; {alias of x}}? For example, if you wrote this:
>>
>> 	int x=123;
>> 	auto tup = {1; x};
>> 	x++;
>> 	writeln(tup);
>>
>> What should be the output?

I'd say that x++ would not modify the x within the tuple. It's the same as:

int x = 123;
auto y = x;
x++;
writeln(y);

Y is not changed, of course. However, if the tuple contains a reference type, such as a slice, then it would be modified.

int[] x = [123];
auto tup = #(1, x);
x[]++;
//Prints #(1, [124])
writeln(tupe);

>> Should the output change if the second line
>> is changed to:
>>
>> 	alias tup = {1; x};
>>
>> ?

I don't think this should be possible. It would be the same as doing:

alias two = 3; //Error

Unless the tuple contained only types. Then it would be possible.

alias intAndStr = #(int, string); //Ok

The semantics are fairly easy when a tuple contains only values and only types. The hard part is when it contains both values AND types, so that should be severely limited, maybe only within variadic templates.

I can't remember where this was mentioned... I think it was in one of the other tuple threads I linked, and I think you brought it up, Teo.

auto tup = #(1, "a");
alias tupType = typeof(tup);

While tup is a value, its type is #(int, string). In other words, the type of a tuple value is a TypeTuple (alias tuple, whatever). Which means the type of a tuple is a tuple itself, which is pretty nifty.
August 20, 2013
2013/8/20 H. S. Teoh <hsteoh@quickfur.ath.cx>

> Actually, reading through DIP32 again, it sounds like Kenji is proposing the *same* syntax for both built-in tuples and std.typecons.Tuple. In the code example under "Generic type/expression tuple syntax", he refers to them respectively as "tuple type" and "tuple value". Mixing is also allowed (e.g., in the "alias Fields" line).
>

 Honestly, I had intended DIP32 to provide *uniform* syntax for both
built-in tuple and std.typecons.Tuple.
However, finally, I noticed that would be _impossible_.

I'll withdraw DIP32 and will open new DIP for only built-in tuple syntax proposal.

Kenji Hara


August 20, 2013
Sorry I cannot reply to each thread comments quickly, so I discharge my opinions at once.

----
D's built-in tuple can contain following entities:
 - Type
    int, long, array types, AA types, user-defined types, etc
 - Expressions
    interger, string literal, etc
 - Symbol
    user-defined types, templates, template instances, etc

Note that: an user-defined type would be treated as both Type and Symbol.

template Test() {}
alias X = std.typetuple.TypeTuple!(
    int, long, char[], int[int], const Object,  // Types
    1, "str", [1,2,3],  // Expressions (literal values)
    object.Object, Test, Test!(),   // Symbols
);

If all of the elements in a built-in tuple are Type, today it is normally
called "Type Tuple".
If all of the elements in a built-in tuple are Expressions, today it is
normally called "Expression Tuple".

Note that: today we cannot create a built-in tuple without using
TemplateTupleParameter.
TemplateTupleParameter cannot take expressions non-literal expressions,
therefore
most of current built-in tuples would contains only literal values as the
Expressions.

----
std.typecons.Tuple is an artifact of built-in tuple + alias this.

struct Tuple(T...) {
    T expand;   // 'expand' is a built-in tuple of
                // the implicitly defined fields that
                // typed T[0], T[1], ... T[$-1].
                // In spec, this is called "TupleDeclaration".
    alias expand this;  // forward indexing/slicing operators to
                        // the TupleDeclaration 'expand'
}
Tuple!(int, string) t;
t[];        // t.expand[]
t[0..$];    // t.expand[0..$]
t[1];       // t.expand[1]

So, std.typecons.Tuple _is not special_. You can define another Tuple
struct in the same way.
We should not define new syntax for the library utility std.typecons.Tuple.

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)

----
The combination of built-in tuple and alias this would be one of the case
of built-in tuple of non-literal Expressions.
For example, `t.expand[1]` is equivalent with the dot expression
`t.__field_1` which cannot be taken by TemplateTupleParameter.
Therefore, `t.expand` would be the built-in tuple of the two dot
expressions `t.__field_0` and `t.__field_1`.

Therefore, calling built-in tuple "Alias Tuple" would not be correct so built-in tuple can contain expressions that cannot be aliased.

----
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


August 20, 2013
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.

- Jonathan M Davis
August 20, 2013
On Monday, 19 August 2013 at 21:03:50 UTC, Andrei Alexandrescu wrote:
> I'm saying that there's a mix of useful stuff and just syntactic additions that are arguably less so. In my opinion:
>
> a) destructuring tuples in auto declarations - good to have:
>
> auto (a, b, c) = functionReturningTupleOrStaticArrayWith3Elements();
>

I propose the following rewrite :

auto tmp = functionReturningTupleOrStaticArrayWith3Elements();
assert(tmp.length == 3);
auto a = tmp[0];
auto b = tmp[1];
auto c = tmp[2];

That way any type user can take advantage of the new syntax, and it is easy to implement as it is simple rewrite rules. Note that tmp do not need to be an lvalue to avoid uneeded copies.

I'd also like to see the term Tuple for variadic template parameter go away. This is confusing the hell out of everybody, as the current conversation is showing.
August 20, 2013
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)?


- Elegance. Eg:

auto seq(T...)(T arg){ return arg; }

auto fold(alias a,S,R)(S start, R range){ ... }


seq(0,[1,2,3]).fold!((a,b)=>a+b);


(Obviously you can get close by requiring expansion at the call site.)


- ABI

Multiple return values could use a more efficient ABI than struct instances because they do not have an address.


- Consistency

A type whose instances cannot be returned from a function is just weird language design.


> It has no state.

It may alias variables that do.
August 20, 2013
On Monday, 19 August 2013 at 18:43:37 UTC, Meta wrote:
> On Monday, 19 August 2013 at 16:53:06 UTC, Wyatt wrote:
>> Can't make it a single underscore? Question mark works best then, IMO.  It isn't as burdened with meanings elsewhere (sure there's ternary and possibly-match in regex, but...have I forgotten something?)
>
> It *could* be an underscore; the only thing is that the underscore is a valid variable name, so the above expression would actually be binding two variables, which might surprise someone who was expecting otherwise. I don't really care all that much, but it's something to think about.

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";

http://php.net/manual/en/function.list.php
August 20, 2013
On Friday, 16 August 2013 at 21:07:52 UTC, Meta wrote:
> A good, comprehensive design has the potential to make tuples easy to use and understand, and hopefully clear up the unpleasant situation we have currently. A summary of what has been discussed so far:
>
> - (a, b) is the prettiest syntax, and it also completely infeasible
>
> - {a, b} is not as pretty, but it's not that bad of an alternative (though it may still have issues as well)
>
> - #(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

What about:

!!(a, b)

? Yes, is long, but is type-able quite fast.

Alternative would be:

??(a, b)

.
August 20, 2013
On Tuesday, 20 August 2013 at 10:38:30 UTC, eles wrote:
> On Friday, 16 August 2013 at 21:07:52 UTC, Meta wrote:
>> A good, comprehensive design has the potential to make tuples easy to use and understand, and hopefully clear up the unpleasant situation we have currently. A summary of what has been discussed so far:
>>
>> - (a, b) is the prettiest syntax, and it also completely infeasible
>>
>> - {a, b} is not as pretty, but it's not that bad of an alternative (though it may still have issues as well)
>>
>> - #(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
>
> What about:
>
> !!(a, b)
>
> ? Yes, is long, but is type-able quite fast.
>
> Alternative would be:
>
> ??(a, b)
>
> .

It's not only long, but also ugly (IMO of course).