<html><head><style>
body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        padding:1em;
        margin:auto;
        background:#fefefe;
}
h1, h2, h3, h4, h5, h6 {
        font-weight: bold;
}
h1 {
        color: #000000;
        font-size: 28pt;
}
h2 {
        border-bottom: 1px solid #CCCCCC;
        color: #000000;
        font-size: 24px;
}
h3 {
        font-size: 18px;
}
h4 {
        font-size: 16px;
}
h5 {
        font-size: 14px;
}
h6 {
        color: #777777;
        background-color: inherit;
        font-size: 14px;
}
hr {
        height: 0.2em;
        border: 0;
        color: #CCCCCC;
        background-color: #CCCCCC;
display: inherit;
}
p, blockquote, ul, ol, dl, li, table, pre {
        margin: 15px 0;
}
a, a:visited {
        color: #4183C4;
        background-color: inherit;
        text-decoration: none;
}
#message {
        border-radius: 6px;
        border: 1px solid #ccc;
        display:block;
        width:100%;
        height:60px;
        margin:6px 0px;
}
button, #ws {
        font-size: 12 pt;
        padding: 4px 6px;
        border-radius: 5px;
        border: 1px solid #bbb;
        background-color: #eee;
}
code, pre, #ws, #message {
        font-family: Monaco;
        font-size: 10pt;
        border-radius: 3px;
        background-color: #F8F8F8;
        color: inherit;
}
code {
        border: 1px solid #EAEAEA;
        margin: 0 2px;
        padding: 0 5px;
}
pre {
        border: 1px solid #CCCCCC;
        overflow: auto;
        padding: 4px 8px;
}
pre > code {
        border: 0;
        margin: 0;
        padding: 0;
}
#ws { background-color: #f8f8f8; }
.bloop_markdown table {
border-collapse: collapse;
font-family: Helvetica, arial, freesans, clean, sans-serif;
color: rgb(51, 51, 51);
font-size: 15px; line-height: 25px;
padding: 0; }
.bloop_markdown table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
.bloop_markdown table tr:nth-child(2n) {
background-color: #f8f8f8; }
.bloop_markdown table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.bloop_markdown table tr th :first-child, table tr td :first-child {
margin-top: 0; }
.bloop_markdown table tr th :last-child, table tr td :last-child {
margin-bottom: 0; }
.bloop_markdown blockquote{
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
blockquote > :first-child {
margin-top: 0; }
blockquote > :last-child {
margin-bottom: 0; }
code, pre, #ws, #message {
word-break: normal;
word-wrap: normal;
}
hr {
display: inherit;
}
.bloop_markdown :first-child {
-webkit-margin-before: 0;
}
code, pre, #ws, #message {
font-family: Menlo, Consolas, Liberation Mono, Courier, monospace;
}
.send { color:#77bb77; }
.server { color:#7799bb; }
.error { color:#AA0000; }</style></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="bloop_markdown"><p>That’s actually the cool part of merging <code>optional func</code> infix <code>?</code> with the discussed problem. If you think how we could represent <code>optional func</code> in pure swift only with some sugar (and also the ability to write <code>var function(label:label:)</code> which we’ll get at some point) then we could do this:</p>
<pre><code class="swift">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)
</code></pre>
<p><code>default</code> is from https://github.com/erica/swift-evolution/blob/a260a33ca39676b41e0436c4dccdb78441308c13/proposals/XXXX-role-keywords.md</p>
<p>Now back to your example, the answer becomes really easy:</p>
<p><code>let c = someFunction?(a, b)</code></p>
<p>This can then be desugared to:</p>
<pre><code class="swift">let c = {
if let someFunction = someFunction, let someA = a, let someB = b {
return someFunction(someA, someB)
} else {
return nil
}
}
</code></pre>
<p>In any case <code>c</code> would be <code>Optional<Int></code>.</p>
<p></p></div><div class="bloop_original_html"><style>body{font-family:Helvetica,Arial;font-size:13px}</style><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px; color: rgba(0,0,0,1.0); margin: 0px; line-height: auto;"><br></div> <br> <div id="bloop_sign_1513108066217218816" class="bloop_sign"></div> <br><p class="airmail_on">Am 12. Dezember 2017 um 20:42:20, Benjamin Spratling (<a href="mailto:bspratling@mac.com">bspratling@mac.com</a>) schrieb:</p> <blockquote type="cite" class="clean_bq"><span><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div></div><div>
<title></title>
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?
<div class=""><br class=""></div>
<div class="">i.e. </div>
<div class=""><br class=""></div>
<div class="">let a:Int? = ...</div>
<div class="">let b:Int? = ...</div>
<div class="">let someFunction:((Int, Int)->(Int))? = ...</div>
<div class="">let c = someFunction??(a, b)</div>
<div class=""><br class=""></div>
<div class="">It seems like it’s trying to provide a fallback of
(Int?, Int?) instead of Int?.</div>
<div class="">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.</div>
<div class=""><br class=""></div>
<div class="">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.</div>
<div class=""><br class="">
<div class=""><br class="">
<div>
<blockquote type="cite" class="">
<div class="">On Dec 12, 2017, at 2:32 PM, Adrian Zubarev via
swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);">
<p style="margin: 15px 0px; -webkit-margin-before: 0px;" class="">I
propose that we do not add a suffix<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">?</code><span class="Apple-converted-space"> </span>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<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">?</code><span class="Apple-converted-space"> </span>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<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">?</code><span class="Apple-converted-space"> </span>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<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">?</code>, 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<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">?</code><span class="Apple-converted-space"> </span>is always close to the
parameter list<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">?(_:_:...)</code>.</p>
<p style="margin: 15px 0px;" class="">Here are some simple examples
to consider:<span class="Apple-converted-space"> </span></p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">func first(one: A, two: B, three: C?) -> D { ... }
func second(one: A, two: B, three: C?) -> D? { ... }
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// no need for infix `?`
first(one: a, two: b, three: optionalC) // returns `D`
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
}
}()
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
}
}()
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// no need for infix `?`
second(one: a, two: b, three: optionalC) // returns `D?`
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
}
}()
</code></pre>
<p style="margin: 15px 0px;" class="">
————————————————————————————————————————————————</p>
<pre style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;" class=""><code class="swift" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;">// 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
}
}()
</code></pre>
<p style="margin: 15px 0px;" class="">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.</p>
<p style="margin: 15px 0px;" class="">If I missed something
where<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal; -webkit-margin-before: 0px;" class="">optional func</code><span class="Apple-converted-space"> </span>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<span class="Apple-converted-space"> </span><code style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;" class="">optional func</code>.</p>
<div style="margin: 15px 0px;" class=""><br class="webkit-block-placeholder"></div>
</div>
<div class="bloop_original_html" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);">
<div id="bloop_customfont" style="font-family: Helvetica, Arial; font-size: 13px; margin: 0px;" class=""><br class=""></div>
<br class="">
<div id="bloop_sign_1513106396093748992" class="bloop_sign"></div>
<br class="">
<p class="airmail_on" style="margin: 15px 0px;">Am 12. Dezember
2017 um 19:47:25, Jared Khan via swift-evolution (<a href="mailto:swift-evolution@swift.org" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;" class="">swift-evolution@swift.org</a>) schrieb:</p>
<blockquote type="cite" class="clean_bq" style="margin: 15px 0px;">
<div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;">
<div class=""></div>
<div class="">
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">Even this small example I think this is still a little
fiddly. If we add another required parameter to the Markdown
initializer:</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">let readme = String(contentsOfFile: “README.md”).flatMap {
Markdown(string: $0, flavor: .github) }</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">this starts to feel a little inside-out and crufty to
me. <br class=""></span>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span>
<blockquote type="cite" class="" style="margin: 15px 0px;">
<div class="" style="margin-top: 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">On 12 Dec 2017, at
05:54, Félix Cloutier <<a href="mailto:felixcloutier@icloud.com" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">felixcloutier@icloud.com</a>>
wrote:</span></div>
<span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class="Apple-interchange-newline"></span>
<div class="" style="margin-bottom: 0px;">
<div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">You talk about
flatMap without giving an example. The readme isn't that bad with
it, IMO:<br class=""></span>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
<div class="">
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">if let readme = String(contentsOfFile:
"README.md").flatMap(Markdown) {</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">// use contents here</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">}</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">That doesn't work when you need multiple optional
parameters. In my own experience, that hasn't been a huge problem,
though.</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">Félix</span></div>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span>
<blockquote type="cite" class="" style="margin: 15px 0px;">
<div class="" style="margin-top: 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">Le 11 déc. 2017 à
08:30, Jared Khan via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">swift-evolution@swift.org</a>>
a écrit :</span></div>
<span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class="Apple-interchange-newline"></span>
<div class="" style="margin-bottom: 0px;">
<div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space;">
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">Hi all,</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">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.</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">The example below
is taken from a project I'm working on at the moment:</span></p>
<pre class="" style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></pre>
<blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;">
<pre class="" style="margin: 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">// Current
let readme: Markdown?
if let rawMarkdown = String(contentsOfFile: "README.md") {
readme = Markdown(string: rawMarkdown)
} else {
readme = nil
}</code></span></pre></blockquote>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">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</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">I propose the
following syntax for an alternative:</span></p>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
<blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;">
<pre class="" style="margin: 0px 0px 15px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">// Proposed alternative
let readme = Markdown(string: String(contentsOfFile: "README.md")?)</code></span></pre>
<pre class="" style="margin: 15px 0px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;"><br class=""></code></span></pre></blockquote>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">The <code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;">?</code> is
familiar in its use for optional chaining.</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">This would act like
syntactic sugar for the <code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;">flatMap</code> method
on <code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(234, 234, 234); margin: 0px 2px; padding: 0px 5px; word-break: normal; word-wrap: normal;">Optional</code>.
For example:</span></p>
<div class=""><span style="margin-top: 0px; margin-bottom: 0px;" class="">(where `john` is of a `Person` type with a property
`address: Address?`)</span></div>
<blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;">
<pre class="" style="margin: 0px 0px 15px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">// func getZipCode(fromAddress address: Address) -> ZipCode</code></span></pre>
<pre class="" style="margin: 15px 0px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">getZipCode(fromAddress: john.address?)
// Would be equivalent to…
john.address.flatMap {
getZipCode($0)
}</code></span></pre></blockquote>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">An example with
multiple parameters:</span></p>
<blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;">
<pre class="" style="margin: 0px 0px 15px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">// func getPostageEstimate(source: Address, destination: Address, weight: Double) -> Int</code></span></pre>
<pre class="" style="margin: 15px 0px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">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)
}()</code></span></pre></blockquote>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">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:</span></p>
<blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;">
<pre class="" style="margin: 0px 0px 15px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">
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</code></span></pre>
<pre class="" style="margin: 15px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;">let result = myFunc(nil?)
// warning: optional argument chaining with nil literal always results in nil</code></span></pre>
<pre class="" style="margin: 15px 0px 0px; font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 1px solid rgb(204, 204, 204); overflow: auto; padding: 4px 8px; word-break: normal; word-wrap: normal;"><span style="margin-top: 0px; margin-bottom: 0px;" class=""><code class="" style="font-family: Menlo, Consolas, 'Liberation Mono', Courier, monospace; font-size: 10pt; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-color: rgb(248, 248, 248); color: inherit; border: 0px; margin: 0px; padding: 0px; word-break: normal; word-wrap: normal;"><br class=""></code></span></pre></blockquote>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">Seeking your
thoughts on this idea, the specific syntax, and more use case
examples.</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">Best,</span></p>
<p class="" style="margin: 15px 0px;"><span style="margin-top: 0px; margin-bottom: 0px;" class="">Jared</span></p>
</div>
<span style="margin-top: 0px; margin-bottom: 0px;" class="">_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">
swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;">
https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</span></div>
</blockquote>
</div>
<span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
</div>
</div>
</blockquote>
</div>
<span style="margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></span></div>
<span style="margin-top: 0px; margin-bottom: 0px;" class="">_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="color: rgb(65, 131, 196); background-color: inherit; text-decoration: none;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</span></div>
</div>
</blockquote>
</div>
<div class="bloop_markdown" style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);">
<div style="margin: 15px 0px; -webkit-margin-before: 0px;" class=""><br class="webkit-block-placeholder"></div>
</div>
<span style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254); float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);" class="">
<span style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254); float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);" class="">
<a href="mailto:swift-evolution@swift.org" style="color: rgb(65, 131, 196); background-color: rgb(254, 254, 254); text-decoration: none; font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);" class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="color: rgb(65, 131, 196); background-color: rgb(254, 254, 254); text-decoration: none; font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br style="font-family: Helvetica, Arial; font-size: 13px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(254, 254, 254);" class=""></div>
</blockquote>
</div>
<br class=""></div>
</div>
</div></div></span></blockquote></div><div class="bloop_markdown"><p></p></div></body></html>