Re: [swift-evolution] Optional Argument Chaining

2017-12-17 Thread Elviro Rocca via swift-evolution
While it's definitely worth knowing, it's not a really usable substitute for 
higher-kinded types in production code, and still requires a lot of code 
generation, which is eased in Kotlin thanks to its annotation/metaprogramming 
features.

Event the Kategory people recognized that the emulation approach is a temporary 
solution, waiting for the approval of a proposal for the addition of HKTs to 
Kotlin itself.

Unfortunately, if we don't get HKTs in Swift we're simply going to miss on a 
barrage of extremely useful abstractions, upon that many contemporary languages 
have started to rely, because they are simply the best known solutions to many 
problems in many contexts.

The huge amount of work that's been done in academia in the last 15 years (and 
it's still going) about applicatives - and also profunctor optics, another 
thing that requires HKTs - is mostly going to elude Swift due to its crucial 
lack of expressivity.

We're on the right track with the approval of the conditional conformance 
proposal, but my fear is that the ABI stability requirement for Swift 5 is 
going to lock the language interfaces in a state where it's going to be 
impossible for these kinds of sophistications to be added to the language at a 
later stage... I hope to be proven wrong here.


Elviro 

> Il giorno 14 dic 2017, alle ore 15:40, Matthew Johnson via swift-evolution 
>  ha scritto:
> 
> 
> Thanks for jumping in and elaborating on a more general approach!  I don’t 
> want to sidetrack the thread, but it actually is possible to encode 
> higher-kindred types and protocols requiring them in Swift today.  It’s a bit 
> clunky and requires some boilerplate but the technique is worth knowing.  
> https://gist.github.com/anandabits/f12a77c49fc002cf68a5f1f62a0ac9c4 
> 
> 
> Some Kotlin folks have created a pretty robust FP library using the same 
> technique: http://kategory.io/ .
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-14 Thread Matthew Johnson via swift-evolution


Sent from my iPad

On Dec 13, 2017, at 11:13 PM, Stephen Celis  wrote:

>> On Dec 13, 2017, at 9:53 PM, Erica Sadun  wrote:
>> 
>> Chris L had a beautiful solution for an "Unwrappable" protocol that allowed 
>> all of the optional sugar to be extended to any type that had a biased 
>> `Wrapped` item, allowing it to be used with `Either`, `Wrapped`, etc as well 
>> as form the basis for `Optional` itself.
>> 
>> protocol Unwrappable {
>>  associatedtype Element
>>  func unwrap() -> Element?
>> }
> 
> It would definitely be nice to make "Optional" sugar work for non-"Optional" 
> types! (I think the goal for "async"/"await" is to make it work for any 
> continuation, so it's basically Haskell "do" notation for Swift!)
> 
> I'm not sure the "Unwrappable" protocol can handle many of the examples I 
> mentioned (accumulative errors, parallelism), though I wonder if it could be 
> designed differently to do so. The applicative structure requires just 2 
> functions[1]:
> 
>protocol Applicative: Functor {
>  static func pure(_ value: A) -> Self
>  static func <*> (lhs: Self<(A) -> B>, rhs: Self) -> Self 
>}
> 
> Such a protocol isn't possible in Swift (yet),

Thanks for jumping in and elaborating on a more general approach!  I don’t want 
to sidetrack the thread, but it actually is possible to encode higher-kindred 
types and protocols requiring them in Swift today.  It’s a bit clunky and 
requires some boilerplate but the technique is worth knowing.  
https://gist.github.com/anandabits/f12a77c49fc002cf68a5f1f62a0ac9c4

Some Kotlin folks have created a pretty robust FP library using the same 
technique: http://kategory.io/.

> but it could unlock this kind of sugar for everyone. Here's "Optional" 
> conformance:
> 
>extension Optional: Applicative {
>  static func pure(_ value: Wrapped) -> Wrapped? {
>return value // promoted to Optional.some
>  }
> 
>  static func <*> (lhs: Optional<(Wrapped) -> B>, rhs: Optional) -> B? {
>guard let lhs = lhs, rhs = rhs else { return nil }
>return lhs(rhs)
>  }
>}
> 
> We can't conform to such an "Applicative" protocol today, but we _can_ still 
> write and use these functions in a concrete manner! (Delete the conformance 
> and see!)
> 
> The original post in this thread had this example:
> 
>getPostageEstimate(source: String, destination: String, weight: Double)
> 
> If we were dealing with this function in the world of optional arguments, 
> here's how we could use our abstraction:
> 
>Optional.pure(curry(getPostageEstimate)) <*> john.address <*> 
> alice.address <*> pure(2.0)
> 
> It's not _too_ bad, though it's kinda noisy, we have to maintain a bunch of 
> custom code, we have to curry "getPostageEstimate" before passing it through, 
> we lose our argument labels, and we're living in custom operator world, which 
> can be disconcerting at first.
> 
> If Swift provided sugar over this structure, we'd merely need to do this:
> 
>getPostageEstimate(|source: john.address, destination: alice.address, 
> weight: 2.0|)
> 
> What's even neater is we can use this same format for types that wrap values 
> in other ways! Let's say the addresses are coming from untrusted sources and 
> need to be validated:
> 
>getPostageEstimate(|source: try validateAddr(john), destination: try 
> validateAddr(alice), weight: 2.0|)
> 
> If both addresses are invalid and "throw", we could get both errors and 
> render them at once to our end user.
> 
> Another example: what if we want to get the postage estimate for two 
> addresses that we need to fetch asynchronously:
> 
>getPostageEstimate(|source: await myAddress(), destination: await 
> theirAddress(), weight: 2.0|)
> 
> Such a syntax allows those requests to run in parallel and not block :)
> 
> In these examples, "Optional" promotion becomes applicative promotion ("2.0" 
> is getting wrapped automatically), which might open a can of worms but it's a 
> fun can to think about!
> 
> 
> --
> [1]: Well, technically it also requires "map", since any applicative is a 
> functor, and it also requires that it follows some math laws.
> 
> 
> Stephen
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Optional Argument Chaining

2017-12-14 Thread Pertti Kröger via swift-evolution
I do not feel new syntax is needed for this.
You can do this currently:

postfix operator ¿

extension Optional {
struct UnwrapError: Error {}
static postfix func ¿(_ value: Optional) throws -> Wrapped {
if let value = value {
return value
} else {
throw UnwrapError()
}
}
}

Given function f: (Foo, Foo, Foo) -> Void
and functions a, b, c: () -> Foo?
you would then chain the calls like

try? f(a()¿, b()¿, c()¿)

This is hardly more verbose than

f(a()?, b()?, c()?)

At least on mac keyboard ¿ is not hard to type either.
Also everyone is free to bikeshed the operator to their liking.

If special syntax were to be added for this, then in my opinion
the behaviour should mimic this; i.e. evaluate arguments left-to-right,
abort on first nil.

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-13 Thread Erica Sadun via swift-evolution


> On Dec 13, 2017, at 10:20 AM, Stephen Celis via swift-evolution 
>  wrote:
> 
>> On Dec 11, 2017, at 1:08 PM, Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> It’s worth mentioning that the problem this thread is discussing can be 
>> generalized to idioms / applicative.  The specific case here is for Optional 
>> but many other types could benefit from an elegant syntactic solution to 
>> this problem.  It might be worth exploring a more general solution.  Here’s 
>> a link to how this is handled in Idris: 
>> http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#idiom-brackets.
>> 
>> Matthew
> 
> Just want to +1 a more general, less "Optional"-specific solution. You can do 
> a ton of interesting things with applicative structure.
> 

