<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 20, 2016, at 11:52 AM, Erica Sadun 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=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Questions being raised in this discussion:</div><div class=""><br class=""></div><div class="">* Are the current stdlib names for optional <font face="Courier" class="">map</font> and <font face="Courier" class="">flatMap</font> misleading? </div></div></div></blockquote><div><br class=""></div><div>Misleading makes it a harder question to answer. I can answer with my opinion though.</div><div><br class=""></div><div>functional methods make sense on several ‘functional things’</div><div>1. An abstract generator of values, returning other generators of values which can be collected/reduced/folded into concrete results</div><div>2. A collection, returning concrete types to optimize the implementation as well as to eliminate the explicit the collection step (FWIW, I think map, etc should be moved off Sequence and onto Collection)</div><div>3. An unordered data set, returning unordered data sets, for processing in a parallel manner.</div><div>4. On optionals, where you are dealing with zero or one values</div><div><br class=""></div><div>( Aside: To be clear, the above does represent two changes from the current state of things in Swift 3:</div><div>- I think LazySequence should be replaced by functional operations on generators</div><div>- I think the functional operations on Sequence should be moved to Collection if the goal is to have optimal/shortcut implementations )</div><div><br class=""></div><div>You might be able to represent these all on a protocol hierarchy at some point in the future (if we get existential protocols in generics). </div><div><br class=""></div><div>In the meantime, there will certainly be duplication. This doesn’t meant that one location is proper and the others are not.</div><div><br class=""></div><div>IMHO the goal is functional composition, so the kind of container (single v multiple elements, lazy or immediate, sequenced or unsequenced data, parallel or not) does not determine whether map/flatMap are present</div><div><br class=""></div></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">* Are the current stdlib functions for optional closure application appropriate and sufficient?</div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class=""><div class=""><font face="Courier" class=""> @warn_unused_result</font></div><div class=""><font face="Courier" class=""> public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?</font></div></div></div></div></blockquote><div><br class=""></div><div>Sure, you are calling a function to transform the value(s) in a container or sequence, and returning the appropriate container/sequence in the new type. You *could* call this something like bind to match Haskell, but really that would just be a synonym. </div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><font face="Courier" class=""> @warn_unused_result</font></div><div class=""><font face="Courier" class=""> public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?</font></div></div></div></div></blockquote><div><br class=""></div><div>Sure, you are calling a function to transform the value(s) in a container or sequence and returning a new container/sequence of some type of element, flattening that down, and returning the appropriate container/sequence in the new type.</div><div><br class=""></div><div>One could say the lack of common types means that flatMap is too simplistic, and needs to support functions which return other types of containers, e.g.:</div><div><br class=""> @warn_unused_result<br class=""> public func flatMap<E,S:SequenceType where S.Generator.Element == E>(@noescape f: (Wrapped) throws -> S) rethrows -> [E]<br class=""><br class=""></div><div>which would return an empty array in the case of optional .none. </div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">Assume there could be up to three stdlib functions just for applying closures to .some-case </div><div class="">optionals. Would they look like this?</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">public func f1<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?</font></div><div class=""><div class=""><font face="Courier" class="">public func f2<U>(@noescape f: (Wrapped) throws -> U!) rethrows -> U!</font></div></div><div class=""><div class=""><font face="Courier" class="">public func f3<U>(@noescape f: (Wrapped) throws -> U) rethrows -> Void</font></div></div><div class=""><br class=""></div><div class="">Right now f2/flatMap returns U?, not U or U!, and won't throw if nil, right? Should it</div><div class="">stay that way or change to something that throws and returns a guaranteed value?</div><div class="">Or maybe the current "f2" model (flatMap) be discarded and replaced by an </div><div class="">"<font face="Courier" class="">ifPresent</font>"-like Void call?</div></div></div></blockquote><div><br class=""></div><div>The discussion in parallel about abolishing the ImplicitlyUnwrappedOptional is about representing IUO closer to what it really is - compiler + language rules which provide default runtime behavior for optionals.</div><div><br class=""></div><div>So f2<U> is really</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public func f2<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?<br class=""><br class=""></div><div>AKA flatMap.</div><div><br class=""></div><div>flatMap semantics are:</div><div>- if value is .none, return .none</div><div>- if value is .some, call function f with the .some value</div><div> - if result of f is .none, return none</div><div> - if result of f is .some value, return .some value</div><div><br class=""></div><div>Even if you had IUO’s as a type, and had a variant that took a function that returned a IUO as a result, that would mean the function should behave closer to f1 aka map. </div><div><br class=""></div><div>There are three good reasons to have forEach even if you have map:</div><div><br class=""></div><div>- generators or lazy collections will not evaluate until they consume. forEach is a consuming function, map may not be.</div><div>- if you are using functional style, map indicates the function is not meant to have side effects. forEach *only* makes sense for operations which do have side effects</div><div>- map returns a value while forEach does not. The creation of that value may have non-zero cost</div><div><br class=""></div><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">And regardless of which functions are included, what would the appropriate </div><div class="">names for each function style be?</div></div></blockquote><div><br class=""></div><div>I’m in favor of using map, flatMap, flatten, filter, etc. unless someone can beat the existing terms of art.</div><div><br class=""></div><div>-DW</div></div><br class=""></body></html>