Using Array.map instead of array.map - swift

Here is what I can do in Swift:
extension Int {
func square() -> Int { return self * self }
}
And then call it like this: 3.square(), that gives me 9. Also, i can do it like so: Int.square(3), and it will give me () -> (Int). So, Int.square(3)() gives 9.
But if I write let array = [1, 2, 3]; Array.map(array) it gives error Cannot convert value of type 'Array<Int>' to expected argument of type '[_]'
Question is, how I can use Array.map in that way?
EDIT
Ok, I'll try to explain my problem in details. Now, I have function like this:
func map<T, U>(f: T -> U) -> [T] -> [U] {
return { ts in
ts.map(f)
}
}
It works, but only on arrays. There are many types that have map function, and it not very nice to declare global function like that for every type. So, lets say there is type C that have map function C<T> -> (T -> U) -> C<U>
Also, lets say I have function f, that transform A -> B -> C into B -> A -> C.
So, it looks like I can do something like this:
let array = [1, 2, 3]
let square: Int -> Int = {$0 * $0}
map(square)(array) // [1, 4, 9], works fine
f(Array.map)(square)(array) // Error
Question is not about code readability but about how Swift's type system works.

Array.map function is defined as:
public func map<T>(self: [Self.Generator.Element]) -> (#noescape Self.Generator.Element throws -> T) rethrows -> [T]
The problem here is that the compiler cannot infer the return type of the transform function or T. So you have to define it the two following ways:
// variable declaration
let mapping: (Int -> Int) throws -> [Int] = Array.map(array)
// or (especially useful for further function calls)
aFunction(Array.map(array) as (Int -> Int) throws -> [Int])
You can also see that the map function is marked as rethrows which gets "translated" to throws if you use the function. (It looks like a bug but closures don't have rethrows which could be the reason for this behavior).
So the function f could look like this in order to use it with Array.map:
// where
// A is the array
// B is the function
// C the type of the returned array
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> (A throws -> C) {
return { b in
{ a in
try f2(a)(b)
}
}
}
// or with a forced try! so you don't have to use try
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> A -> C {
return { b in
{ a in
try! f2(a)(b)
}
}
}
// call f (use try if you use the first implementation)
let square: Int -> Int = {$0 * $0}
f(Array.map)(square)

In the example with square the compiler can infer the type of the expression. In other words:
let f = Int.square(3)
is the same as
let f:() -> Int = Int.square(3)
However, map is a generic function that is parameterized on the closure return type:
public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
Consequently, this generates an error because the compiler doesn't know what T is:
let f = Array<Int>.map([1, 2, 3])
However, you can explicitly tell it what T is like this:
let f: ((Int) throws -> Int) throws -> [Int] = Array.map([1, 2, 3])
try! f({$0 * $0})
I think that answers your first question about square and map. I don't completely understand the rest of your question about converting A -> B -> C to B -> A -> C. Maybe you can provide more info on what f would look like.

Related

How does typecasting/polymorphism work with this nested, closure type in Swift?

I know that (Int) -> Void can't be typecasted to (Any) -> Void:
let intHandler: (Int) -> Void = { i in
print(i)
}
var anyHandler: (Any) -> Void = intHandler <<<< ERROR
This gives:
error: cannot convert value of type '(Int) -> Void' to specified type
'(Any) -> Void'
Question: But I don't know why this work?
let intResolver: ((Int) -> Void) -> Void = { f in
f(5)
}
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Void = intResolver
I messed around with the return type and it still works...:
let intResolver: ((Int) -> Void) -> String = { f in
f(5)
return "I want to return some string here."
}
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Any = intResolver (or stringResolver)
Sorry if this is asked before. I couldn't find this kind of question yet, maybe I don't know the keyword here.
Please enlighten me!
If you want to try: https://iswift.org/playground?wZgwi3&v=3
It's all about variance and Swift closures.
Swift is covariant in respect to closure return type, and contra-variant in respect to its arguments. This makes closures having the same return type or a more specific one, and same arguments or less specific, to be compatible.
Thus (Arg1) -> Res1 can be assigned to (Arg2) -> Res2 if Res1: Res2 and Arg2: Arg1.
To express this, let's tweak a little bit the first closure:
import Foundation
let nsErrorHandler: (CustomStringConvertible) -> NSError = { _ in
return NSError(domain: "", code: 0, userInfo: nil)
}
var anyHandler: (Int) -> Error = nsErrorHandler
The above code works because Int conforms to CustomStringConvertible, while NSError conforms to Error. Any would've also work instead of Error as it's even more generic.
Now that we established that, let's see what happens in your two blocks of code.
The first block tries to assign a more specific argument closure to a less specific one, and this doesn't follow the variance rules, thus it doesn't compile.
How about the second block of code? We are in a similar scenario as in the first block: closures with one argument.
we know that String, or Void, is more specific that Any, so we can use it as return value
(Int) -> Void is more specific than (Any) -> Void (closure variance rules), so we can use it as argument
The closure variance is respected, thus intResolver and stringResolver are a compatible match for anyResolver. This sounds a little bit counter-intuitive, but still the compile rules are followed, and this allows the assignment.
Things complicate however if we want to use closures as generic arguments, the variance rules no longer apply, and this due to the fact that Swift generics (with few exceptions) are invariant in respect to their type: MyGenericType<B> can't be assigned to MyGenericType<A> even if B: A. The exceptions are standard library structs, like Optional and Array.
First, let's consider exactly why your first example is illegal:
let intHandler: (Int) -> Void = { i in
print(i)
}
var anyHandler: (Any) -> Void = intHandler
// error: Cannot convert value of type '(Int) -> Void' to specified type '(Any) -> Void'
An (Any) -> Void is a function that can deal with any input; an (Int) -> Void is a function that can only deal with Int input. Therefore it follows that we cannot treat an Int-taking function as a function that can deal with anything, because it can't. What if we called anyHandler with a String?
What about the other way around? This is legal:
let anyHandler: (Any) -> Void = { i in
print(i)
}
var intHandler: (Int) -> Void = anyHandler
Why? Because we can treat a function that deals with anything as a function that can deal with Int, because if it can deal with anything, by definition it must be able to deal with Int.
So we've established that we can treat an (Any) -> Void as an (Int) -> Void. Let's look at your second example:
let intResolver: ((Int) -> Void) -> Void = { f in
f(5)
}
var anyResolver: ((Any) -> Void) -> Void = intResolver
Why can we treat a ((Int) -> Void) -> Void as an ((Any) -> Void) -> Void? In other words, why when calling anyResolver can we forward an (Any) -> Void argument onto an (Int) -> Void parameter? Well, as we've already found out, we can treat an (Any) -> Void as an (Int) -> Void, thus it's legal.
The same logic applies for your example with ((String) -> Void) -> Void:
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Void = stringResolver
When calling anyResolver, we can pass an (Any) -> Void to it, which then gets passed onto stringResolver which takes a (String) -> Void. And a function that can deal with anything is also a function that deals with strings, thus it's legal.
Playing about with the return types works:
let intResolver: ((Int) -> Void) -> String = { f in
f(5)
return "I want to return some string here."
}
var anyResolver: ((Any) -> Void) -> Any = intResolver
Because intResolver says it returns a String, and anyResolver says it returns Any; well a string is Any, so it's legal.

Using #discardableResult for Closures in Swift

Swift 3 has introduced the #discardableResult annotation for functions to disable the warnings for an unused function return value.
I'm looking for a way to silence this warning for closures.
Currently, my code looks like this:
func f(x: Int) -> Int -> Int {
func g(_ y: Int) -> Int {
doSomething(with: x, and: y)
return x*y
}
return g
}
In various places I call f once to obtain a closure g which I then call repeatedly:
let g = f(5)
g(3)
g(7)
g(11)
In most places I'm only interested in the side effects of the nested call to doSomething, and not in the return value of the closure g. With Swift 3, there are now dozens of warnings in my project for the unused result. Is there a way to suppress the warnings besides changing the calls to g to _ = g(...) everywhere? I couldn't find a place where I could place the #discardableResult annotation.
I don't think there's a way to apply that attribute to a closure. You could capture your closure in another that discards the result:
func discardingResult<T, U>(_ f: #escaping (T) -> U) -> (T) -> Void {
return { x in _ = f(x) }
}
let g = f(5)
g(3) // warns
let h = discardingResult(g)
h(4) // doesn't warn
I was looking for an answer to this recently, and I've found another way (a newer way) to do this!
It could arguably be overkill for some simple problems, but I just thought that this is an interesting yet neat approach that's worth sharing.
Say you have a closure that doubles an integer value:
let double = { (int: Int) -> Int in
return int * 2
}
With Swift 5.0 (SE-0216) introducing the #dynamicCallable attribute, you can "wrap" your closure with #discardableResult by creating a dynamically callable class or struct as such:
// same for struct, except without the need of an initializer
#dynamicCallable
class DiscardableResultClosure<T, U> {
var closure: (T) -> U
#discardableResult
func dynamicallyCall(withArguments args: [Any]) -> U {
let arg = args.first as! T
return self.closure(arg)
}
// implicit for struct
init(closure: #escaping (T) -> U) {
self.closure = closure
}
}
double(5) // warning: result of call to function returning 'Int' is unused
let discardableDouble = DiscardableResultClosure(closure: double)
discardableDouble(5) // * no warning *
Even better, in Swift 5.2 (SE-0253), you can create a dynamically callable struct using a built-in callAsFunction method without going through the trouble of using the attribute #dynamicCallable (or using class) with its sometimes cumbersome declaration.
struct DiscardableResultClosure<T, U> {
var closure: (T) -> U
#discardableResult
func callAsFunction(_ arg: T) -> U {
return closure(arg)
}
}
let discardableDouble = DiscardableResultClosure(closure: double)
discardableDouble(5) // * no warning *

Curried closures in Swift3?

Why
let arr = [1,2,3,4,5]
let filtered = arr.filter { $0 < 3 }
and why not?
let filtered = arr.filter(<3)
if I can use operator function:
[1,2,3].sorted(by: >)
The signatures of Sequence:s filter(...) and sorted(...) are as follows
func filter(_ isIncluded: (Self.Iterator.Element) throws -> Bool) rethrows -> [Self.Iterator.Element]
func sorted(by areInIncreasingOrder: (Self.Iterator.Element, Self.Iterator.Element) -> Bool) -> [Self.Iterator.Element]
Both methods expect a closure as their argument; the former one of type (Self.Iterator.Element) -> Bool, and the latter a one of type (Self.Iterator.Element, Self.Iterator.Element) -> Bool). < is function fulfilling the latter for Comparable types (specifically (Int, Int) -> Bool in your example), whereas <3 isn't a closure at all.
You could define your own function specifically for this purpose (thanks #vacawama)
func lessThan(_ value: Int) -> ((Int) -> Bool) {
return { $0 < value }
}
let arr = [1,2,3,4,5]
let filtered = arr.filter(lessThan(3))
print(filtered) // [1, 2]
But generally it might be more simple to just supply a closure on the fly to higher order functions such as filter and sorted.

How do I write map that works for all types in Swift?

As an exercise, I'm implementing a map function that takes an array and a function and applies the function to all elements of the array, but I don't know how to declare it such that it works for any type of array.
I can do something like
func intMap(var arr: [Int], fun: (Int) -> Int) -> [Int] {
for i in 0 ..< arr.count {
arr[i] = fun(arr[i])
}
return arr
}
intMap([1,2,3], {x in return x * x})
But this only works for int.
What is the type signature for Swift's built-in map?
Edit:
So I was missing the fact that I can declare param type signatures without declaring their types explicitly.
func myMap<T>(var arr: [T], fun: (T) -> T) -> [T] {
for i in 0 ..< arr.count {
arr[i] = fun(arr[i])
}
return arr
}
myMap([1,2,3], fun: {
x in return x * x
})
Create a new Playground
Just under where it has import UIKit type import Swift
Command click on the word Swift
This will open the Swift library and you can see all the type definitions there.
And you can see:
extension CollectionType {
/// Return an `Array` containing the results of mapping `transform`
/// over `self`.
///
/// - Complexity: O(N).
#warn_unused_result
#rethrows public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
Edited to add
Alternatively, you can write a more generalised map
func myMap<T, U>(var arr: [T], fun: T -> U) -> [U] {
var a: [U] = []
for i in 0 ..< arr.count {
a.append(fun(arr[i]))
}
return a
}
Which returns a new array, of a possibly different type, which you can see for yourself by putting this in your playground.
let a = [1, 2, 3]
let b = myMap(a, fun: { x in Double(x) * 2.1 })
a
b

Curry Function in Swift

I want to make a function that return a curry function like below
func addTwoNumbers(a: Int)(b: Int) -> Int {
return a + b
}
addTwoNumbers(4)(b: 6) // Result: 10
var add4 = addTwoNumbers(4)
add4(b: 10) // returns 14
What is the return type of such function and how can I generate a function like this using a function that take Variadic parameters.
func generateCurry(.../*Variadic parameters*/) -> .../*curry function type*/ {
return ...//curry function
}
I want a generic solution and not take only Int as arguments in the parmeter of the generateCurry function
let curried = curry(func(a, b, c) {
print(a + b + c)
})
curried(1)(2)(3) //prints 6
You can achieve this pretty easily with closures:
/// Takes a binary function and returns a curried version
func curry<A,B,C>(f: (A, B) -> C) -> A -> B -> C {
return { a in { b in f(a, b) } }
}
curry(+)(5)(6) // => 11
let add: Int -> Int -> Int = curry(+)
add(5)(6) // => 11
It would be really nice to be able to do the same thing for functions that take 3, 4 or more arguments, but without duplicating the implementation. The signature of such a function might start something like:
/// Take a function accepting N arguments and return a curried version
func curry<T>(args: T...) -> /* ? */
What would the return type be? It would change based on the input to the function. This definitely isn't possible in Swift at the moment, and I don't think it would be possible at all without some kind of macro system. But even with macros I don't think the compiler would be satisfied unless it knew the length of the list at compile-time.
Having said that, it's really straight-forward to manually overload the currying function with a version that accepts 3, 4, 5 or more parameters:
func curry<A,B,C,D>(f: (A, B, C) -> D) -> A -> B -> C -> D {
return { a in { b in { c in f(a,b,c) } } }
}
func curry<A,B,C,D,E>(f: (A, B, C, D) -> E) -> A -> B -> C -> D -> E {
return { a in { b in { c in { d in f(a,b,c,d) } } } }
}
// etc.
I'm not sure this is actually going to be possible in the same way it is inside of languages like Python.
The core problem I see to having a single generic solution is the strong typing of the closures/funcs you want to accept.
You could fairly easily create a curry function that worked on a specific or common function signature, but as far as a general purpose curry I don't see a way for it to work. The issue is more than about the types of the arguments (as mentioned in comments) but also with the number of them.
I've written up a simple example of how you could implement a curry function. It works, but I don't see a sane way to have a truly generic one like you can in more loosely typed languages.
func add(a1: Int, a2: Int) -> Int {
return a1 + a2
}
func curry(argument: Int, block: (Int, Int) -> Int) -> Int -> Int{
func curried(arg: Int) -> Int {
return block(argument, arg)
}
return curried
}
curry(5, add)(6)
In case you want to quickly get the curry function for any number of parameters, it's possible to generate it as shown in this gist.
The code is in Swift 2.2 and generates code for Swift 2.2 (at the moment). It uses simple template-based approach (a possible alternative is constructing an AST followed by code-generation):
func genCurry(n: Int, indent: Indent = .fourSpaces, accessLevel: AccessLevel = .Default, verbose: Bool = false) -> String {
// ...
// The bulky park is skipped for clarity.
return accessLevel.asPrefix + "func curry<\(genericParams)>(f: \(fSig)) -> \(curriedSig(n)) {\n"
+ indent.single + "return \(closure)\n"
+ "}\n"
}
I recently found that currying was removed back in Swift3. I created my own version which is repetitive but does the job.
precedencegroup CurryPrecedence {
associativity: left
higherThan: MultiplicationPrecedence
}
infix operator <<== :CurryPrecedence
//1 param
func <<==<A,Z>(_ f: #escaping (A) -> (Z), _ p:A) -> () -> (Z) {
{ f(p) }
}
//2 param
func <<==<A,B,Z>(_ f: #escaping (A, B) -> (Z), _ p:B) -> (A) -> (Z) {
{ (A) in f(A,p) }
}
//3 param
func <<==<A,B,C,Z>(_ f: #escaping (A, B, C) -> (Z), _ p:C) -> (A, B) -> (Z) {
{ (A, B) in f(A,B,p) }
}
//4 param
func <<==<A,B,C,D,Z>(_ f: #escaping (A, B, C, D) -> (Z), _ p:D) -> (A, B, C) -> (Z) {
{ (A, B, C) in f(A,B,C,p) }
}
To use it:
let ten = (addTwoNumbers <<== 6 <<== 4)()
or
let ten = (addTwoNumbers <<== 6)(4)