How to use Anonymous Closure in Swift? - swift

A closure function :
func makeIncrementer(externNumber:Int) -> (Int -> Int) {
func addOne(number: Int) -> Int {
return externNumber + number
}
return addOne
}
I want to use Anonymous Closure to achieve it, so I write this :
func my_makeIncrementer(externNumber:Int) -> (Int -> Int) {
return {
(number:Int)-> Int { // Error : cannot create a single-element tuple with an element label ;
return externNumber + number ;
} ;
}
}
You can see, Xcode throw a error
Error : cannot create a single-element tuple with an element label

You should re-look up the syntax here:
func my_makeIncrementer(externNumber:Int) -> (Int -> Int) {
return {
(number:Int)-> Int in
return externNumber + number
}
}

Related

How to check/predicate function type in Swift?

For example:
func f(x: Int) -> Int {
return x
}
func h(f: #escaping (Int) -> Any) {
if (f is (Int) -> Int) {
print(f(1))
} else {
print("invalid")
}
}
h(f: f)
I expect it to print out 1 but it actually prints out invalid.
There's a workaround using generics:
func intF(x: Int) -> Int {
return x
}
func stringF(x: Int) -> String {
return "\(x)"
}
func h<T>(f: (Int) -> T) {
if (T.self == Int.self) {
print(f(1))
} else {
print("invalid")
}
}
h(f: intF) // prints: 1
h(f: stringF) // prints: invalid
Using Any is almost always a sign of code smell, you should try to rely as much as possible of the type safety that Swift provides. You can achieve this by making h generic, thus verifiable at compile time.
// the overload that does the actual stuff
func h(f: #escaping (Int) -> Int) {
print(f(1))
}
// this maps to all other types
func h<T>(f: #escaping (Int) -> T) {
print("invalid")
}
h { _ in return "15" } // Invalid
h { 2 * $0 } // 2
Heck, you could even give up the generic overload, thus you'll have for free compile checks instead of runtime failures (much, much reliable and predictive)
You can rewrite h into a generic function:
func h<T>(f: #escaping (Int) -> T) {
if T.self == Int.self {
print(f(1))
} else {
print("invalid")
}
}
But the better way to to write type-specific overloads for h and a generic catch-all for the rest (if you need it at all).

overload operator as generic function

i saw an example on "Pro swift" book.
it overloaded the operator, the first parameter "lhs" is a function that takes T -> U.
but "generateRandomNumber" function is Int -> Int
How can it work on >>> operator?
how does it work?
thanks.
import Foundation
infix operator >>> { associativity left }
func >>> <T, U, V>(lhs: T -> U, rhs: U -> V) -> T -> V {
return { rhs(lhs($0)) }
}
func generateRandomNumber(max: Int) -> Int {
let number = Int(arc4random_uniform(UInt32(max)))
print("Using number: \(number)")
return number
}
func calculateFactors(number: Int) -> [Int] {
return (1...number).filter { number % $0 == 0 }
}
func reduceToString(numbers: [Int]) -> String {
return numbers.reduce("Factors: ") { $0 + String($1) + " " }
}
let combined = generateRandomNumber >>> calculateFactors >>>
reduceToString
print(combined(100))
see the documentation about generics.
let combined = generateRandomNumber >>> calculateFactors >>> reduceToString
print(generateRandomNumber.dynamicType)
print(calculateFactors.dynamicType)
print(reduceToString.dynamicType)
print(combined.dynamicType)
/*
Int -> Int
Int -> Array<Int>
Array<Int> -> String
Int -> String
*/

Advantage of function types as parameter types in swift?

