<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="">I want to write an extension on <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">SequenceType</span> that contains a set of methods named <span style="font-family: Menlo; font-size: 11px;" class="">findFirst()</span> that should return the first element that matches the given predicate.<div class=""><br class=""></div><div class="">For heterogeneous sequences where the caller is only interested in a specific subtype of elements, it is useful to have a variant of <span style="font-family: Menlo; font-size: 11px;" class="">findFirst()</span> that allows somehow specifying the type the caller is interested in so the predicate closure only gets called with that specific type.</div><div class=""><br class=""></div><div class="">That was probably not very easy to understand, but this example hopefully explains it clearly:</div><div class="">In an <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSView</span>’s <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">subviews</span> array (which are <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSView</span>s), find the first <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSButton</span> whose <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">state</span> is <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSOnState</span>. It would be neat if the predicate closure that checks the <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">state</span> property only gets passed <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSButton</span>s and no <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSView</span>s because that eliminates type checks in the closure.</div><div class=""><br class=""></div><div class="">I have two candidates for the implementation of this method and I’m looking for the more idiomatic one.</div><div class=""><br class=""></div><div class="">The examples work with a variable called <span style="color: rgb(79, 129, 135); font-family: Menlo; font-size: 11px;" class="">containerView</span>, which is of type <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSView</span>.</div><div class=""><br class=""></div><div class="">First try:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>SequenceType<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="color: rgb(187, 44, 162);" class=""> @warn_unused_result</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> findFirst<T>(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">_</span>: T.Type, <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> matching predicate: T <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Bool</span>) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span>? {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">for</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">case</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> element <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> predicate(element) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> element</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> result1 = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">containerView</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">subviews</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">findFirst</span>(<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSButton</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span>, matching: { $0.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">state</span> == <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSOnState</span> })</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">Here, the first parameter (which is ignored in the implementation) pins down the type of the generic parameter. Note that the predicate’s parameter is of type <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">NSButton</span> so there’s no <span style="color: rgb(187, 44, 162); font-family: Menlo; font-size: 11px;" class="">as</span><span style="font-family: Menlo; font-size: 11px;" class="">?</span> or something like that necessary.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">But there’s another way to pin down the generic parameter:</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">extension</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>SequenceType<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><div style="margin: 0px; line-height: normal; color: rgb(187, 44, 162);" class=""> @warn_unused_result</div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> findFirst<T>(<span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">@noescape</span> matching predicate: T <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">throws</span> -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Bool</span>) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">rethrows</span> -> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span>? {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">for</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">case</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> element <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span> <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">self</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">where</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">try</span> predicate(element) {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> element</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""> }</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class="">}</div></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(112, 61, 170);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> result2: </span>NSButton<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">? = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">containerView</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span>subviews<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">findFirst</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { $0.</span>state<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> == </span>NSOnState<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> }</span></div></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">This time, the generic parameter is inferred at call site by explicitly specifying the type of the <span style="font-family: Menlo; font-size: 11px;" class="">result2</span> variable.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">Note that with this implementation of <span style="font-family: Menlo; font-size: 11px;" class="">findFirst()</span> it’s also possible to pin down the generic parameter by giving the closure parameter a specific type:</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> result3 = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">containerView</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">subviews</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">findFirst</span> { (button: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSButton</span>) <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">in</span> button.<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">state</span> == <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">NSOnState</span> }</div></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">The first implementation seems nice to me at the call site because users of the API can’t miss specifying the type of <span style="color: rgb(112, 61, 170); font-family: Menlo; font-size: 11px;" class="">T</span>. But I don’t really like the way <span style="font-family: Menlo; font-size: 11px; color: rgb(112, 61, 170);" class="">NSButton</span><span style="font-family: Menlo; font-size: 11px;" class="">.</span><span style="font-family: Menlo; font-size: 11px; color: rgb(187, 44, 162);" class="">self</span> looks and from a language standpoint, the first parameter is redundant. It’s even ignored in the implementation!</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">The second implementation seems more correct to me, but at the call site, it may be easy to miss specifying the resulting variable’s type, which leads to a compiler error that is not 100% obvious to newcomers (“Type of expression is ambiguous without more context” pointing at the <span style="font-family: Menlo; font-size: 11px;" class="">$0</span>), which leads to users thinking about what they did wrong, which leads to them coming to me asking how to use this method.</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">I’d love to hear comments on this and what you think is the better way to implement this. If that were a method in the Swift Standard Library, how would you expect it to work?</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">(Bonus question: Why isn’t there a method like this in the Standard Library?)</div></body></html>