Chris L had a beautiful solution for an "Unwrappable" protocol that allowed all 
of the optional sugar to be extended to any type that had a biased `Wrapped` 
item, allowing it to be used with `Either`, `Wrapped`, etc as well as form the 
basis for `Optional` itself.

protocol Unwrappable {
associatedtype Element
func unwrap() -> Element?
}

I have a proposal around somewhere.(1)

-- E
(1) But then again, I have a lot of those


> Failures from "Optional" and "throws" operate sequentially and halt 
> immediately: the first "nil" or "throw" encountered prevents all work chained 
> from it[1]. Another upcoming sequential operation that's worth thinking about 
> in this discussion: "async"/"await".
> 
> Applicative structures throw away that sequential constraint. Let's consider 
> some fun things that happen when we take it away in a couple of the examples 
> above.
> 
> If "throws" were applicative, you could accumulate a bunch of errors at once.
> 
>do { 
>  // made-up syntax
>  let user = User(|name: try validate(name: name), email: try 
> validate(email: email)|)
>} catch {
>  print(error) // .manyErrors(["name is too short", "email is invalid"])
>}
> 
> Currently, the above would halt on the first error.
> 
> If "async"/"await" were applicative, you could fire off a bunch of 
> asynchronous requests in parallel.
> 
>let homepageData = HomepageData(|await fetchCurrentUser(), await 
> fetchProducts()|)
> 
> In the proposed version of "async"/"await", the above would block on 
> "fetchCurrentUser()" and only call "fetchProducts()" after the response.
> 
> "Optional" would get to use that same sugar! An example from the original 
> email:
> 
>getPostageEstimate(|source: john.address, destination: alice.address, 
> weight 2.0|)
> 
> 
> --
> [1]: "Optional" and "throws" are monadic structures and "flatMap" is the 
> abstraction of this sequential operation.
> 
> 
> Stephen
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-13 Thread Stephen Celis via swift-evolution
> On Dec 11, 2017, at 1:08 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> It’s worth mentioning that the problem this thread is discussing can be 
> generalized to idioms / applicative.  The specific case here is for Optional 
> but many other types could benefit from an elegant syntactic solution to this 
> problem.  It might be worth exploring a more general solution.  Here’s a link 
> to how this is handled in Idris: 
> http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#idiom-brackets.
> 
> Matthew

Just want to +1 a more general, less "Optional"-specific solution. You can do a 
ton of interesting things with applicative structure.

Failures from "Optional" and "throws" operate sequentially and halt 
immediately: the first "nil" or "throw" encountered prevents all work chained 
from it[1]. Another upcoming sequential operation that's worth thinking about 
in this discussion: "async"/"await".

Applicative structures throw away that sequential constraint. Let's consider 
some fun things that happen when we take it away in a couple of the examples 
above.

If "throws" were applicative, you could accumulate a bunch of errors at once.

do { 
  // made-up syntax
  let user = User(|name: try validate(name: name), email: try 
validate(email: email)|)
} catch {
  print(error) // .manyErrors(["name is too short", "email is invalid"])
}

Currently, the above would halt on the first error.

If "async"/"await" were applicative, you could fire off a bunch of asynchronous 
requests in parallel.

let homepageData = HomepageData(|await fetchCurrentUser(), await 
fetchProducts()|)

In the proposed version of "async"/"await", the above would block on 
"fetchCurrentUser()" and only call "fetchProducts()" after the response.

"Optional" would get to use that same sugar! An example from the original email:

getPostageEstimate(|source: john.address, destination: alice.address, 
weight 2.0|)


--
[1]: "Optional" and "throws" are monadic structures and "flatMap" is the 
abstraction of this sequential operation.


Stephen

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-13 Thread Jonathan Hull via swift-evolution
+1 to this.  I also like Adrian’s notation where the ? is after the name, but 
before the parameter list.

> On Dec 12, 2017, at 7:33 AM, Yuta Koshizawa via swift-evolution 
>  wrote:
> 
> I think evaluating them in the same way as `try` calls is consistent.
> 
> ```
> f(g()?, h()?, i(), j()?)?
> // like
> try f(try g(), try h(), i(), try j())
> ```
> 
> ```
> foo(bar(x()?)) + y()?
> // like
> foo(bar(try x())) + (try y())
> ```
> 
> --
> Yuta
> 
> 
> 2017-12-12 7:42 GMT+09:00 Slava Pestov via swift-evolution
> :
>> 
>> 
>> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution
>>  wrote:
>> 
>> I missed the previous threads! I’ve found one of the relevant threads here:
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>> 
>> Thanks for this important point.
>> 
>> If you were to write this logic out by hand then you would short-circuit it
>> and this is analogous to current chaining behaviour so to me evaluating left
>> to right (as Swift usually does) and stopping at the first failed unwrap
>> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t
>> think it’s really less intuitive than the current chaining behaviour.
>> 
>> 
>> I think it gets confusing when you have multiple levels of nested
>> expressions, eg
>> 
>> foo(bar(x?)) + y?
>> 
>> Slava
>> 
>> 
>> Jared
>> 
>> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> This topic has been discussed at least two and maybe more times in the
>> past.. It’s hard for me to post links at the moment, but it should be
>> possible to find on Google.
>> 
>> One major challenge to this idea, for which no satisfactory answer has been
>> achieved after all these years, is the following issue:
>> 
>> f(g()?, h()?, i(), j()?)?
>> 
>> If g() evaluates to nil, is h() called or not? How about i(), which is not
>> failable? Since any function or property access can have side effects, in
>> what order are the arguments evaluated, and how does one reason about this
>> code flow?
>> 
>> To my mind, in the absence of an intuitive answer to the above—which does
>> not appear to be possible—this idea is not feasible.
>> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution
>>  wrote:
>>> 
>>> 
 12 Dec. 2017 02:58 Jared Khan  wrote:
 
 2. It felt natural to me. It’s analogous to the existing optional
 chaining scenarios and composes nicely. I think it’s about as 
 understandable
 as existing chaining, a newbie would have to look it up to discover its
 meaning. What are your thoughts on this particular syntax (ignoring 3.
 momentarily)? Hopefully others in this thread can share their views too.
>>> 
>>> Chaining methods is linear, while nesting fills a similar purpose when we
>>> use function calls. This of course affects the way existing Swift code is
>>> written, but that is something we have to live with if we want to use
>>> familiar syntax patterns. However, I think we have to consider this
>>> difference in this case, since the syntax becomes more convoluted. Your
>>> suggestion is definitely not as easy to read as the optional chaining
>>> syntax, and maybe it can't be.
>>> 
 As for how common I’d expect it to be, it’s something I’ve run into
 myself a few times. Again, I hope members of this list can give their view
 on if this would be useful to them.
>>> 
>>> I don't have any real examples, but I certainly think that I have run into
>>> it, so I'm quite open to solving the problem. For me, it is probably only a
>>> matter of finding a syntax that is acceptable.
>>> 
 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
 has never been available as a postfix operator. Perhaps I’m missing your
 point, could you demonstrate where it is allowed?