I'm currently working my way through the Swift Programming Manual from Apple and came across function types as parameter types.
In usual way,
func add(one : Int , _ two:Int) ->Int
{
return one+two
}
func multiply(one : Int ,_ two : Int) ->Int
{
return one*two
}
func subtract(one : Int , _ two :Int) ->Int
{
return one-two
}
add(1, 2)
subtract( 1 , 2)
multiply(1 , 2)
Using Function types as parameters,
func add(one : Int , _ two:Int) ->Int
{
return one+two
}
func multiply(one : Int ,_ two : Int) ->Int
{
return one*two
}
func subtract(one : Int , _ two :Int) ->Int
{
return one-two
}
func basic(result : (Int , Int) ->Int,_ one : Int , _ two : Int)
{
result(one,two)
}
basic(add, 1, 2)
basic(multiply, 2, 3)
So, from above code it is clear that we are writing extra function basic() and extra lines of code which are not that useful in this example and makes it complicated.It's better not to use function types as parameter types.
So,is there any example which takes advantage of the feature?
If you look at Swift's standard library you will see that many methods do that like map which is defined on Array.
map takes a function which transforms the elements of the array to a new array with a new type.
It is also a generic function but in order to keep it simple I use a function which maps Int Arrays:
func map(_ array: [Int], _ transform: Int -> Int) -> [Int] {
var result = [Int]()
for element in array {
result.append(transform(element))
}
return result
}
// map can be used with other functions
// and also closures which are functions
// without a name and can be created "on the fly"
func addByOne(i: Int) -> Int {
return i + 1
}
func square(i: Int) -> Int {
return i * i
}
map([1,2,3], addByOne) // [2,3,4]
map([1,2,3], square) // [1,4,9]
// and so on...
// with closures
map([1,2,3]) { $0 + 1 } // [2,3,4]
map([1,2,3]) { $0 * $0 } // [1,4,9]
So it is mainly used in libraries where you can offer APIs which have a much broader range of usage.

Im confused on how this function is being called, there is no call for it?

I'm confused on how getFunctionNeededForReference is running. There is no call for it and where are the functions returned to? where are they going? I know they are being referenced but where are the functions going to, there is not call for getFunctionNeededForReference in the beginning? there is no call sending the argument flag anyway?
func add ( a: Int , b : Int)-> Int {
//returing a result and not a variable
return a + b
}
func multiply ( a: Int, b: Int) -> Int{
return a * b
}
// declaring a function as a variable, it takes in 2 Ints and returns an Int
var f1 : (Int, Int)-> Int
f1 = add
f1 = multiply
// Function as a parameter
func arrayOperation (f: (Int, Int) -> Int , arr1: [Int] , arr2: [Int]) -> [Int]
{
// Declaring and initializing an empty array to return
var returningArray = [Int]()
for (i, val) in enumerate(arr1)
{
returningArray.append(f(arr1 [i], arr2 [i]))
}
return returningArray
}
arrayOperation(add, [2,3,4], [4,5,6])
arrayOperation(multiply, [2,3,4], [4,5,6])
//Function as a return value
func getFunctionNeededForReference (flag : Int) -> (Int,Int) ->Int
{
if flag == 0 {
return add
}else {
return multiply
}
}
What you've posted is just some example code showing things that Swift supports. It's not code that's useful for anything. It's just demonstrating Swift's syntax for first-class functions.
If you don't understand what “first-class functions” means, you can look up the term in your favorite search engine and find many explanations.

Function of swift, taking another function of its arguments

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)
This is the example on The Swift Programming Language.
But in this example, I want to change
func lessThanTen(number: Int) -> Bool {
return number < 10
}
to
func lessThanBenchmark(number: Int, benchMark: Int) -> Bool {
return number < 10
}
so I also change this example to
func hasAnyMatches(list: Int[], condition: (Int, benchmark: Int) -> Bool) -> Bool {
for item in list {
if condition(item, benchmark) {
return true
}
}
return false
}
func lessThanBenchmark(number: Int, benchmark: Int) -> Bool {
return number < benchmark
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanBenchmark)
However, I got an error.
<REPL>:155:28: error: use of unresolved identifier 'benchmark'
if condition(item, benchmark) {
At last, I have to write like this style
func hasAnyMatches(list: Int[], condition: (Int, Int) -> Bool, benchmark:Int) -> Bool {
for item in list{
if condition(item, benchmark) {
return true
}
}
return false
}
func lessThanBenchmark(number: Int, benckmark: Int) -> Bool {
return number < benckmark
}
var numbers = [20, 19, 7,12]
hasAnyMatches(numbers, lessThanBenchmark, 10)
How can I pass benchmark to condition just as its own parameter?
benchmark is an argument of function.
condition: (Int, benchmark: Int) -> Bool
this line of code means that condition is a function that return Bool value and can takes two arguments: Int as first argument, and benchmark: Int is second argument.
You can call benchmark inside of condition.
smth like that:
func hasAnyMatches(list: Int[], condition: (Int, benchmark: Int) -> Bool) -> Bool {
for item in list {
if condition(item, benchmark: 15) {
return true
}
}
return false
}
15 is a value that you want to use