Proposal: Object/?? Destruction

Timon Gehr timon.gehr at gmx.ch
Mon Oct 9 15:22:35 UTC 2017


On 09.10.2017 01:20, Steven Schveighoffer wrote:
> On 10/7/17 8:56 PM, Timon Gehr wrote:
>> On 06.10.2017 23:34, Steven Schveighoffer wrote:
>>>>>
>>>>
>>>> No. All functions take one argument and produce one result. (The 
>>>> argument and the result may or may not be a tuple, but there is no 
>>>> essential difference between the two cases.) You can match a value 
>>>> against a pattern on the function call.
>>>
>>> It is weird to me that a function with 2 parameters is the same as a 
>>> function that takes a 2-element tuple, but a function with one 
>>> parameter is not the same as a function that takes a 1-element tuple. 
>>> That is where I feel it's a contradiction.
>>> ...
>> If a function with 2 parameters was the same as a function that takes 
>> a 2-element tuple, and a function with one parameter that is a 
>> 2-element tuple is the same as a function that takes a 1-element 
>> tuple, then a function that takes a 2-element tuple is the same as a 
>> function that takes a 1-element tuple. So I think the opposite is the 
>> case.
>>
>> // those two are the same
>> void foo(int a,string b); // match two-element tuple
>> void foo((int,string) x); // take two-element tuple w/o matching
>>
>> // those two are the same
>> void bar(int a,);   // match one-element tuple
>> void bar((int,) x); // take one-element tuple w/o matching
>>
>> This is like:
>>
>> (int a,string b)=(1,"2"); // match
>> // vs
>> (int,string) x=(1,"2"); // w/o matching
>>
>> and
>>
>> (int a,)=(1,); // match
>> // vs
>> (int,) x=(1,); // w/o matching
> 
> My questioning comes with this:
> 
> void bar(int a);
> void bar((int,) x);
> 
> To me, it is confusing or at least puzzling that these two aren't the same.
> ...

Well, to me it is a bit confusing that this is puzzling to you. Why 
should int be the same as (int,)? It does not make sense to index an 
integer, but (int,) can be indexed with 0 to get an integer.

I believe your difficulty is rather with the notion that what before was 
a function that takes a single value is no longer analogous to what 
before was a function that takes multiple values. The analogy breaks 
because now they are handled precisely the same way, rather than just 
analogously. Furthermore, some existing syntax slightly changes meaning: 
The prior syntax for declaring multiple arguments is now a pattern that 
matches against a single tuple argument.

The new design is more orthogonal and in effect more useful, because 
functions no longer need to care about and interfere with the concept of 
"multiple values".

> The first is like a "regular" function that doesn't take a tuple.
> 
> The second is a new "tuplized" function that takes a tuple. both take 
> one parameter (one version via the regular argument syntax, one via a 
> tuplized syntax).

One takes an argument that is an integer. The other takes an argument 
that is a tuple containing a single integer.

> Why is it not the same?

One takes an int while the other takes an (int,).

> Clearly a tuple of 1 can bind 
> to a single value, just like a tuple of 2 can bind to 2 values.
> ...

But it is precisely what is happening. However, not every value is a 
singleton tuple just by virtue of not being a tuple of multiple values.

> Currently, I can call this:
> 
> foo(T...)(T t) if (T.length == 1) // function that takes a single 
> element tuple
> 
> like this:
> 
> foo(1);
> 
> Why is this disallowed in your tuple scheme?
> ...

I take this to mean, why does the following code not compile:

void foo(T)(T t) if(T.length == 1) { ... }

foo(1);

This is because T is matched to int, which does not have length.

A few more examples:

void foo(int x);       // foo takes an int
void foo(int x,);      // foo takes an (int,) and matches it against 
(int x,) in order to extract the value x
void foo(int x,int y); // foo takes an (int,int) and matches it against 
(int x,int y) in order to extract the values x and y.

>> In case this is not convincing to you: Why does your reasoning apply 
>> to arguments but not return values? Why should arguments not behave 
>> the same as return values? If it does actually apply to return values: 
>> what special syntax would you propose for functions that "return 
>> multiple values"? Is it really reasonable to not use tuples for that?
> 
> I don't understand the question.

I'm was trying to figure out what is causing the confusion. I was trying 
to appeal to symmetry to get past what seemed to be your notion that 
there is a significant difference between multiple values and a single 
tuple: If you have a function that needs to return multiple values, you 
return a single tuple. If you have a function that needs to take 
multiple values, you take a single tuple. With tuples, it is sufficient 
to return a single value, and it is also sufficient to take a single 
value as the argument.

> I would think single value tuples and 
> single values would be pretty much interchangeable.

Well, no. Otherwise 2[0] would be allowed and equal to 2. And then, what 
would [2][0] be? [2] or 2?

> It's up to the user 
> of the value whether he wants to look at it as a tuple (which has length 
> and must be indexed) vs. a single value.
> ...

A singleton tuple is like a box that contains a single value. You need 
to open the box to get at the value. Opening the box is achieved by 
matching the tuple against a tuple pattern. This is the same regardless 
of the length of the tuple.

Singleton tuples might seem pointless, and some languages do not support 
such single-element tuples, but as we want to support slicing, they 
should probably exist. (Also, we might want to create a tuple from an 
AliasSeq, which can be achieved by dropping it into a single-element 
tuple and letting it auto-expand.)

>>> Right, but cases where T is expected to match to exactly one type 
>>> will now match with multiple types. It messes up is(typeof(...)) checks.
>>>
>>
>> All new language features can be detected using is(typeof(...)) this 
>> is usually ignored for language evolution. We'd need to check how much 
>> code relies on this specific case not compiling.
> 
> I definitely don't have an answer off hand, but I wouldn't be surprised 
> if this broke at least some code in phobos.
> ...

I guess we'll need to try.

>> We can also think about adding a "light" version of tuple support, 
>> that just supports unpacking for library-defined tuple types and 
>> nothing else, but I'd prefer to have proper tuples.
> 
> This flew over my head :)
> ...

If we cannot have proper tuples, having some syntactic sugar for tuple 
unpacking during variable declaration may still be useful:

import std.typecons;

auto (x,y) = tuple(1,"2");
(int x,string y) = tuple(1,"2");

This is syntactically forward-compatible.


More information about the Digitalmars-d mailing list