>>> 
>>> I did not expect that you would be able to answer that, it was more a
>>> question directed to people who are more connected to the inner workings of
>>> the parsing of Swift than I am. It is not allowed, but the error message is
>>> not the one I expect, something that gives me a hint that it does have some
>>> meaning early in the parsing.
>>> 
>>> /Magnus
>>> 
>>> ___
>>> 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
>> 
>> 
>> 
>> ___
>> swift-evolution mailing list
>> 

[swift-evolution] Optional Argument Chaining

2017-12-12 Thread Xiang Deng via swift-evolution
Hi all,

We probably don't need additional syntax to achieve this. I just wrote a 
library which allows you to `(pass?.aLongOptionalChaining()?.to ?< 
aFunctionTakingNonOptionalValues(:))?.ThenDoSomethingElse()` with `?>` operator.

The multiple parameters example:

(john.address, alice.address, 2.0) ?> 
getPostageEstimate(source:destination:weight:)

> // Equivalent to

> john.address.flatMap { freshVar1 in
>   alice.address.flatMap { freshVar2 in
>   getPostageEstimate(source: freshVar1, destination: freshVar2, 
> weight: 2.0)
>   }
> }


See more about the library: https://github.com/xxx/ChainingFunction 


--
Xander

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Adrian Zubarev via swift-evolution
That’s actually the cool part of merging optional func infix ? with the 
discussed problem. If you think how we could represent optional func in pure 
swift only with some sugar (and also the ability to write var 
function(label:label:) which we’ll get at some point) then we could do this:

protocol P {
optional func foo(label: Int)
}

// compiler could synthesize this for you:
extension P {
default var foo(label:): ((Int) -> Void)? { return nil }
}

(someInstance as P).foo?(label: 42)
default is from 
https://github.com/erica/swift-evolution/blob/a260a33ca39676b41e0436c4dccdb78441308c13/proposals/-role-keywords.md

Now back to your example, the answer becomes really easy:

let c = someFunction?(a, b)

This can then be desugared to:

let c = {
if let someFunction = someFunction, let someA = a, let someB = b {
return someFunction(someA, someB)
} else {
return nil
}
}
In any case c would be Optional.




Am 12. Dezember 2017 um 20:42:20, Benjamin Spratling (bspratl...@mac.com) 
schrieb:

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 
 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: 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Benjamin Spratling via swift-evolution
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 
>  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 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Adrian Zubarev via swift-evolution
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) 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  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 
 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 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Jared Khan via swift-evolution
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  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 
>> > 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 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Jared Khan via swift-evolution
I’d agree with that. That’s consistent with the “left-to-right and 
short-circuit at first failure” approach.

> On 12 Dec 2017, at 15:33, Yuta Koshizawa  wrote:
> 
> I think evaluating them in the same way as `try` calls is consistent.
> 
> ```
> f(g()?, h()?, i(), j()?)?
> // like
> try f(try g(), try h(), i(), try j())
> ```
> 
> ```
> foo(bar(x()?)) + y()?
> // like
> foo(bar(try x())) + (try y())
> ```
> 
> --
> Yuta
> 
> 
> 2017-12-12 7:42 GMT+09:00 Slava Pestov via swift-evolution
> :
>> 
>> 
>> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution
>>  wrote:
>> 
>> I missed the previous threads! I’ve found one of the relevant threads here:
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>> 
>> Thanks for this important point.
>> 
>> If you were to write this logic out by hand then you would short-circuit it
>> and this is analogous to current chaining behaviour so to me evaluating left
>> to right (as Swift usually does) and stopping at the first failed unwrap
>> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t
>> think it’s really less intuitive than the current chaining behaviour.
>> 
>> 
>> I think it gets confusing when you have multiple levels of nested
>> expressions, eg
>> 
>> foo(bar(x?)) + y?
>> 
>> Slava
>> 
>> 
>> Jared
>> 
>> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> This topic has been discussed at least two and maybe more times in the
>> past.. It’s hard for me to post links at the moment, but it should be
>> possible to find on Google.
>> 
>> One major challenge to this idea, for which no satisfactory answer has been
>> achieved after all these years, is the following issue:
>> 
>> f(g()?, h()?, i(), j()?)?
>> 
>> If g() evaluates to nil, is h() called or not? How about i(), which is not
>> failable? Since any function or property access can have side effects, in
>> what order are the arguments evaluated, and how does one reason about this
>> code flow?
>> 
>> To my mind, in the absence of an intuitive answer to the above—which does
>> not appear to be possible—this idea is not feasible.
>> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution
>>  wrote:
>>> 
>>> 
 12 Dec. 2017 02:58 Jared Khan  wrote:
 
 2. It felt natural to me. It’s analogous to the existing optional
 chaining scenarios and composes nicely. I think it’s about as 
 understandable
 as existing chaining, a newbie would have to look it up to discover its
 meaning. What are your thoughts on this particular syntax (ignoring 3.
 momentarily)? Hopefully others in this thread can share their views too.
>>> 
>>> Chaining methods is linear, while nesting fills a similar purpose when we
>>> use function calls. This of course affects the way existing Swift code is
>>> written, but that is something we have to live with if we want to use
>>> familiar syntax patterns. However, I think we have to consider this
>>> difference in this case, since the syntax becomes more convoluted. Your
>>> suggestion is definitely not as easy to read as the optional chaining
>>> syntax, and maybe it can't be.
>>> 
 As for how common I’d expect it to be, it’s something I’ve run into
 myself a few times. Again, I hope members of this list can give their view
 on if this would be useful to them.
>>> 
>>> I don't have any real examples, but I certainly think that I have run into
>>> it, so I'm quite open to solving the problem. For me, it is probably only a
>>> matter of finding a syntax that is acceptable.
>>> 
 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
 has never been available as a postfix operator. Perhaps I’m missing your
 point, could you demonstrate where it is allowed?
>>> 
>>> I did not expect that you would be able to answer that, it was more a
>>> question directed to people who are more connected to the inner workings of
>>> the parsing of Swift than I am. It is not allowed, but the error message is
>>> not the one I expect, something that gives me a hint that it does have some
>>> meaning early in the parsing.
>>> 
>>> /Magnus
>>> 
>>> ___
>>> 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
>> 
>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Yuta Koshizawa via swift-evolution
I think evaluating them in the same way as `try` calls is consistent.

```
f(g()?, h()?, i(), j()?)?
// like
try f(try g(), try h(), i(), try j())
```

```
foo(bar(x()?)) + y()?
// like
foo(bar(try x())) + (try y())
```

--
Yuta


