[swift-evolution] [Review] SE-0032: Add find method to SequenceType

Dave Abrahams dabrahams at apple.com
Fri Apr 29 19:51:18 CDT 2016


on Fri Apr 29 2016, Kevin Ballard <swift-evolution at swift.org> wrote:

> On Fri, Apr 29, 2016, at 05:12 PM, Max Moiseev via swift-evolution wrote:
>> HI all,
>>
>>
>> After having discussed this proposal with the members of the standard
>> library team, we would like to propose the following updates:
>>
>> - Since both the language and the standard library have evolved since
>>   it was written, the proposal should reflect these changes (things
>>   like renaming `Generator` to `Iterator`, adjusting for first
>>   argument label rules etc.)
>>> (Actually, while writing this, I discovered
>>> https://github.com/apple/swift-evolution/pull/276)
>> - We believe that renaming `find(_:)` to `first(where:)` would make
>>   call sites more clear
>>
>>> // original proposal
>>> numbers.find { isPrime($0) }
>>> numbers.find(isPrime)
>>>
>>> // suggested update
>>> numbers.first { isPrime($0) }
>>> numbers.first(where: isPrime)
>>>
>>> In the examples above, when the predicate is passed as a trailing
>>> closure, there is no big difference in the invocation, but it changes
>>> when we have a named function that we would like to use as a
>>> predicate.
>>> The Collection protocol already has a property called `first`, that
>>> returns an optional element, it also has a method `index(where:)`. In
>>> this sense `first(where:)` does not introduce new words to the
>>> library vocabulary.
>
> first(where:) is a neat idea, but I'm a little concerned about ambiguity
> with the property in the presence of type errors. Experimentally, if I
> try to call first(where:) with a block with the wrong signature, Swift 3
> produces an unhelpful error about how I cannot call value of a non-
> function type (i.e. the property) instead of recognizing that I'm trying
> to call the function.
>
> Example:
>
> struct Foo {
> var first: Int = 42
>
> func first(where: @noescape Int -> Bool) -> Int {
> return 42
> }
> }
>
> If I try and call `print(Foo().find(where: { true }))`, you'll note that
> the closure has the wrong type signature (it types as `() -> Bool`), and
> the compiler gives me the error:
>
> <REPL Input>:1:12: error: cannot call value of non-function type 'Int'
> Foo().first(where: { true })
> ~~~~~~~~~~~^
>
> Calling it with a block of the correct type works, but having useful
> errors is very important.

That's a QOI bug in the compiler that can be fixed.  IMO we should avoid
designing APIs around temporary limitations of the compiler
implementation.

-- 
Dave



More information about the swift-evolution mailing list