How to make a function operate on a Sequence of Optional values? - swift

How does one specify that a function should operate on a sequence of optional values in Swift? For example, I want to make a function like this, which works for an Array of Optional values, for sequences.
// Given an array of optional values, return the first one with a value, if any
func firstValue<E>(ary: [E?]) -> E? {
for e in ary {
if let x = e {
return x
}
}
return nil
}
What I was hoping would work, but doesn't, because because there is no such thing as OptionalType):
func firstValue<C: SequenceType where C.Generator.Element: OptionalType>(seq: C) -> C.Generator.Element {
var g = seq.generate()
while let e = g.next() {
return e
}
return nil
}

Try this:
func firstValue<E, S: SequenceType where S.Generator.Element == Optional<E> >(seq: S) -> E? {
var g = seq.generate()
while let e:Optional<E> = g.next() {
if e != nil {
return e
}
}
return nil
}
let a:[Int?] = [nil,nil, 42, nil]
println(firstValue(a)) // -> 42 as Int?
I tested with Xcode Version 6.1.1 (6A2006) and Version 6.2 (6C86e)
Note
Without :Optional<E> in while condition, the compiler crashes.
And if we declare the function like this, the compiler clashes on some environment.
func firstValue<S: SequenceType, E where S.Generator.Element == Optional<E> > {
// ^^^^^^^^^^^^^^^^^^ replaced E and S
I think these are compiler bug. Please see the comments below.

There are two operations needed for the sequence elements:
Check if an element is nil or not, and
Create a nil value of the appropriate type as the default return value if nothing as was found.
For #2 we can use the fact that enum Optional conforms to the NilLiteralConvertible
protocol. For #1 I have defined a NilComparable protocol and made
enum Optional conform to it:
protocol NilComparable {
func isNil() -> Bool
}
extension Optional : NilComparable {
func isNil() -> Bool { return self == nil }
}
Now we can define a function for all sequences whose elements conform
to NilComparable and NilLiteralConvertible. All sequences of optionals
fall into this category:
func firstValue<C: SequenceType where
C.Generator.Element : NilComparable,
C.Generator.Element : NilLiteralConvertible
>(seq: C) -> C.Generator.Element {
var gen = seq.generate()
while let elem = gen.next() {
if !elem.isNil() {
return elem
}
}
return nil // Here NilLiteralConvertible is used.
}
Example:
let arr = [nil, nil, Optional(1), Optional(2)] // Type is [Optional<Int>]
println(firstValue(arr)) // Output: Optional(1)
Update: There is already a function
func !=<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool
which compares any optional value with nil, so the above protocol can be simplified
to
protocol NilComparable {
func !=(lhs: Self, rhs: _OptionalNilComparisonType) -> Bool
}
extension Optional : NilComparable { } // Already conforming
Then we can write if elem != nil { ... } instead of if !elem.isNil() { ... }
in the function.
A possible disadvantage is that _OptionalNilComparisonType is not officially
documented.
Remark: I tried to declare the function as
func firstValue<C: SequenceType, E where C.Generator.Element == Optional<E> >(seq: C) -> E? {
// ...
}
but that actually caused the compiler to crash. I don't know if this should compile.

Related

Swift 4.0 Difference between implementing custom operator inside a type as a type method and in global scope as a global function

Given a Parser type as following:
public struct Parser<Result> {
internal let parse: (String) -> (Result, String)?
public func run(_ string: String) -> (Result, String)? {
guard let (result, remainder) = parse(string) else { return nil }
return (result, remainder)
}
public func map<T>(_ transform: #escaping (Result) -> T )
-> Parser<T> {
return Parser<T> { input in
guard let (result, remainder) = self.run(input) else { return nil }
return (transform(result), remainder)
}
}
public func followed<A>(by other: Parser<A>) -> Parser<(Result, A)> {
return Parser<(Result, A)> { input in
guard let (result, remainder) = self.run(input) else { return nil }
guard let (resultA, remainderA) = other.run(remainder) else { return nil }
return ((result, resultA), remainderA)
}
}
}
First implementation as following:
infix operator >>> : FunctionCompositionPrecedence
public func >>> <A, B> (lhs: Parser<A>, rhs: Parser<B>)
-> Parser<(A,B)> {
return lhs.followed(by: rhs)
}
Second implementation as following:
infix operator >>> : FunctionCompositionPrecedence
extension Parser {
public static func >>> <A, B> (lhs: Parser<A>, rhs: Parser<B>)
-> Parser<(A,B)> {
return lhs.followed(by: rhs)
}
}
Reclaim the question as what is the difference between the first implementation and the second one.
Moreover, when I use the first implementation, and compile the following code, the compiler reported an error as
"'map' produces 'Parser', not the expected contextual result type 'Parser'"
extension Parser {
public static func apply <A, B> (_ lhs: Parser<(A)->B>, _ rhs: Parser<A>) -> Parser<B> {
return (lhs >>> rhs).map{(arg) -> B in let (f, x) = arg; return f(x)}
}
}
However, after I use the second implementation, everything goes fine.
I am so confused about the essential nuances between them.
With
infix operator >>> : FunctionCompositionPrecedence
extension Parser {
public static func >>> <A, B> (lhs: Parser<A>, rhs: Parser<B>)
-> Parser<(A,B)> {
return lhs.followed(by: rhs)
}
}
You've provided no way for the compiler to infer the generic placeholder Result on calling the operator (really I think the compiler should error here rather than on usage). Remember that static methods on generic types are called on specialisations of those types; the placeholders must be satisfied (as they're accessible at static scope).
So to directly answer
what is the difference between the first implementation and the second one.
The main difference is that as a static member, you have the additional generic placeholder Result that needs to be satisfied; as a top-level function, you don't have that.
So, if you want to keep >>> as a static method, you'll want to use the Result placeholder in the signature of your operator implementation such that the compiler can infer its type on usage, for example:
infix operator >>> : FunctionCompositionPrecedence
extension Parser {
public static func >>> <B> (
lhs: Parser, rhs: Parser<B>
) -> Parser<(Result, B)> {
return lhs.followed(by: rhs)
}
}
Now Result can be inferred from the type of the argument passed as the lhs of the operator (Parser is syntactic sugar for Parser<Result> in this context).
Note you'll face a similar problem with
extension Parser {
public static func apply <A, B> (_ lhs: Parser<(A)->B>, _ rhs: Parser<A>) -> Parser<B> {
return (lhs >>> rhs).map{(arg) -> B in let (f, x) = arg; return f(x)}
}
}
in that you'll need to explicitly satisfy the Result placeholder when calling; although the type used to satisfy it won't actually be used by the method.
Better would be to use the Result placeholder in the signature to allow the compiler to infer it at the call-site:
extension Parser {
public static func apply<Arg>(
_ lhs: Parser<(Arg) -> Result>, _ rhs: Parser<Arg>
) -> Parser<Result> {
return (lhs >>> rhs).map { arg -> Result in
let (f, x) = arg
return f(x)
}
}
}
// ...
let p = Parser<(String) -> String> { input in ({ $0 + input }, "hello") }
let p1 = Parser { ($0, "") }
let p2 = Parser.apply(p, p1)
print(p2.run(" world") as Any) // Optional(("hello world", ""))
Or, better still, as an instance method:
extension Parser {
public func apply<A, B>(with rhs: Parser<A>) -> Parser<B>
where Result == (A) -> B {
return (self >>> rhs).map { arg -> B in
let (f, x) = arg
return f(x)
}
}
}
// ...
let p = Parser<(String) -> String> { input in ({ $0 + input }, "hello") }
let p1 = Parser { ($0, "") }
let p2 = p.apply(with: p1)
print(p2.run(" world") as Any) // Optional(("hello world", ""))

Extending the SequenceType in Swift

I wondered why map() and filter() in SequenceType return both an Array.
Actually, I don't think that's necessary. Returning a sequence again feels much more sensible to me.
However, I got stuck when trying to add sequential versions. Here's my attempt with map:
extension SequenceType {
func seqMap<T, S: SequenceType where S.Generator.Element == T>(
transform: Self.Generator.Element -> T) -> S
{
var sourceGen = generate()
let tGen: AnyGenerator<T> = anyGenerator {
if let el = sourceGen.next() {
return transform(el)
} else {
return nil
}
}
return AnySequence { tGen }
}
}
XCode tells me at the last return statement the following error:
cannot invoke initializer for type 'AnySequence<T>' with an argument list of type '(() -> AnyGenerator<T>)'
note: overloads for 'AnySequence<T>' exist with these partially matching parameter lists: (S), (() -> G)
Actually, my tGen is of type () -> G, so why does XCode think it is ambiguous?
The problem becomes more apparent if you split the return statement:
let tSeq = AnySequence { tGen }
return tSeq // error: cannot convert return expression of type 'AnySequence<T>' to return type 'S'
The compiler would infer the placeholder type S from the context
of a method call, and that could be any sequence
type with element type T, and not necessarily an AnySequence.
Here is a simple example demonstrating the same problem:
protocol MyProtocol { }
struct MyType { }
extension MyType : MyProtocol { }
func foo<P : Protocol>() -> P {
return MyType() // error: cannot convert return expression of type 'MyType' to return type 'P'
}
To solve the problem, change the return type to AnySequence<T>
and drop the generic type S:
extension SequenceType {
func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T>
{
var sourceGen = generate()
let tGen: AnyGenerator<T> = anyGenerator {
if let el = sourceGen.next() {
return transform(el)
} else {
return nil
}
}
return AnySequence { tGen }
}
}
which can be written more compactly as
extension SequenceType {
func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T>
{
var sourceGen = generate()
return AnySequence(anyGenerator {
sourceGen.next().map(transform)
})
}
}
using the map() method of the Optional type.
But note that SequenceType already has a lazy method which returns
a LazySequenceType:
/// A sequence containing the same elements as a `Base` sequence, but
/// on which some operations such as `map` and `filter` are
/// implemented lazily.
///
/// - See also: `LazySequenceType`
public struct LazySequence<Base : SequenceType>
and you can use
someSequence.lazy.map { ... }
to get a (lazily evaluated) sequence of the mapped values.

Swift error comparing two arrays of optionals

I get a compilation error in the next Swift code
var x:Array<Int?> = [1,2]
var y:Array<Int?> = [1,2]
if x == y { // Error
}
If both arrays are Array<Int> it works fine, but if at least one of them is optional it throws an error like the next:
Binary operator '==' cannot be applied to two Array<Int?> operands
I filed a bug report months ago but I had no answer. It still occurs in Swift 1.2.
Why is this happening?
The issue here is the distinction between something having an == operator, versus something being “equatable”.
Both Optional and Array have an == operator, that works when what they contain is equatable:
// if T is equatable, you can compare each entry for equality
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
// if T is equatable, you can compare the contents, if any, for equality
func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool
let i: Int? = 1
let j: Int = 1
i == j // fine, Int is Equatable
["a","b"] == ["a","b"] // and so is String
But they themselves do not conform to Equatable. This makes sense given you can put a non-equatable type inside them. But the upshot of this is, if an array contains a non-equatable type, then == won’t work. And since optionals aren’t Equatable, this is the case when you put an optional in an array.
You'd get the same thing if you tried to compare an array of arrays:
let a = [[1,2]]
let b = [[1,2]]
a == b // error: `==` can’t be applied to `[Array<Int>]`
If you wanted to special case it, you could write == for arrays of optionals as:
func ==<T: Equatable>(lhs: [T?], rhs: [T?]) -> Bool {
if lhs.count != rhs.count { return false }
for (l,r) in zip(lhs,rhs) {
if l != r { return false }
}
return true
}
For a counter-example, since Set requires its contents to be hashable (and thus equatable), it can be equatable:
let setarray: [Set<Int>] = [[1,2,3],[4,5,6]]
setarray == [[1,2,3],[4,5,6]] // true

Tuple-type in Swift generic constraint

I'm trying to write a generic function in Swift with the constraint that the parameter must be a sequence of pairs (which I'm going to turn into a dictionary). Is this possible? I've tried a number of variations on the following, but the compiler doesn't like any of them.
func foo<K, V, S: SequenceType where S.Generator.Element == (K,V)>(xs: S) { //...}
Not a direct answer to your question, but if you want to create
a dictionary then you could define your function as an extension
method to Dictionary and use the fact that Dictionary defines
typealias Element = (Key, Value)
Then your method declaration could be
extension Dictionary {
func foo<S : SequenceType where S.Generator.Element == Element>(xs : S) {
//...
}
}
To create a dictionary from the tuples, an init method might be more appropriate, for example
extension Dictionary {
init<S : SequenceType where S.Generator.Element == Element>(xs : S) {
self.init()
var gen = xs.generate()
while let (key, value) : Element = gen.next() {
self[key] = value
}
}
}
Usage:
let d = Dictionary(xs: [("a", 1), ("b", 2)])
println(d) // [b: 2, a: 1]
Note: The enumation via generate() and next() in above code
is a workaround for the problem that, for some reason
for (key, value) in xs { }
does not compile. Compare Implementing Set.addSequence in Swift.
Update: As of Swift 2/Xcode 7, the above method can be simplified
to
extension Dictionary {
init<S : SequenceType where S.Generator.Element == Element>(xs : S) {
self.init()
xs.forEach { (key, value) in
self[key] = value
}
}
}
It looks like a compiler bug to me.
Problem here is that: you cannot use tuple type directly in generic parameters.
As #MartinR said in his answer, it works if we use typealiased tuple type. But of course, we cannot declare generic typealias in global context.
For example, this compiles and works:
struct Foo<K,V> {
typealias Element = (K,V)
static func foo<S:SequenceType where S.Generator.Element == Element>(xs:S) {
var gen = xs.generate()
while let (k,v): Element = gen.next() {
println((k,v))
}
}
}
Foo.foo(["test":"foo", "bar": "baz"])
One more idea is something like this:
struct SequenceOfTuple<K,V>: SequenceType {
typealias Element = (K,V)
let _generate:() -> GeneratorOf<Element>
init<S:SequenceType where S.Generator.Element == Element>(_ seq:S) {
_generate = { GeneratorOf(seq.generate()) }
}
func generate() -> GeneratorOf<Element> {
return _generate()
}
}
func foo<K,V>(xs:SequenceOfTuple<K,V>) {
for (k, v) in xs {
println((k,v))
}
}
foo(SequenceOfTuple(["test":"foo", "bar": "baz"]))
In this case, you must wrap the sequence of tuple with SequenceOfTuple type, then pass it to foo().
Hmm...
You can use a struct with a subscript and store the results in a Dictionary:
struct Matrix<K:Hashable, V> {
var container:[K:[K:V]] = [:]
subscript(x:K, y:K) -> V? {
get {
return container[x]?[y]
}
set (value) {
if container[x] == nil {
container[x] = [:]
}
container[x]![y] = value
}
}
}
var matrix = Matrix<Int, String>()
matrix[11,42] = "Hello World"
println("(11,42): \(matrix[11,42])") // Optional("Hello World")
println("(1,3): \(matrix[1,3])") // nil

Why is generic type information lost in generic functions with a Comparable constraint?

When creating a normal generic function without constraints it works as intended, i.e:
func select<T,U>(x:T, f:(T) -> U) -> U {
return f(x)
}
The type flows through into the closure argument where it lets me access it as the strong type, i.e:
var b1:Bool = select("ABC") { $0.hasPrefix("A") }
var b2:Bool = select(10) { $0 > 0 }
It continues to work when I add an Equatable constraint:
func selectEquatable<T : Equatable, U : Equatable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b3:Bool = selectEquatable("ABC") { $0.hasPrefix("A") }
But for some reason fails when using a Comparable constraint:
func selectComparable<T : Comparable, U : Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b4:Bool = selectComparable("ABC") { $0.hasPrefix("A") }
Fails with the build error:
Could not find member 'hasPrefix'
But it does allow returning itself where the type flows through as a String
var b5:String = selectComparable("ABC") { $0 }
Looking at the API docs shows that String is Comparable:
extension String : Comparable {
}
and it even allows implicit casting from a String to a Comparable:
var str:Comparable = ""
So why can't I access it as a strong-typed String inside my Closure?
var b4:Bool = selectComparable("ABC") { $0.hasPrefix("A") } //build error
It's not the String. Your closure { $0.hasPrefix("A") } has the return type Bool, which is assigned to U. Bool is Equatable, but not Comparable.
You probably want the closure to return Bool, but selectComparable to return U.
Edit
Here's evidence that returning a String (which is Comparable) instead of a Bool (not Comparable) will compile:
func selectComparable<T: Comparable, U: Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
var b4 = selectComparable("ABC") { (str: String) -> String in str }
Your selectComparable declaration is incorrect.
func selectComparable<T: Comparable, U: Comparable>(x:T, f:(T) -> U) -> U {
return f(x)
}
U: Comparable cannot hold for type Bool, it is not Comparable, only Equatable
This will work fine
func selectComparable<T: Comparable, U>(x:T, f:(T) -> U) -> U {
return f(x)
}
as will
func select<T:Comparable,U: Equatable>(x:T, f:(T) -> U) -> U {
return f(x)
}