2017-12-12 7:42 GMT+09:00 Slava Pestov via swift-evolution
:
>
>
> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution
>  wrote:
>
> I missed the previous threads! I’ve found one of the relevant threads here:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>
> Thanks for this important point.
>
> If you were to write this logic out by hand then you would short-circuit it
> and this is analogous to current chaining behaviour so to me evaluating left
> to right (as Swift usually does) and stopping at the first failed unwrap
> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t
> think it’s really less intuitive than the current chaining behaviour.
>
>
> I think it gets confusing when you have multiple levels of nested
> expressions, eg
>
> foo(bar(x?)) + y?
>
> Slava
>
>
> Jared
>
> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution
>  wrote:
>
> This topic has been discussed at least two and maybe more times in the
> past.. It’s hard for me to post links at the moment, but it should be
> possible to find on Google.
>
> One major challenge to this idea, for which no satisfactory answer has been
> achieved after all these years, is the following issue:
>
> f(g()?, h()?, i(), j()?)?
>
> If g() evaluates to nil, is h() called or not? How about i(), which is not
> failable? Since any function or property access can have side effects, in
> what order are the arguments evaluated, and how does one reason about this
> code flow?
>
> To my mind, in the absence of an intuitive answer to the above—which does
> not appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution
>  wrote:
>>
>>
>> > 12 Dec. 2017 02:58 Jared Khan  wrote:
>> >
>> > 2. It felt natural to me. It’s analogous to the existing optional
>> > chaining scenarios and composes nicely. I think it’s about as 
>> > understandable
>> > as existing chaining, a newbie would have to look it up to discover its
>> > meaning. What are your thoughts on this particular syntax (ignoring 3.
>> > momentarily)? Hopefully others in this thread can share their views too.
>>
>> Chaining methods is linear, while nesting fills a similar purpose when we
>> use function calls. This of course affects the way existing Swift code is
>> written, but that is something we have to live with if we want to use
>> familiar syntax patterns. However, I think we have to consider this
>> difference in this case, since the syntax becomes more convoluted. Your
>> suggestion is definitely not as easy to read as the optional chaining
>> syntax, and maybe it can't be.
>>
>> > As for how common I’d expect it to be, it’s something I’ve run into
>> > myself a few times. Again, I hope members of this list can give their view
>> > on if this would be useful to them.
>>
>> I don't have any real examples, but I certainly think that I have run into
>> it, so I'm quite open to solving the problem. For me, it is probably only a
>> matter of finding a syntax that is acceptable.
>>
>> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
>> > has never been available as a postfix operator. Perhaps I’m missing your
>> > point, could you demonstrate where it is allowed?
>>
>> I did not expect that you would be able to answer that, it was more a
>> question directed to people who are more connected to the inner workings of
>> the parsing of Swift than I am. It is not allowed, but the error message is
>> not the one I expect, something that gives me a hint that it does have some
>> meaning early in the parsing.
>>
>> /Magnus
>>
>> ___
>> 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
>
>
>
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Jonathan Hull via swift-evolution
In my opinion, simple left to right evaluation where it short circuits on the 
first failure is the simplest.  But I don’t think it matters that much as long 
as we have a consistent way to define it, and explain it.

It is nice to have forward transfer from other features, but sometimes we just 
need to forge ahead to create something new and then have education on the new 
feature.


> On Dec 11, 2017, at 11:28 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This topic has been discussed at least two and maybe more times in the past. 
> It’s hard for me to post links at the moment, but it should be possible to 
> find on Google.
> 
> One major challenge to this idea, for which no satisfactory answer has been 
> achieved after all these years, is the following issue:
> 
> f(g()?, h()?, i(), j()?)?
> 
> If g() evaluates to nil, is h() called or not? How about i(), which is not 
> failable? Since any function or property access can have side effects, in 
> what order are the arguments evaluated, and how does one reason about this 
> code flow?
> 
> To my mind, in the absence of an intuitive answer to the above—which does not 
> appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
> > wrote:
> 
> > 12 Dec. 2017 02:58 Jared Khan > 
> > wrote:
> >
> > 2. It felt natural to me. It’s analogous to the existing optional chaining 
> > scenarios and composes nicely. I think it’s about as understandable as 
> > existing chaining, a newbie would have to look it up to discover its 
> > meaning. What are your thoughts on this particular syntax (ignoring 3. 
> > momentarily)? Hopefully others in this thread can share their views too.
> 
> Chaining methods is linear, while nesting fills a similar purpose when we use 
> function calls. This of course affects the way existing Swift code is 
> written, but that is something we have to live with if we want to use 
> familiar syntax patterns. However, I think we have to consider this 
> difference in this case, since the syntax becomes more convoluted. Your 
> suggestion is definitely not as easy to read as the optional chaining syntax, 
> and maybe it can't be.
> 
> > As for how common I’d expect it to be, it’s something I’ve run into myself 
> > a few times. Again, I hope members of this list can give their view on if 
> > this would be useful to them.
> 
> I don't have any real examples, but I certainly think that I have run into 
> it, so I'm quite open to solving the problem. For me, it is probably only a 
> matter of finding a syntax that is acceptable.
> 
> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ 
> > has never been available as a postfix operator. Perhaps I’m missing your 
> > point, could you demonstrate where it is allowed?
> 
> I did not expect that you would be able to answer that, it was more a 
> question directed to people who are more connected to the inner workings of 
> the parsing of Swift than I am. It is not allowed, but the error message is 
> not the one I expect, something that gives me a hint that it does have some 
> meaning early in the parsing.
> 
> /Magnus
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Adrian Zubarev via swift-evolution
I think it might be a good idea to reuse optional function syntax in this case. 
I don’t think it would even break existing code with the rule I described in my 
previous post. I mean, in the end the result of the whole function becomes 
optional (only if it was non-optional before, or it simply stays optional 
otherwise).

foo?(bar?(x)) +? y
Problematic are the operator functions because there is no way to really 
disambiguate those - at least right now, nor can we reference them like Int.+ 
and in the worse case it would require us to burn all operators with a trailing 
?. Even more complicated is the ?? operator.

On the other hand we could simply say that an operator function is a special 
case, where we cannot make the function optional with this syntax. That would 
mean that operator functions (and subscripts?) still would require the old 
fashion way:

let result: FooResult?
if lhs = foo?(bar?(x)), let rhs = y {
result = lhs + rhs
} else {
result = nil
}
However here is my thinking in a different direction for operator functions and 
subscripts:

If we could explicitly reference operator functions like Int.+ or Swift.??, 
would it be possible to disambiguate the above case like this?

(Int.+)?(lhs: foo?(bar?(x)), rhs: y)
Here is the syntax as pitched that works today:

@objc protocol P : AnyObject {
@objc optional static func functionName(label: Int)
@objc optional func otherFunctionName(label: Int)
}

@objc class A : NSObject, P {}

let type: P.Type = A.self
(type.functionName)?(label: 42)

let instance: P = A()
(instance.otherFunctionName)?(label: 42)
We may need to fix optional subscripts first because the implicit behavior is 
really weird IMHO:

@objc protocol P : AnyObject {
@objc optional subscript (label value: Int) -> Int { get }
}

@objc class A : NSObject, P {}

let instance: P = A()
instance[label: 42] // => compiles and returns nil
We definitely should require an infix ? here - instance?[label: 42].

Then even subscripts would work with the same syntax I pitched before. ;)


Am 11. Dezember 2017 um 23:42:58, Slava Pestov via swift-evolution 
(swift-evolution@swift.org) schrieb:



On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution 
 wrote:

I missed the previous threads! I’ve found one of the relevant threads here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html

Thanks for this important point.

If you were to write this logic out by hand then you would short-circuit it and 
this is analogous to current chaining behaviour so to me evaluating left to 
right (as Swift usually does) and stopping at the first failed unwrap would 
make sense. I wouldn’t necessarily say it’s intuitive but I don’t think it’s 
really less intuitive than the current chaining behaviour. 

I think it gets confusing when you have multiple levels of nested expressions, 
eg

foo(bar(x?)) + y?

Slava


Jared

On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution 
 wrote:

