Reputation: 4895
I am learning swift coming from a Haskell background, I would like to translate this bit into swift:
match :: Int -> Bool
match = (>) 3
hasMatch :: (Int -> Bool) -> [Int] -> [Int]
hasMatch pred ns = filter pred ns
hasMatch match [1..5] = [4,5]
Silly example I know. This is what I have with swift:
func hasMatch(pred : (Int) -> Bool, ns : [Int]) -> [Int]{
return ns.filter{n in pred(n:n)}
}
func match(n: Int) -> Bool{
return n > 3
}
let os = hasMatch(pred : match, ns: [1,2,3,4,5])
Which does not compile. This is the error message:
let os = hasMatch(pred : match, ns: [1,2,3,4,5])
./hello-swift.swift:48:28: error: extraneous argument label 'n:' in call
return ns.filter{n in pred(n:n)}
^~~
./hello-swift.swift:48:24: error: closure use of non-escaping parameter 'pred' may allow it to escape
return ns.filter{n in pred(n:n)}
^
./hello-swift.swift:47:15: note: parameter 'pred' is implicitly non-escaping
func hasMatch(pred : (Int) -> Bool, ns : [Int]) -> [Int]{
^
@escaping
I have two questions:
I have pred(n:n)
but this assumes that pred
names its input as n
, which does not make sense. Do all functions have to have named inputs?
How would I change to the code so that it compiles
Upvotes: 0
Views: 1390
Reputation: 11
func mapedData(){
let bookData = ["book1":120, "book2": 150]
let mapedData = bookData.map({(key,value) in return value + 40 })
print(mapedData)
}
// [160, 190]
func filterData()
{
let bookData = ["book1":127, "book2": 150 ,"book3": 289 ,"book4": 190, "book5": 950 ]
let filterData = bookData.filter({(key,value) in return value < 200})
print(filterData)
}
// ["book2": 150, "book4": 190, "book1": 127]
func reducedData()
{
let data = [1,2,3,4,5,6,7,8,9,10]
let reducedData = data.reduce(0, { sum , number in return sum + number })
print(reducedData)
}
//55
func compactData(){
let data = [1,nil,3,4,5,6,7,nil,9,10]
let cMap = data.compactMap({return $0})
print(cMap)
}
// [1, 3, 4, 5, 6, 7, 9, 10]
func flatMappedData(){
let data = ["sachin"]
let characters = data.flatMap({return $0})
print(characters)
}
// ["s", "a", "c", "h", "i", "n"]
Upvotes: 0
Reputation: 38475
func hasMatch(pred: (Int) -> Bool, ns: [Int]) -> [Int] {
return ns.filter { n in pred(n) }
}
You don't need parameter names if the function is a closure.
@escaping
is a keyword in swift which tells the compiler that the passed in function will escape the current scope, so it needs to retain/release the passed in arguments (Swift, like objective-c, uses retain counting for memory management)
However, you don't need it in this case - that error was a red herring thrown by the compiler because it couldn't compile the line with filter
in, so it didn't know whether you needed to escape or not. Looks like it plays things safe :)
As soon as you remove the n:
and it can work out which filter
you are calling, it knows that because filter
doesn't need an @escaping
closure, your method doesn't either so that error goes away.
Upvotes: 3