Swift single argument with autoclosure without braces at all - swift

I would like to achieve Haskell elem function with Apple Swift language.
This looks like not very hard to implement:
func elem<T: Equatable>(item: T) -> [T] -> Bool {
return { arr in find(arr, item) != nil }
}
elem(2)([1,2,3])
But I wanna to skip braces for arguments. It is possible for last(or single) argument of closure type:
func elem<T: Equatable>(item: ()->T) -> (()->[T]) -> Bool {
return { (arr: ()->[T]) in find(arr(), item()) != nil }
}
elem{2}{[1,2,3]}
But here we have an error:
Consecutive statements on a line must be separated by ':'
This error is a real problem, which looks like compiler imperfection. But we need to go deeper to avoid brackets {}, it can be achieved with #autoclosure:
func elem<T: Equatable>(item: #autoclosure ()->T) -> (#autoclosure ()->[T]) -> Bool {
return { (arr: #autoclosure ()->[T]) in find(arr(), item()) != nil }
}
elem 2 [1,2,3]
And we have the same error.
I think Swift compiler should not give me this errors. Are there any other ways to avoid braces and brackets?

Related

Get first mapped result from array

I have an array of functions like
let array = [(Int) -> T?, (Int) -> T?, (Int) -> T?,...]
I need to get first non nil T value from array and I want 1 iteration for this task (O(n) will be the worst complexity). Anybody has neat ideas without for loops?
As I mentioned in my comment, there's no ready-made way to do this in Swift, so you have to at least implement something that uses a for loop.
If you want appearances at the call-site to look functional and not use a for loop, you can make the function extend Array like so:
extension Array {
func firstNonNilResult<V, T>(value: V) -> T? where Element == (V) -> T? {
for element in self {
if let t = element(value) {
return t
}
}
return nil
}
}
var array = [(Int) -> String?]()
func f(_ i: Int) -> String? {
print("called f() with \(i)")
return nil
}
func g(_ i: Int) -> String? {
print("called g() with \(i)")
return i == 5 ? "found it" : nil
}
array.append(f)
array.append(g)
if let t = array.firstNonNilResult(value: 5) {
print(t)
}
which prints:
called f() with 5
called g() with 5
found it
Whether or not this has any real-world utility I can't say. I think it's specialized enough that an Array extension seems like overkill, but your question is interesting so this is at least a potential solution.

How do I write the not/negate higher order function in swift?

I am a Javascripter and I love using the not/negate function:
function not (predicateFunc) {
return function () {
return !predicateFunc.apply(this, arguments);
};
}
I am trying to do the same thing with swift:
func not <A> (_ f: #escaping (_ A: Any) -> Bool) -> (A) -> Bool {
return { a in !f(a) }
}
But I am getting errors like
generic parameter 'T' could not be inferred
and
Cannot convert value of type '(_) -> Bool' to expected argument type '(Any) -> Bool'
The outcome I am looking for is when I have a function like this:
func isEmpty<T: Collection>(collection: T) -> Bool {
return collection.count == 0
}
I can just create a notEmpty function like this:
let notEmpty = not(isEmpty)
And then use it like
notEmpty([3,4,5]) // true
What am I doing wrong?
Using Any is a code smell. You can just extend Collection directly:
extension Collection {
var notEmpty: Bool {
return !isEmpty
}
}
[1, 3, 5].notEmpty // true
Your functional definition of not can work like this:
func not <A> (_ f: #escaping (_ a: A) -> Bool) -> (A) -> Bool {
return { a in !f(a) }
}
But to call it you would need something like this:
let arrayNotEmpty = not { (array: [Int]) in array.isEmpty }
arrayNotEmpty([1, 3, 5]) // true
You have two errors:
You're using A as both the type parameter and as the argument name.
You're using Any as the argument type instead of using the type parameter (A) as the argument type.
Try this:
func not<A>(predicate: #escaping (A) -> Bool) -> (A) -> Bool {
return { !predicate($0) }
}
Note that in this version, I'm not using argument names for the predicate argument. You don't need an argument name in the declaration ((A) -> Bool) and I'm using the anonymous argument name ($0) in the body.
Okay, so you want to write this:
func isEmpty<T: Collection>(collection: T) -> Bool {
return collection.count == 0
}
func not<A>(_ predicate: #escaping (A) -> Bool) -> (A) -> Bool {
return { !predicate($0) }
}
let notEmpty = not(isEmpty)
And you get this error:
let notEmpty = not(isEmpty)
^ Generic parameter 'A' could not be inferred
The problem is that this code tries to create a generic closure, but Swift doesn't support generic closures.
That is to say, what would the type of nonEmpty be? It would be something like:
<A: Collection>(A) -> Bool
and Swift doesn't support that.

In Swift 3, what is a way to compare two closures?

Suppose you have two closures of type (Int)->() in Swift 3 and test to see if they are the same as each other:
typealias Baz = (Int)->()
let closure1:Baz = { print("foo \($0)") }
let closure2:Baz = { print("bar \($0)") }
if(closure1 == closure2) {
print("equal")
}
This fails to compile, giving the message:
Binary operator '==' cannot be applied to two '(Int)->()' operands
OK, well, how then can we compare two closures of the same type, to see if they are the same?
I'm pretty sure there is no way to determine if two closures are equal.
Obviously, a logical equality check is out of the question. That would be equivalent to finding an answer to the halting problem. (Just test to see if your code is equivalent to a piece of code that loops forever. If it is, it doesn't halt. If it isn't, it does halt.)
In theory you might expect the === operator to test if two closures are the exact same piece of code, but that gives an error when I try it in Playground.
Playground execution failed: error: MyPlayground.playground:1:20: error: cannot check reference equality of functions; operands here have types '(Int) -> ()' and '(Int) -> ()'
let bar = closure1 === closure2
~~~~~~~~ ^ ~~~~~~~~
Having thought about it, I'm sure the reason why that doesn't work is because you can't be sure that the closures really are equal. A closure is not just the code, but also the context in which it was created including any captures. The reason you can't check for equality is that there is no meaningful way in which two closures are equal.
To understand why thew captures are important, look at the following code.
func giveMeClosure(aString: String) -> () -> String
{
return { "returning " + aString }
}
let closure1 = giveMeClosure(aString: "foo")
let closure2 = giveMeClosure(aString: "bar")
Are closure1 and closure2 equal? They both use the same block of code
print(closure1()) // prints "returning foo"
print(closure2()) // prints "returning bar"
So they are not equal. You could argue that you can check the code is the same and the captures are the same, but what about
func giveMeACount(aString: String) -> () -> Int
{
return { aString.characters.count }
}
let closure3 = giveMeACount(aString: "foo")
let closure4 = giveMeACount(aString: "bar")
print(closure3()) // prints 3
print(closure4()) // prints 3
Apparently these closures are equal. It's not possible to implement any reasonable definition of equality that will work in every case, so Apple has instead not even tried. This is safer than providing an incomplete implementation that is wrong in some cases.
In the case where you want to track your own closures, uses them as Dictionary keys, etc., you can use something like this:
struct TaggedClosure<P, R>: Equatable, Hashable {
let id: Int
let closure: (P) -> R
static func == (lhs: TaggedClosure, rhs: TaggedClosure) -> Bool {
return lhs.id == rhs.id
}
var hashValue: Int { return id }
}
let a = TaggedClosure(id: 1) { print("foo") }
let b = TaggedClosure(id: 1) { print("foo") }
let c = TaggedClosure(id: 2) { print("bar") }
print("a == b:", a == b) // => true
print("a == c:", a == c) // => false
print("b == c:", b == c) // => false

is there a more elegant syntax for Swift Filter with 2 parameters

Is there a more elegant way to filter with an additional parameter (or map, reduce).
When I filter with a single parameter, we get a beautiful easy to ready syntax
let numbers = Array(1...10)
func isGreaterThan5(number:Int) -> Bool {
return number > 5
}
numbers.filter(isGreaterThan5)
However, if I need to pass an additional parameter to my function it turns out ugly
func isGreaterThanX(number:Int,x:Int) -> Bool {
return number > x
}
numbers.filter { (number) -> Bool in
isGreaterThanX(number: number, x: 8)
}
I would like to use something like
numbers.filter(isGreaterThanX(number: $0, x: 3))
but this gives a compile error annonymous closure argument not contained in a closure
You could change your function to return a closure which serves
as predicate for the filter method:
func isGreaterThan(_ lowerBound: Int) -> (Int) -> Bool {
return { $0 > lowerBound }
}
let filtered = numbers.filter(isGreaterThan(5))
isGreaterThan is a function taking an Int argument and returning
a closure of type (Int) -> Bool. The returned closure "captures"
the value of the given lower bound.
If you make the function generic then it can be used with
other comparable types as well:
func isGreaterThan<T: Comparable>(_ lowerBound: T) -> (T) -> Bool {
return { $0 > lowerBound }
}
print(["D", "C", "B", "A"].filter(isGreaterThan("B")))
In this particular case however, a literal closure is also easy to read:
let filtered = numbers.filter( { $0 > 5 })
And just for the sake of completeness: Using the fact that
Instance Methods are Curried Functions in Swift, this would work as well:
extension Comparable {
func greaterThanFilter(value: Self) -> Bool {
return value > self
}
}
let filtered = numbers.filter(5.greaterThanFilter)
but the "reversed logic" might be confusing.
Remark: In earlier Swift versions you could use a curried function
syntax:
func isGreaterThan(lowerBound: Int)(value: Int) -> Bool {
return value > lowerBound
}
but this feature has been removed in Swift 3.

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

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.