Proposal: Object/?? Destruction
Steven Schveighoffer
schveiguy at yahoo.com
Fri Oct 6 21:34:31 UTC 2017
On 10/6/17 3:31 PM, Timon Gehr wrote:
> On 06.10.2017 14:26, Steven Schveighoffer wrote:
>> On 10/5/17 3:42 PM, Timon Gehr wrote:
>>> On 05.10.2017 17:40, Steven Schveighoffer wrote:
>>>> On 10/5/17 2:42 AM, Timon Gehr wrote:
>>>>
>>>>> The only unresolved question is (as using the result of the comma
>>>>> operator has been deprecated already): How to write a unary tuple.
>>>>> My favourite is what python does: "(3,)". This is however already
>>>>> accepted as a function argument list. I think it is worth breaking
>>>>> though. Maybe we should deprecate it.
>>>>
>>>> I know you have an answer for this, but pardon my ignorance.
>>>
>>> I indeed have strong opinions on how to do this correctly, as I have
>>> given some thought to it when designing the (still quite basic) type
>>> system of PSI: https://github.com/eth-srl/psi
>>>
>>> The idea is to follow type theory/mathematics where the type of
>>> functions is a binary type constructor taking domain and codomain to
>>> the type of functions mapping values from the domain to values from
>>> the codomain. Multiple function arguments are just the function
>>> applied to a tuple of values.
>>>
>>>> Why isn't (a) good enough?
>>>>
>>>
>>> typeof((a)) should be typeof(a). This is just a parenthesized
>>> expression, as in (a+b)*c.
>>
>> Right, I agree.
>>
>>> typeof((a,)) should be (typeof(a),).
>>
>> I guess my question is more in the context of the problem at hand:
>>
>> int foo();
>>
>> auto (a) = foo();
>>
>> why can't this work?
>> ...
>
> This could be made to compile, but this is not really about tuples.
>
>> But then of course, it shouldn't work, because int is not a tuple. So
>> I suppose I have answered my own question -- we need a way to specify
>> a tuple of one for prototype foo!
>>
>> Indeed, my experience with tuples and their usage is quite limited.
>>
>> Even though the syntax is straightforward and unambiguous, it looks
>> incorrect, like you forgot something.
>> ...
>
> That's not necessarily bad. (When is the last time you have used a
> singleton tuple?)
>
>> I'm not an expert in language design, but would it be worth exploring
>> other punctuation that isn't used in the language currently to allow
>> better syntax? It seems like the trailing comma is to get around
>> ambiguity,
>
> It's the comma that indicates tupling, so there is not really ambiguity,
> the expression (a) just is not a tuple. To indicate a tuple you need to
> use the tupling operator ','. Trailing commas are allowed for all
> tuples, but for singleton tuples they are also necessary.
>
>> but there would be no ambiguity if you used something other than
>> current punctuation to surround the tuple.
>>
>> Angle brackets come to mind <a>.
>
> D avoids angle brackets.
>
>> Also you could use a leading symbol to change the meaning of the
>> parentheses, like $(a).
>> ...
>
> This is very noisy, and once you go with non-standard tuple syntax, you
> can just as well use tuple(a).
>
>>> ---
>>> (int,) foo(int a){ return (a,); } // turn value into singleton tuple
>>> int bar(int a,){ return a[0]; } // turn singleton tuple into value
>>>
>>> void main(){
>>> foo(2,); // error: cannot convert (int,) to int
>>> bar(2); // error: cannot convert int to (int,)
>>> auto (x,) = foo(2); // ok, x has type int
>>> auto y = bar(2,); // ok y has type int
>>> auto z = foo(2); // ok, z has type (int,)
>>> }
>>> ---
>>>
>>> ---
>>> // The following two function signatures are equivalent (identical
>>> name mangling):
>>> (int,string) foo(int a,string b){
>>> return (a,b);
>>> }
>>>
>>> (int,string) foo((int,string) x){
>>> return x;
>>> }
>>> ---
>>
>> So I will ask, what is the usage of foo here?
>>
>> In the first example (foo and bar), you can't call a function that
>> takes a tuple with a single value, and you can't call a function that
>> takes a value with a single tuple (BTW, this is not how AliasSeq
>> works, you can call functions that take a single arg with single
>> element tuples).
>> ...
>
> AliasSeq auto-expands. If you call a function with a single element
> AliasSeq, it will expand to a single value and not be an AliasSeq
> anymore. Built-in tuples should not auto-expand, so a singleton tuple
> stays a singleton tuple (they will have an explicit .expand property).
>
>> In your second example, where foo takes a 2-element tuple or 2 values,
>
> All functions take a single value. That value might be a tuple. (Of
> course, we will continue to say that a function can take multiple
> arguments, because it is convenient, but what this _means_ is that it
> takes a single tuple argument.)
>
>> you say the name mangling is equivalent. Does that mean if I only
>> define the tuple version, I can call it with foo(1, "hello") and vice
>> versa?
>
> Yes. (Both options are "the tuple version".)
>
>> This seems to contradict your example above.
>> ...
>
> 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.
>> This would mess up a TON of code. I can say for certain, a single type
>> argument can never be made to accept a tuple.
>>
> The proposal is to make all arguments "single type arguments". The
> "single type" might be a tuple. A tuple type is just a type, after all.
> For two current functions where only one matches but after the change
> both would match, the same one would still be selected, because it is
> more specialized.
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.
-Steve
More information about the Digitalmars-d
mailing list