[swift-evolution] [Pitch] Nil struct

Adrian Zubarev adrian.zubarev at devandartist.com
Tue Nov 8 14:44:53 CST 2016


At first glance this doesn’t make any sense to me:

public protocol ExpressibleByNilLiteral {
  associatedtype NilLiteralType = Nil
  init(nilLiteral: NilLiteralType)
}
What’s the need for associatedtype there?

Shouldn’t it be just like this:

public protocol ExpressibleByNilLiteral {

  init(nilLiteral: Nil)
}
I actually would appreciate this change, because of one thing I run into a few days ago.

I’m building a library for BSON (Binary JSON) where I have a struct Document which conforms to ExpressibleByDictionaryLiteral. Than I have a protocol which can convert any type to a value type my document can store.

Now I would have to choose how to implement ExpressibleByDictionaryLiteral:

public init(dictionaryLiteral elements: (String, Element.Value)...)

public init(dictionaryLiteral elements: (String, ElementValueConvertible)…)

If I would go for the second version, I’d lose the ExpressibleByNilLiteral from my value type but I could use every other type naturally.

With the proposed change I could extend Nil with my protocol and make the conversion naturally again.

That is the only advantage I would gain from such a change in the language.



-- 
Adrian Zubarev
Sent with Airmail

Am 8. November 2016 um 21:30:26, Anton Zhilin via swift-evolution (swift-evolution at swift.org) schrieb:

Gist link

Introduction

Change  
nil literal type from  
() to  
Nil.
Before:

public protocol ExpressibleByNilLiteral {
  init(nilLiteral: ())
}
After:

public struct Nil {
  init()
}
public protocol ExpressibleByNilLiteral {
  associatedtype NilLiteralType = Nil
  init(nilLiteral: NilLiteralType)
}
Motivation

Currently,  
nil differs from other literals: it doesn’t have its own type.
But in some cases we want to deal directly with it, without creating any instances.

The most important use case is comparison of an  
Optional to  
nil.
Currently, this operation is implemented using a hidden struct  
_OptionalNilComparisonType,
which is needed precisely because because  
nil does not have its own type.
Removal of such underscored types is one of the goals stated in Generics manifesto.

Additionally, declaration of  
ExpressibleByNilLiteral differs from all other  
Expressibles,
because it doesn’t have a  
Literal type. It is generally beneficial to eliminate special cases.

Proposed solution

Introduce a struct  
Nil, which becomes the default type for  
nil literals:

public struct Nil : ExpressibleByNilLiteral {
  init()
  init(nilLiteral: NilLiteralType)
}

let a = nil
print(type(of: a))   //=> Nil
Rewrite  
ExpressibleByNilLiteral:

public protocol ExpressibleByNilLiteral {
  associatedtype NilLiteralType = Nil
  init(nilLiteral: NilLiteralType)
}
Make use of  
Nil in the standard library:

public func == <T>(left: T?, right: Nil)
public func == <T>(left: Nil, right: T?)
public func != <T>(left: T?, right: Nil)
public func != <T>(left: Nil, right: T?)
public func ~= <T>(left: Nil, right: T?)
Source compatibility


Nil identifier is taken, therefore applications that already use it will stop compiling.
Automatic migration is somewhat possible by renaming of the old entity; manual migration is recommended.

Applications that use declare  
ExpressibleByNilLiteral conformances will stop compiling.
Automatic migration is possible.

Effect on ABI stability

Applications that use  
Nil identifier will have to make ABI-breaking changes.

Otherwise, the change can mostly be applied in an ABI-compatible manner.

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161108/5b7ea081/attachment.html>


More information about the swift-evolution mailing list