This topic has been discussed at least two and maybe more times in the past.. 
It’s hard for me to post links at the moment, but it should be possible to find 
on Google.

One major challenge to this idea, for which no satisfactory answer has been 
achieved after all these years, is the following issue:

f(g()?, h()?, i(), j()?)?

If g() evaluates to nil, is h() called or not? How about i(), which is not 
failable? Since any function or property access can have side effects, in what 
order are the arguments evaluated, and how does one reason about this code flow?

To my mind, in the absence of an intuitive answer to the above—which does not 
appear to be possible—this idea is not feasible.
On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
 wrote:

> 12 Dec. 2017 02:58 Jared Khan  wrote:
>
> 2. It felt natural to me. It’s analogous to the existing optional chaining 
> scenarios and composes nicely. I think it’s about as understandable as 
> existing chaining, a newbie would have to look it up to discover its meaning. 
> What are your thoughts on this particular syntax (ignoring 3. momentarily)? 
> Hopefully others in this thread can share their views too.

Chaining methods is linear, while nesting fills a similar purpose when we use 
function calls. This of course affects the way existing Swift code is written, 
but that is something we have to live with if we want to use familiar syntax 
patterns. However, I think we have to consider this difference in this case, 
since the syntax becomes more convoluted. Your suggestion is definitely not as 
easy to read as the optional chaining syntax, and maybe it can't be.

> As for how common I’d expect it to be, it’s something I’ve run into myself a 
> few times. Again, I hope members of this list can give their view on if this 
> would be useful to them.

I don't have any real examples, but I certainly think that I have run into 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Howard Lovatt via swift-evolution
To me the short syntax should be a ‘macro’ expansion (syntax sugar only), 
therefore option 1 in Nick’s example. I choose the syntax sugar option because 
it is easy to explain. 

-- Howard. 

> On 12 Dec 2017, at 7:03 pm, Nick Keets via swift-evolution 
>  wrote:
> 
> 
> 
>> On Tue, Dec 12, 2017 at 12:42 AM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> I think it gets confusing when you have multiple levels of nested 
>> expressions, eg
>> 
>> foo(bar(x?)) + y?
>> 
>> Slava
> 
> I'm not sure we need to optimize much for complicated nested examples, as I 
> don't think this is something that will happen a lot in practice. I imagine 
> the most common scenario will be a single call with one or more arguments.
> 
> Having said that, we did receive 2 different reasonable answers on what the 
> evaluation order would be for:
>   f(a(), b?)
> 
> (1) It desugars to:
> 
> if let someB = b {
>   f(a(), someB)
> }
> 
> So a() doesn't get called if b is nil.
> 
> (2) "If you were to write this logic out by hand then you would short-circuit 
> it and this is analogous to current chaining behaviour so to me evaluating 
> left to right (as Swift usually does) and stopping at the first failed unwrap 
> would make sense"
> 
> So a() gets called if b is nil.
> 
>  
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Nick Keets via swift-evolution
On Tue, Dec 12, 2017 at 12:42 AM, Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

>
> I think it gets confusing when you have multiple levels of nested
> expressions, eg
>
> foo(bar(x?)) + y?
>
> Slava
>

I'm not sure we need to optimize much for complicated nested examples, as I
don't think this is something that will happen a lot in practice. I imagine
the most common scenario will be a single call with one or more arguments.

Having said that, we did receive 2 different reasonable answers on what the
evaluation order would be for:
f(a(), b?)

(1) It desugars to:

if let someB = b {
f(a(), someB)
}

So a() doesn't get called if b is nil.

(2) "If you were to write this logic out by hand then you would
short-circuit it and this is analogous to current chaining behaviour so to
me evaluating left to right (as Swift usually does) and stopping at the
first failed unwrap would make sense"

So a() gets called if b is nil.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Félix Cloutier via swift-evolution
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 
>  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
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Slava Pestov via swift-evolution


> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution 
>  wrote:
> 
> I missed the previous threads! I’ve found one of the relevant threads here:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>  
> 
> 
> Thanks for this important point.
> 
> If you were to write this logic out by hand then you would short-circuit it 
> and this is analogous to current chaining behaviour so to me evaluating left 
> to right (as Swift usually does) and stopping at the first failed unwrap 
> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t think 
> it’s really less intuitive than the current chaining behaviour. 

I think it gets confusing when you have multiple levels of nested expressions, 
eg

foo(bar(x?)) + y?

Slava

> 
> Jared
> 
>> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> This topic has been discussed at least two and maybe more times in the 
>> past.. It’s hard for me to post links at the moment, but it should be 
>> possible to find on Google.
>> 
>> One major challenge to this idea, for which no satisfactory answer has been 
>> achieved after all these years, is the following issue:
>> 
>> f(g()?, h()?, i(), j()?)?
>> 
>> If g() evaluates to nil, is h() called or not? How about i(), which is not 
>> failable? Since any function or property access can have side effects, in 
>> what order are the arguments evaluated, and how does one reason about this 
>> code flow?
>> 
>> To my mind, in the absence of an intuitive answer to the above—which does 
>> not appear to be possible—this idea is not feasible.
>> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
>> > wrote:
>> 
>> > 12 Dec. 2017 02:58 Jared Khan > 
>> > wrote:
>> >
>> > 2. It felt natural to me. It’s analogous to the existing optional chaining 
>> > scenarios and composes nicely. I think it’s about as understandable as 
>> > existing chaining, a newbie would have to look it up to discover its 
>> > meaning. What are your thoughts on this particular syntax (ignoring 3. 
>> > momentarily)? Hopefully others in this thread can share their views too.
>> 
>> Chaining methods is linear, while nesting fills a similar purpose when we 
>> use function calls. This of course affects the way existing Swift code is 
>> written, but that is something we have to live with if we want to use 
>> familiar syntax patterns. However, I think we have to consider this 
>> difference in this case, since the syntax becomes more convoluted. Your 
>> suggestion is definitely not as easy to read as the optional chaining 
>> syntax, and maybe it can't be.
>> 
>> > As for how common I’d expect it to be, it’s something I’ve run into myself 
>> > a few times. Again, I hope members of this list can give their view on if 
>> > this would be useful to them.
>> 
>> I don't have any real examples, but I certainly think that I have run into 
>> it, so I'm quite open to solving the problem. For me, it is probably only a 
>> matter of finding a syntax that is acceptable.
>> 
>> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ 
>> > has never been available as a postfix operator. Perhaps I’m missing your 
>> > point, could you demonstrate where it is allowed?
>> 
>> I did not expect that you would be able to answer that, it was more a 
>> question directed to people who are more connected to the inner workings of 
>> the parsing of Swift than I am. It is not allowed, but the error message is 
>> not the one I expect, something that gives me a hint that it does have some 
>> meaning early in the parsing.
>> 
>> /Magnus
>> 
>> ___
>> 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

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Jared Khan via swift-evolution
I missed the previous threads! I’ve found one of the relevant threads here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
 


Thanks for this important point.

If you were to write this logic out by hand then you would short-circuit it and 
this is analogous to current chaining behaviour so to me evaluating left to 
right (as Swift usually does) and stopping at the first failed unwrap would 
make sense. I wouldn’t necessarily say it’s intuitive but I don’t think it’s 
really less intuitive than the current chaining behaviour. 

Jared

> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This topic has been discussed at least two and maybe more times in the past.. 
> It’s hard for me to post links at the moment, but it should be possible to 
> find on Google.
> 
> One major challenge to this idea, for which no satisfactory answer has been 
> achieved after all these years, is the following issue:
> 
> f(g()?, h()?, i(), j()?)?
> 
> If g() evaluates to nil, is h() called or not? How about i(), which is not 
> failable? Since any function or property access can have side effects, in 
> what order are the arguments evaluated, and how does one reason about this 
> code flow?
> 
> To my mind, in the absence of an intuitive answer to the above—which does not 
> appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
> > wrote:
> 
> > 12 Dec. 2017 02:58 Jared Khan > 
> > wrote:
> >
> > 2. It felt natural to me. It’s analogous to the existing optional chaining 
> > scenarios and composes nicely. I think it’s about as understandable as 
> > existing chaining, a newbie would have to look it up to discover its 
> > meaning. What are your thoughts on this particular syntax (ignoring 3. 
> > momentarily)? Hopefully others in this thread can share their views too.
> 
> Chaining methods is linear, while nesting fills a similar purpose when we use 
> function calls. This of course affects the way existing Swift code is 
> written, but that is something we have to live with if we want to use 
> familiar syntax patterns. However, I think we have to consider this 
> difference in this case, since the syntax becomes more convoluted. Your 
> suggestion is definitely not as easy to read as the optional chaining syntax, 
> and maybe it can't be.
> 
> > As for how common I’d expect it to be, it’s something I’ve run into myself 
> > a few times. Again, I hope members of this list can give their view on if 
> > this would be useful to them.
> 
> I don't have any real examples, but I certainly think that I have run into 
> it, so I'm quite open to solving the problem. For me, it is probably only a 
> matter of finding a syntax that is acceptable.
> 
> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ 
> > has never been available as a postfix operator. Perhaps I’m missing your 
> > point, could you demonstrate where it is allowed?
> 
> I did not expect that you would be able to answer that, it was more a 
> question directed to people who are more connected to the inner workings of 
> the parsing of Swift than I am. It is not allowed, but the error message is 
> not the one I expect, something that gives me a hint that it does have some 
> meaning early in the parsing.
> 
> /Magnus
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Jared Khan via swift-evolution
I missed the previous threads! I’ve found one of the relevant threads here:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
 


Thanks for this important point.

If you were to write this logic out by hand then you would short-circuit it and 
this is analogous to current chaining behaviour so to me evaluating left to 
right (as Swift usually does) and stopping at the first failed unwrap would 
make sense. I wouldn’t necessarily say it’s intuitive but I don’t think it’s 
really less intuitive than the current chaining behaviour. 

Jared

> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This topic has been discussed at least two and maybe more times in the past.. 
> It’s hard for me to post links at the moment, but it should be possible to 
> find on Google.
> 
> One major challenge to this idea, for which no satisfactory answer has been 
> achieved after all these years, is the following issue:
> 
> f(g()?, h()?, i(), j()?)?
> 
> If g() evaluates to nil, is h() called or not? How about i(), which is not 
> failable? Since any function or property access can have side effects, in 
> what order are the arguments evaluated, and how does one reason about this 
> code flow?
> 
> To my mind, in the absence of an intuitive answer to the above—which does not 
> appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
> > wrote:
> 
> > 12 Dec. 2017 02:58 Jared Khan > 
> > wrote:
> >
> > 2. It felt natural to me. It’s analogous to the existing optional chaining 
> > scenarios and composes nicely. I think it’s about as understandable as 
> > existing chaining, a newbie would have to look it up to discover its 
> > meaning. What are your thoughts on this particular syntax (ignoring 3. 
> > momentarily)? Hopefully others in this thread can share their views too.
> 
> Chaining methods is linear, while nesting fills a similar purpose when we use 
> function calls. This of course affects the way existing Swift code is 
> written, but that is something we have to live with if we want to use 
> familiar syntax patterns. However, I think we have to consider this 
> difference in this case, since the syntax becomes more convoluted. Your 
> suggestion is definitely not as easy to read as the optional chaining syntax, 
> and maybe it can't be.
> 
> > As for how common I’d expect it to be, it’s something I’ve run into myself 
> > a few times. Again, I hope members of this list can give their view on if 
> > this would be useful to them.
> 
> I don't have any real examples, but I certainly think that I have run into 
> it, so I'm quite open to solving the problem. For me, it is probably only a 
> matter of finding a syntax that is acceptable.
> 
> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ 
> > has never been available as a postfix operator. Perhaps I’m missing your 
> > point, could you demonstrate where it is allowed?
> 
> I did not expect that you would be able to answer that, it was more a 
> question directed to people who are more connected to the inner workings of 
> the parsing of Swift than I am. It is not allowed, but the error message is 
> not the one I expect, something that gives me a hint that it does have some 
> meaning early in the parsing.
> 
> /Magnus
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Adrian Zubarev via swift-evolution
This is an interesting example but I think the solution might be simple if we 
try to desugar it.

// example
f(g()?, h()?, i(), j()?)?

// desugared
let/var someF: SomeType?
if let someG = g(),  let someH = h(), let someJ = j() {
someF = f(someG, someH, i(), someJ)
} else {
someF = nil
}
Final syntax aside, let’s use the optional function syntax from obj-c world 
here for a moment: f?(g(), h(), i(), j(), k()) where the function signature 
would look like func f(_: G, _: H, _: I, _: J, _: K?).

Only if the parameter type is non-optional and the argument is optional then we 
can desugar it like this:

let/var someF: SomeType?
if let someG = g(),  let someH = h(), let someJ = j() {
someF = f(someG, someH, i(), someJ, k())
} else {
someF = nil
}
No need to unwrap the result from k() here.




Am 11. Dezember 2017 um 20:28:52, Xiaodi Wu via swift-evolution 
(swift-evolution@swift.org) schrieb:

This topic has been discussed at least two and maybe more times in the past. 
It’s hard for me to post links at the moment, but it should be possible to find 
on Google.

One major challenge to this idea, for which no satisfactory answer has been 
achieved after all these years, is the following issue:

f(g()?, h()?, i(), j()?)?

If g() evaluates to nil, is h() called or not? How about i(), which is not 
failable? Since any function or property access can have side effects, in what 
order are the arguments evaluated, and how does one reason about this code flow?

To my mind, in the absence of an intuitive answer to the above—which does not 
appear to be possible—this idea is not feasible.
On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
 wrote:

> 12 Dec. 2017 02:58 Jared Khan  wrote:
>
> 2. It felt natural to me. It’s analogous to the existing optional chaining 
> scenarios and composes nicely. I think it’s about as understandable as 
> existing chaining, a newbie would have to look it up to discover its meaning. 
> What are your thoughts on this particular syntax (ignoring 3. momentarily)? 
> Hopefully others in this thread can share their views too.

Chaining methods is linear, while nesting fills a similar purpose when we use 
function calls. This of course affects the way existing Swift code is written, 
but that is something we have to live with if we want to use familiar syntax 
patterns. However, I think we have to consider this difference in this case, 
since the syntax becomes more convoluted. Your suggestion is definitely not as 
easy to read as the optional chaining syntax, and maybe it can't be.

> As for how common I’d expect it to be, it’s something I’ve run into myself a 
> few times. Again, I hope members of this list can give their view on if this 
> would be useful to them.

