In addition to being unspecific, how would you access an optional closure?  
Since trailing operators can’t be separated with whitespace, how do you 
differentiate two trailing “?” from a “??” operator?

i.e. 

let a:Int? = ...
let b:Int? = ...
let someFunction:((Int, Int)->(Int))? = ...
let c = someFunction??(a, b)

It seems like it’s trying to provide a fallback of (Int?, Int?) instead of Int?.
I’m on the side of using the postfix “?” on the specific optional values, not 
on the function name.  It has the benefit of not being confusing to someone new 
approaching the language because they are adjacent to the thing to change 
instead of in some other location.

In response to other criticisms, it seems very odd to me that the question of 
evaluation order of arguments is a serious problem for the original idea.


> On Dec 12, 2017, at 2:32 PM, Adrian Zubarev via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> I propose that we do not add a suffix ? to the arguments because it does not 
> really signal that the whole function may return an optional value. This is 
> especially not convenient in a nested scenario like mentioned by others in 
> previous posts. Instead we should reuse the inifix ? on functions, subscripts 
> and initializer. This way we can signal that the function might fail if one 
> of the provided optional arguments could not be unwrapped where the function 
> expects a non-optional argument. If the return type was already an optional, 
> we do not generate a nested optional, because there is no real reason for us 
> to do so. All arguments can simply be passed to the function with an infix ? 
> in their current form. If all non-optional parameter types match with the 
> argument types - optional parameter types can safely be ignored - we generate 
> an error, thus we don’t need an infix ?, otherwise the conversion happens 
> implicitly. This approach removes the need for explicit argument annotations, 
> which is IMHO boilerplate in first place. It also provides a hint to the 
> reader that some of the passed arguments should be unwrapped to succeed. In 
> every chase the ? is always close to the parameter list ?(_:_:...).
> 
> Here are some simple examples to consider: 
> 
> func first(one: A, two: B, three: C?) -> D { ... }
> func second(one: A, two: B, three: C?) -> D? { ... }
> ————————————————————————————————————————————————
> 
> // error when adding infix `?` if all arguments match the types
> first?(one: a, two: b, three: c) // c can be both optional and non-optional
> ————————————————————————————————————————————————
> 
> // no need for infix `?`
> first(one: a, two: b, three: optionalC) // returns `D`  
> ————————————————————————————————————————————————
> 
> // sugared
> first?(one: optionalA, two: b, three: c) // returns `D?` if succeed
> 
> // desugared
> { () -> D? in
>     if let someA = optionalA {
>         return first(one: someA, two: b, three: c)
>     } else {
>         return nil
>     }
> }()
> ————————————————————————————————————————————————
> 
> // sugared
> first?(one: optionalA, two: optionalB, three: optionalC) // returns `D?` if 
> succeed
> 
> // desugared
> { () -> D? in
>     if let someA = optionalA, let someB = optionalB {
>         return first(one: someA, two: someB, three: optionalC)
>     } else {
>     return nil
>     }    
> }()
> ————————————————————————————————————————————————
> 
> // error when adding infix `?` if all arguments match the types
> second?(one: a, two: b, three: c) // c can be both optional and non-optional
> ————————————————————————————————————————————————
> 
> // no need for infix `?`
> second(one: a, two: b, three: optionalC) // returns `D?`  
> ————————————————————————————————————————————————
> 
> // sugared
> second?(one: optionalA, two: b, three: c) // returns `D?` if succeed - no 
> need for nested optionals!
> 
> // desugared
> { () -> D? in
>     if let someA = optionalA {
>         return second(one: someA, two: b, three: c)
>     } else {
>         return nil
>     }
> }()
> ————————————————————————————————————————————————
> 
> // sugared
> second?(one: optionalA, two: optionalB, three: optionalC) // returns `D?` if 
> succeed - no need for nested optionals!
> 
> // desugared
> { () -> D? in
>     if let someA = optionalA, let someB = optionalB {
>         return second(one: someA, two: someB, three: optionalC)
>     } else {
>         return nil
>     }
> }()
> Please note that this can only work with non-operator functions and 
> initializers. Operator functions cannot be referenced as normal functions yet 
> and optional subscripts would require a source breaking change to align with 
> that behaviour.
> 
> If I missed something where optional func from Objective-C results into 
> incompatibility with this approach, please fell free to correct me. From my 
> point of view I don’t see how this additional behaviour could break optional 
> func.
> 
> 
> 
> 
> 
> Am 12. Dezember 2017 um 19:47:25, Jared Khan via swift-evolution 
> (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:
> 
>> Even this small example I think this is still a little fiddly. If we add 
>> another required parameter to the Markdown initializer:
>> let readme = String(contentsOfFile: “README.md”).flatMap { Markdown(string: 
>> $0, flavor: .github) }
>> this starts to feel a little inside-out and crufty to me. 
>> 
>>> On 12 Dec 2017, at 05:54, Félix Cloutier <felixclout...@icloud.com 
>>> <mailto:felixclout...@icloud.com>> wrote:
>>> 
>>> You talk about flatMap without giving an example. The readme isn't that bad 
>>> with it, IMO:
>>> 
>>> if let readme = String(contentsOfFile: "README.md").flatMap(Markdown) {
>>> // use contents here
>>> }
>>> 
>>> That doesn't work when you need multiple optional parameters. In my own 
>>> experience, that hasn't been a huge problem, though.
>>> 
>>> Félix
>>> 
>>>> Le 11 déc. 2017 à 08:30, Jared Khan via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :
>>>> 
>>>> Hi all,
>>>> 
>>>> I'd like to propose a syntax addition that acts to ease some things that I 
>>>> believe should fall under the umbrella of 'optional chaining'. Optional 
>>>> chaining allows us to access the properties of an optional value and 
>>>> return nil if any link in that chain breaks. I propose we introduce syntax 
>>>> to allow similar chaining when passing optional valued parameters to 
>>>> functions that expect that parameter to be non-optional.
>>>> 
>>>> The example below is taken from a project I'm working on at the moment:
>>>> 
>>>> 
>>>> // Current
>>>> let readme: Markdown?
>>>> if let rawMarkdown = String(contentsOfFile: "README.md") {
>>>>         readme = Markdown(string: rawMarkdown)
>>>> } else {
>>>>         readme = nil
>>>> }
>>>> In this example we want to perform an operation, the initialisation of a 
>>>> 'Markdown' type, with our raw text if it exists and get nil otherwise. 
>>>> This is rather verbose
>>>> 
>>>> I propose the following syntax for an alternative:
>>>> 
>>>> 
>>>> // Proposed alternative
>>>> let readme = Markdown(string: String(contentsOfFile: "README.md")?)
>>>> 
>>>> The ? is familiar in its use for optional chaining.
>>>> 
>>>> This would act like syntactic sugar for the flatMap method on Optional. 
>>>> For example:
>>>> 
>>>> (where `john` is of a `Person` type with a property `address: Address?`)
>>>> // func getZipCode(fromAddress address: Address) -> ZipCode
>>>> getZipCode(fromAddress: john.address?)
>>>> 
>>>> // Would be equivalent to…
>>>> john.address.flatMap {
>>>>         getZipCode($0)
>>>> }
>>>> An example with multiple parameters:
>>>> 
>>>> // func getPostageEstimate(source: Address, destination: Address, weight: 
>>>> Double) -> Int
>>>> getPostageEstimate(source: john.address?, destination: alice.address?, 
>>>> weight: 2.0)
>>>> 
>>>> // Equivalent to
>>>> john.address.flatMap { freshVar1 in
>>>>         alice.address.flatMap { freshVar2 in
>>>>                 getPostageEstimate(source: freshVar1, destination: 
>>>> freshVar2, weight: 2.0)
>>>>         }
>>>> }
>>>> 
>>>> // Or equally:
>>>> {
>>>>         guard let freshVar1 = john.address,
>>>>                 let freshVar2 = alice.address else {
>>>>                         return nil
>>>>         }
>>>> 
>>>>         return getPostageEstimate(source: freshVar1, destination: 
>>>> freshVar2, weight: 2.0)
>>>> }()
>>>> This would only be allowed when the parameter doesn’t already accept 
>>>> Optionals and when the chained value is in fact an optional. We’d want to 
>>>> consider emitting at least the following errors/warnings in the given 
>>>> scenarios:
>>>> 
>>>> 
>>>> let result = myFunc(3?)
>>>> // error: cannot use optional chaining on non-optional value of type 'Int'
>>>> 
>>>> // func myFunc2(x: String?) -> String
>>>> let result = myFunc2(x: john.address?)
>>>> // error: cannot use optional argument chaining on argument of optional 
>>>> type
>>>> let result = myFunc(nil?)
>>>> // warning: optional argument chaining with nil literal always results in 
>>>> nil
>>>> 
>>>> Seeking your thoughts on this idea, the specific syntax, and more use case 
>>>> examples.
>>>> 
>>>> Best,
>>>> 
>>>> Jared
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <https://lists.swift.org/mailman/listinfo/swift-evolution>

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

Reply via email to