[Discussion] Zero-element tuple glitch


(Anton Zhilin) #1

let x = (Int, Int)(1, 2) //=> (1, 2)
let y = (Int)(1) //=> 1
let z = ()() // error :frowning:

Am I requesting too much from type checker?


(Vladimir) #2

let x = (Int, Int)(1, 2) //=> (1, 2)
let y = (Int)(1) //=> 1
let z = ()() // error :frowning:

Am I requesting too much from type checker?

As I understand, because () is Void, you can't have anything additional for it. It is just Void, like you write 'let z = Void Void'. I.e. only 'let z = ()' allowed.

路路路

On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Anton Zhilin) #3

Vladimir.S via swift-evolution <swift-evolution@...> writes:

> let x = (Int, Int)(1, 2) //=> (1, 2)
> let y = (Int)(1) //=> 1
> let z = ()() // error :frowning:
>
> Am I requesting too much from type checker?

As I understand, because () is Void, you can't have anything additional

for

it. It is just Void, like you write 'let z = Void Void'. I.e. only 'let

z =

()' allowed.

In the example, that's how I expect that to parse:

let z = ().init() // just demo, does not compile

I mean, first () is type, and second () is its initializer.

By the way, this is one thing that Void can do, but () cannot.
Are there any others?

路路路

On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:


(Vladimir) #4

Vladimir.S via swift-evolution <swift-evolution@...> writes:

let x = (Int, Int)(1, 2) //=> (1, 2)
let y = (Int)(1) //=> 1
let z = ()() // error :frowning:

Am I requesting too much from type checker?

As I understand, because () is Void, you can't have anything additional

for

it. It is just Void, like you write 'let z = Void Void'. I.e. only 'let

z =

()' allowed.

In the example, that's how I expect that to parse:

let z = ().init() // just demo, does not compile

I mean, first () is type, and second () is its initializer.

By the way, this is one thing that Void can do, but () cannot.
Are there any others?

I believe in this case () is playing a role of instance of type Void, i.e. empty tuple. I don't think you can expect ().init()

Also:
func f(_ x: ())->() {}
f(())
//f(Void) // argument passed to call that takes no arguments

And just some fun:

let x1 : Void
//let x2 : Void = Void // cannot convert value of type 'Void.Type' (aka '().Type') to specified type 'Void' (aka '()')
let x3 : ()
let x4 : () = ()
let x5 : Void = ()
//let x4 : () = Void // cannot convert value of type 'Void.Type' (aka '().Type') to specified type '()'

print(().dynamicType) // ()
print(().self) // ()
// print("Void.dynamicType = ", Void.dynamicType) // '.dynamicType' is not allowed after a type name
print(Void.self) // ()
print(().dynamicType == Void.self) // true

路路路

On 04.07.2016 0:47, Anton Zhilin via swift-evolution wrote:

On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Austin Zheng) #5

Void is just a typealias for (). () is the only type in Swift whose type and only instance are spelled the same way, as far as I can tell. This isn't true for Void, since Void is only a type, not the value.

As for the zero-argument/one-argument problem...how often does realistic code need to pass in a zero-argument function to a function type that takes one argument? If the answer is "often", we should consider what it would take to define an implicit conversion. Otherwise, maybe we can get away with a standard library adapter that can be used to wrap a () -> T as a U -> T (where U = () or something).

Austin

路路路

On Jul 3, 2016, at 3:35 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 04.07.2016 0:47, Anton Zhilin via swift-evolution wrote:

Vladimir.S via swift-evolution <swift-evolution@...> writes:

On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:

let x = (Int, Int)(1, 2) //=> (1, 2)
let y = (Int)(1) //=> 1
let z = ()() // error :frowning:

Am I requesting too much from type checker?

As I understand, because () is Void, you can't have anything additional

for

it. It is just Void, like you write 'let z = Void Void'. I.e. only 'let

z =

()' allowed.

In the example, that's how I expect that to parse:

let z = ().init() // just demo, does not compile

I mean, first () is type, and second () is its initializer.

By the way, this is one thing that Void can do, but () cannot.
Are there any others?

I believe in this case () is playing a role of instance of type Void, i.e. empty tuple. I don't think you can expect ().init()

Also:
func f(_ x: ())->() {}
f(())
//f(Void) // argument passed to call that takes no arguments

And just some fun:

let x1 : Void
//let x2 : Void = Void // cannot convert value of type 'Void.Type' (aka '().Type') to specified type 'Void' (aka '()')
let x3 : ()
let x4 : () = ()
let x5 : Void = ()
//let x4 : () = Void // cannot convert value of type 'Void.Type' (aka '().Type') to specified type '()'

print(().dynamicType) // ()
print(().self) // ()
// print("Void.dynamicType = ", Void.dynamicType) // '.dynamicType' is not allowed after a type name
print(Void.self) // ()
print(().dynamicType == Void.self) // true

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Austin Zheng) #6