I don't have any real examples, but I certainly think that I have run into it, 
so I'm quite open to solving the problem. For me, it is probably only a matter 
of finding a syntax that is acceptable.

> 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ has 
> never been available as a postfix operator. Perhaps I’m missing your point, 
> could you demonstrate where it is allowed?

I did not expect that you would be able to answer that, it was more a question 
directed to people who are more connected to the inner workings of the parsing 
of Swift than I am. It is not allowed, but the error message is not the one I 
expect, something that gives me a hint that it does have some meaning early in 
the parsing.

/Magnus

___
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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Xiaodi Wu via swift-evolution
This topic has been discussed at least two and maybe more times in the
past. It’s hard for me to post links at the moment, but it should be
possible to find on Google.

One major challenge to this idea, for which no satisfactory answer has been
achieved after all these years, is the following issue:

f(g()?, h()?, i(), j()?)?

If g() evaluates to nil, is h() called or not? How about i(), which is not
failable? Since any function or property access can have side effects, in
what order are the arguments evaluated, and how does one reason about this
code flow?

To my mind, in the absence of an intuitive answer to the above—which does
not appear to be possible—this idea is not feasible.
On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution <
swift-evolution@swift.org> wrote:

>
> > 12 Dec. 2017 02:58 Jared Khan  wrote:
> >
> > 2. It felt natural to me. It’s analogous to the existing optional
> chaining scenarios and composes nicely. I think it’s about as
> understandable as existing chaining, a newbie would have to look it up to
> discover its meaning. What are your thoughts on this particular syntax
> (ignoring 3. momentarily)? Hopefully others in this thread can share their
> views too.
>
> Chaining methods is linear, while nesting fills a similar purpose when we
> use function calls. This of course affects the way existing Swift code is
> written, but that is something we have to live with if we want to use
> familiar syntax patterns. However, I think we have to consider this
> difference in this case, since the syntax becomes more convoluted. Your
> suggestion is definitely not as easy to read as the optional chaining
> syntax, and maybe it can't be.
>
> > As for how common I’d expect it to be, it’s something I’ve run into
> myself a few times. Again, I hope members of this list can give their view
> on if this would be useful to them.
>
> I don't have any real examples, but I certainly think that I have run into
> it, so I'm quite open to solving the problem. For me, it is probably only a
> matter of finding a syntax that is acceptable.
>
> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
> has never been available as a postfix operator. Perhaps I’m missing your
> point, could you demonstrate where it is allowed?
>
> I did not expect that you would be able to answer that, it was more a
> question directed to people who are more connected to the inner workings of
> the parsing of Swift than I am. It is not allowed, but the error message is
> not the one I expect, something that gives me a hint that it does have some
> meaning early in the parsing.
>
> /Magnus
>
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Magnus Ahltorp via swift-evolution

> 12 Dec. 2017 02:58 Jared Khan  wrote:
> 
> 2. It felt natural to me. It’s analogous to the existing optional chaining 
> scenarios and composes nicely. I think it’s about as understandable as 
> existing chaining, a newbie would have to look it up to discover its meaning. 
> What are your thoughts on this particular syntax (ignoring 3. momentarily)? 
> Hopefully others in this thread can share their views too.

Chaining methods is linear, while nesting fills a similar purpose when we use 
function calls. This of course affects the way existing Swift code is written, 
but that is something we have to live with if we want to use familiar syntax 
patterns. However, I think we have to consider this difference in this case, 
since the syntax becomes more convoluted. Your suggestion is definitely not as 
easy to read as the optional chaining syntax, and maybe it can't be.

> As for how common I’d expect it to be, it’s something I’ve run into myself a 
> few times. Again, I hope members of this list can give their view on if this 
> would be useful to them.

I don't have any real examples, but I certainly think that I have run into it, 
so I'm quite open to solving the problem. For me, it is probably only a matter 
of finding a syntax that is acceptable.

> 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ has 
> never been available as a postfix operator. Perhaps I’m missing your point, 
> could you demonstrate where it is allowed?

I did not expect that you would be able to answer that, it was more a question 
directed to people who are more connected to the inner workings of the parsing 
of Swift than I am. It is not allowed, but the error message is not the one I 
expect, something that gives me a hint that it does have some meaning early in 
the parsing.  

/Magnus

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Matthew Johnson via swift-evolution
It’s worth mentioning that the problem this thread is discussing can be 
generalized to idioms / applicative.  The specific case here is for Optional 
but many other types could benefit from an elegant syntactic solution to this 
problem.  It might be worth exploring a more general solution.  Here’s a link 
to how this is handled in Idris: 
http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#idiom-brackets 
.

Matthew

> On Dec 11, 2017, at 12:01 PM, Jared Khan via swift-evolution 
>  wrote:
> 
> 1. Correct
> 
> 2. It felt natural to me. It’s analogous to the existing optional chaining 
> scenarios and composes nicely. I think it’s about as understandable as 
> existing chaining, a newbie would have to look it up to discover its meaning. 
> What are your thoughts on this particular syntax (ignoring 3. momentarily)? 
> Hopefully others in this thread can share their views too.
> As for how common I’d expect it to be, it’s something I’ve run into myself a 
> few times. Again, I hope members of this list can give their view on if this 
> would be useful to them.
> 
> 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ has 
> never been available as a postfix operator. Perhaps I’m missing your point, 
> could you demonstrate where it is allowed?
> 
> Best,
> Jared
> 
>> On 11 Dec 2017, at 17:07, Magnus Ahltorp  wrote:
>> 
>> 
>>> 12 Dec. 2017 01:30 Jared Khan via swift-evolution 
>>>  wrote:
>>> 
>>> 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.
>> 
>> 1. Am I right in assuming that you propose that the suffix operator "?" 
>> would make the result of the surrounding method/function call optional, so 
>> that a(b(c?)) would make the result of the "b" function call optional, but 
>> not the "a" function call, and that it would be a(b(c?)?) if we would like 
>> to propagate this two levels?
>> 
>> 2. If that is the case, is that understandable/neat enough? How common would 
>> you expect this to be?
>> 
>> 3. For some reason, (in current Swift) the suffix operator "?" seems to be 
>> allowed in intra-expression syntax, and only fails when the inter-expression 
>> syntax is checked for optionality congruence. Is there a reason for this? I 
>> would have expected that the congruence error "cannot use optional chaining 
>> on non-optional value of type" would never be seen for a lone "?", since the 
>> error message "'?' must be followed by a call, member lookup, or subscript" 
>> would always be displayed first if it was checked first. The "." operator 
>> checks intra-expression syntax first, before checking congruence. Is this a 
>> sign that "?" as a suffix operator is already somewhat operational as an 
>> operator for optional types? I have a faint recollection that it was doing 
>> something in earlier versions of Swift.
>> 
>> /Magnus
>> 
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Jared Khan via swift-evolution
1. Correct

2. It felt natural to me. It’s analogous to the existing optional chaining 
scenarios and composes nicely. I think it’s about as understandable as existing 
chaining, a newbie would have to look it up to discover its meaning. What are 
your thoughts on this particular syntax (ignoring 3. momentarily)? Hopefully 
others in this thread can share their views too.
As for how common I’d expect it to be, it’s something I’ve run into myself a 
few times. Again, I hope members of this list can give their view on if this 
would be useful to them.

3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ has 
never been available as a postfix operator. Perhaps I’m missing your point, 
could you demonstrate where it is allowed?

Best,
Jared

> On 11 Dec 2017, at 17:07, Magnus Ahltorp  wrote:
> 
> 
>> 12 Dec. 2017 01:30 Jared Khan via swift-evolution 
>>  wrote:
>> 
>> 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.
> 
> 1. Am I right in assuming that you propose that the suffix operator "?" would 
> make the result of the surrounding method/function call optional, so that 
> a(b(c?)) would make the result of the "b" function call optional, but not the 
> "a" function call, and that it would be a(b(c?)?) if we would like to 
> propagate this two levels?
> 
> 2. If that is the case, is that understandable/neat enough? How common would 
> you expect this to be?
> 
> 3. For some reason, (in current Swift) the suffix operator "?" seems to be 
> allowed in intra-expression syntax, and only fails when the inter-expression 
> syntax is checked for optionality congruence. Is there a reason for this? I 
> would have expected that the congruence error "cannot use optional chaining 
> on non-optional value of type" would never be seen for a lone "?", since the 
> error message "'?' must be followed by a call, member lookup, or subscript" 
> would always be displayed first if it was checked first. The "." operator 
> checks intra-expression syntax first, before checking congruence. Is this a 
> sign that "?" as a suffix operator is already somewhat operational as an 
> operator for optional types? I have a faint recollection that it was doing 
> something in earlier versions of Swift.
> 
> /Magnus
> 

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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Charles Augustine via swift-evolution
I don’t think that solves the same thing.  The problem is I read it is to allow 
some sort of short hand to be able to pass optional types as parameters into 
methods / initializers that do not take optional types.  The result of that 
method / initializer being nil if any of said parameters were nil or a typical 
result otherwise.  Based on your example I think it’s identical to the existing 
?? operator, is it not?

As per the suggested syntax, I do think that we would want to be able to 
control this feature on a per parameter basis, so it would make sense to have 
the ? operator placed after the parameter that needed to be unwrapped.  This 
would also be more consistent with the usage of the existing syntax.

— Charles

> On Dec 11, 2017, at 9:37 AM, C. Keith Ray via swift-evolution 
>  wrote:
> 
> You can create a binary operator that tests the left-hand operand for nil, 
> and passes the unwrapped value to the right-hand operand (a function taking 
> one value), this operator can be made left-associative to allow chaining.
> 
> let m = String(contentsOfFile: "README.md") ??? Markdown 
> where ??? is the operator described above.
> 
> --
> C. Keith Ray
> 
> * https://leanpub.com/wepntk  <- buy my book?
> * http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf 
> 
> * http://agilesolutionspace.blogspot.com/ 
> 
> 
> On Dec 11, 2017, at 9:07 AM, Magnus Ahltorp via swift-evolution 
> > wrote:
> 
>> 
>>> 12 Dec. 2017 01:30 Jared Khan via swift-evolution 
>>> > wrote:
>>> 
>>> 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.
>> 
>> 1. Am I right in assuming that you propose that the suffix operator "?" 
>> would make the result of the surrounding method/function call optional, so 
>> that a(b(c?)) would make the result of the "b" function call optional, but 
>> not the "a" function call, and that it would be a(b(c?)?) if we would like 
>> to propagate this two levels?
>> 
>> 2. If that is the case, is that understandable/neat enough? How common would 
>> you expect this to be?
>> 
>> 3. For some reason, (in current Swift) the suffix operator "?" seems to be 
>> allowed in intra-expression syntax, and only fails when the inter-expression 
>> syntax is checked for optionality congruence. Is there a reason for this? I 
>> would have expected that the congruence error "cannot use optional chaining 
>> on non-optional value of type" would never be seen for a lone "?", since the 
>> error message "'?' must be followed by a call, member lookup, or subscript" 
>> would always be displayed first if it was checked first. The "." operator 
>> checks intra-expression syntax first, before checking congruence. Is this a 
>> sign that "?" as a suffix operator is already somewhat operational as an 
>> operator for optional types? I have a faint recollection that it was doing 
>> something in earlier versions of Swift.
>> 
>> /Magnus
>> 
>> ___
>> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread C. Keith Ray via swift-evolution
You can create a binary operator that tests the left-hand operand for nil, and 
passes the unwrapped value to the right-hand operand (a function taking one 
value), this operator can be made left-associative to allow chaining.

let m = String(contentsOfFile: "README.md") ??? Markdown 
where ??? is the operator described above.

--
C. Keith Ray

* https://leanpub.com/wepntk <- buy my book?
* http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf
* http://agilesolutionspace.blogspot.com/

> On Dec 11, 2017, at 9:07 AM, Magnus Ahltorp via swift-evolution 
>  wrote:
> 
> 
>> 12 Dec. 2017 01:30 Jared Khan via swift-evolution 
>>  wrote:
>> 
>> 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.
> 
> 1. Am I right in assuming that you propose that the suffix operator "?" would 
> make the result of the surrounding method/function call optional, so that 
> a(b(c?)) would make the result of the "b" function call optional, but not the 
> "a" function call, and that it would be a(b(c?)?) if we would like to 
> propagate this two levels?
> 
> 2. If that is the case, is that understandable/neat enough? How common would 
> you expect this to be?
> 
> 3. For some reason, (in current Swift) the suffix operator "?" seems to be 
> allowed in intra-expression syntax, and only fails when the inter-expression 
> syntax is checked for optionality congruence. Is there a reason for this? I 
> would have expected that the congruence error "cannot use optional chaining 
> on non-optional value of type" would never be seen for a lone "?", since the 
> error message "'?' must be followed by a call, member lookup, or subscript" 
> would always be displayed first if it was checked first. The "." operator 
> checks intra-expression syntax first, before checking congruence. Is this a 
> sign that "?" as a suffix operator is already somewhat operational as an 
> operator for optional types? I have a faint recollection that it was doing 
> something in earlier versions of Swift.
> 
> /Magnus
> 
> ___
> 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


Re: [swift-evolution] Optional Argument Chaining

2017-12-11 Thread Magnus Ahltorp via swift-evolution

> 12 Dec. 2017 01:30 Jared Khan via swift-evolution  
> wrote:
> 
> 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.

1. Am I right in assuming that you propose that the suffix operator "?" would 
make the result of the surrounding method/function call optional, so that 
a(b(c?)) would make the result of the "b" function call optional, but not the 
"a" function call, and that it would be a(b(c?)?) if we would like to propagate 
this two levels?

2. If that is the case, is that understandable/neat enough? How common would 
you expect this to be?

3. For some reason, (in current Swift) the suffix operator "?" seems to be 
allowed in intra-expression syntax, and only fails when the inter-expression 
syntax is checked for optionality congruence. Is there a reason for this? I 
would have expected that the congruence error "cannot use optional chaining on 
non-optional value of type" would never be seen for a lone "?", since the error 
message "'?' must be followed by a call, member lookup, or subscript" would 
always be displayed first if it was checked first. The "." operator checks 
intra-expression syntax first, before checking congruence. Is this a sign that 
"?" as a suffix operator is already somewhat operational as an operator for 
optional types? I have a faint recollection that it was doing something in 
earlier versions of Swift.

/Magnus

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


[swift-evolution] Optional Argument Chaining

2017-12-11 Thread Jared Khan via swift-evolution
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
https://lists.swift.org/mailman/listinfo/swift-evolution