I considered that (and I think it's a fine overall solution), but it just
feels weird to me to change the arity of a function like that implicitly.
(I consider that a separate case from the return value, since every
function returns exactly one thing and many, many things in Swift would
break if functions didn't return Void instead of nothing at all.)

This isn't a strong objection from me; I would just prefer to see if there
are any solutions that work just as well and don't require a special case.
In particular, I'm curious about whether () -> U to T -> U implicit
conversion really is a good idea; if a parameter of function type is
generic on an input value I would assume it's almost certainly because it
intends to pass in some meaningful value into that function value. Would a
no-magic wrapper (like the SinkType of old) be convenient enough to do the
trick?

Austin

路路路

On Sun, Jul 3, 2016 at 3:44 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Why can't () as an argument list be regarded as the same as (()) just like
no return type is regarded as the same as `-> ()`?

On Sun, Jul 3, 2016 at 17:41 Austin Zheng via swift-evolution < > swift-evolution@swift.org> wrote:

Void is just a typealias for (). () is the only type in Swift whose type
and only instance are spelled the same way, as far as I can tell. This
isn't true for Void, since Void is only a type, not the value.

As for the zero-argument/one-argument problem...how often does realistic
code need to pass in a zero-argument function to a function type that takes
one argument? If the answer is "often", we should consider what it would
take to define an implicit conversion. Otherwise, maybe we can get away
with a standard library adapter that can be used to wrap a () -> T as a U
-> T (where U = () or something).

Austin

> On Jul 3, 2016, at 3:35 PM, Vladimir.S via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> On 04.07.2016 0:47, Anton Zhilin via swift-evolution wrote:
>> Vladimir.S via swift-evolution <swift-evolution@...> writes:
>>
>>> On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:
>>>> let x = (Int, Int)(1, 2) //=> (1, 2)
>>>> let y = (Int)(1) //=> 1
>>>> let z = ()() // error :frowning:
>>>>
>>>> Am I requesting too much from type checker?
>>>
>>> As I understand, because () is Void, you can't have anything
additional
>> for
>>> it. It is just Void, like you write 'let z = Void Void'. I.e. only
'let
>> z =
>>> ()' allowed.
>>
>> In the example, that's how I expect that to parse:
>>
>> let z = ().init() // just demo, does not compile
>>
>> I mean, first () is type, and second () is its initializer.
>>
>> By the way, this is one thing that Void can do, but () cannot.
>> Are there any others?
>>
>
> I believe in this case () is playing a role of instance of type Void,
i.e. empty tuple. I don't think you can expect ().init()
>
> Also:
> func f(_ x: ())->() {}
> f(())
> //f(Void) // argument passed to call that takes no arguments
>
> And just some fun:
>
> let x1 : Void
> //let x2 : Void = Void // cannot convert value of type 'Void.Type' (aka
'().Type') to specified type 'Void' (aka '()')
> let x3 : ()
> let x4 : () = ()
> let x5 : Void = ()
> //let x4 : () = Void // cannot convert value of type 'Void.Type' (aka
'().Type') to specified type '()'
>
> print(().dynamicType) // ()
> print(().self) // ()
> // print("Void.dynamicType = ", Void.dynamicType) // '.dynamicType' is
not allowed after a type name
> print(Void.self) // ()
> print(().dynamicType == Void.self) // true
>
>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #7

Why can't () as an argument list be regarded as the same as (()) just like
no return type is regarded as the same as `-> ()`?

路路路

On Sun, Jul 3, 2016 at 17:41 Austin Zheng via swift-evolution < swift-evolution@swift.org> wrote:

Void is just a typealias for (). () is the only type in Swift whose type
and only instance are spelled the same way, as far as I can tell. This
isn't true for Void, since Void is only a type, not the value.

As for the zero-argument/one-argument problem...how often does realistic
code need to pass in a zero-argument function to a function type that takes
one argument? If the answer is "often", we should consider what it would
take to define an implicit conversion. Otherwise, maybe we can get away
with a standard library adapter that can be used to wrap a () -> T as a U
-> T (where U = () or something).

Austin

> On Jul 3, 2016, at 3:35 PM, Vladimir.S via swift-evolution < > swift-evolution@swift.org> wrote:
>
> On 04.07.2016 0:47, Anton Zhilin via swift-evolution wrote:
>> Vladimir.S via swift-evolution <swift-evolution@...> writes:
>>
>>> On 03.07.2016 23:53, Anton Zhilin via swift-evolution wrote:
>>>> let x = (Int, Int)(1, 2) //=> (1, 2)
>>>> let y = (Int)(1) //=> 1
>>>> let z = ()() // error :frowning:
>>>>
>>>> Am I requesting too much from type checker?
>>>
>>> As I understand, because () is Void, you can't have anything additional
>> for
>>> it. It is just Void, like you write 'let z = Void Void'. I.e. only 'let
>> z =
>>> ()' allowed.
>>
>> In the example, that's how I expect that to parse:
>>
>> let z = ().init() // just demo, does not compile
>>
>> I mean, first () is type, and second () is its initializer.
>>
>> By the way, this is one thing that Void can do, but () cannot.
>> Are there any others?
>>
>
> I believe in this case () is playing a role of instance of type Void,
i.e. empty tuple. I don't think you can expect ().init()
>
> Also:
> func f(_ x: ())->() {}
> f(())
> //f(Void) // argument passed to call that takes no arguments
>
> And just some fun:
>
> let x1 : Void
> //let x2 : Void = Void // cannot convert value of type 'Void.Type' (aka
'().Type') to specified type 'Void' (aka '()')
> let x3 : ()
> let x4 : () = ()
> let x5 : Void = ()
> //let x4 : () = Void // cannot convert value of type 'Void.Type' (aka
'().Type') to specified type '()'
>
> print(().dynamicType) // ()
> print(().self) // ()
> // print("Void.dynamicType = ", Void.dynamicType) // '.dynamicType' is
not allowed after a type name
> print(Void.self) // ()
> print(().dynamicType == Void.self) // true
>
>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution