Swift: Closure with Known Types Syntax - swift

I am trying to understand the syntax behind Known Types Closures.
Below is an example:
func applyMutliplication(value: Int, multiFunction: Int -> Int) -> Int {
return multiFunction(value)
}
applyMutliplication(2, multiFunction: {value in
value * 3 // returns a 6
})
I am struggling with multiFucntion: Int -> Int. Is this the same as (multiFunction: Int) -> Int?
When I try I try the following signature in playground, I get an error:
//below gives an error
func applyMutliplication(value: Int, ((multiFunction: Int) -> Int)) -> Int {
return multiFunction(value)
}
My understanding is:
applyMultiplication takes in an Int called value, and a closure called multiFunction that takes an Int and returns an Int. applyMultiplication also returns Int
But then I am confused with as to how does {value in value * 3} causes it to return a 6?

multiFucntion: Int -> Int. is not (multiFunction: Int) -> Int?
multiFunction is a function parameter name, it does not have anything to do with the type. The type is just (Int) -> Int. A function that has one Int parameter and returns an Int.
You are passing a closure that returns its parameter multiplied by 3 and you are passing it 2 as its parameter. The result is logically 6.
Maybe it could be more readable this way:
func applyMutliplication(value: Int, multiFunction: Int -> Int) -> Int {
return multiFunction(value)
}
let multiplyByThree: (Int) -> Int = {value in
value * 3 // returns a 6
}
applyMutliplication(2, multiFunction: multiplyByThree)

Related

Extraneous argument label 'number:' in call

While I was learning about "Functions", I met an issue showing "Extraneous argument label 'number:' in call" error msg for my code. I wonder why I shouldn't place "number" in argument?
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
increment(number: 7)
enter image description here
The problem is that you're returning a (Int) -> Int, which doesn't specify a name for its argument. Ideally, you'd want to write
func makeIncrementer() -> ((number: Int) -> Int)
but that isn't allowed in Swift:
function types cannot have argument labels; use '_' before 'number'
The best you can do is
func makeIncrementer() -> ((_ number: Int) -> Int)
This strategy might make your code a little clearer because giving the argument a name makes its purpose more obvious. Unfortunately, you still have to omit the number: label when you call the returned function:
let increment = makeIncrementer()
increment(7) // <- no `number:` label
What's the rationale?
Specifying argument labels for function types was possible before Swift 3. The problem was that you could write
func add(numToAdd: Int) -> Int { ... }
func subtract(numToSubtract: Int) -> Int { ... }
let f: ((numToAdd: Int) -> Int) = subtract
and then calling f(numToAdd: 3) would actually call subtract(numToSubtract: 3), which is quite surprising and can cause confusion.
Check out this proposal for the full rationale behind removing this feature.

Cannot convert value of type '[Int]' to expected argument type 'Int'

I new in swift and now learning this hard as i can. I wrote function that got arguments: numbers and function that work with this numbers:
func anotherSum(_ numbers : Int...) -> Int {
return numbers.reduce(0, +)
}
func makeSomething(_ numbers : Int..., f : (Int...) -> Int) {
print(workFunction(numbers))
}
makeSomething(1,2,3,4,5,6,7,8, f: anotherSum)
But compile gives out error cannot convert value of type '[Int]' to expected argument type 'Int'
. When i tried to change argument like
workFunction : ([Int]) -> Int) and
func anotherSum(_ numbers : [Int]) -> Int
It work perfectly, but i still can't understand why realisation with Int... doesn't work and why compiler gives this error.
As the Int... is considered as an [Int] in the function body so compiler will not allow to pass [Int] in place of Int.... You better calculate the sum as below,
func makeSomething(_ numbers : Int..., workFunction : (Int...) -> Int) {
let sum = numbers.map({ workFunction($0)}).reduce(0, +)
print(sum)
}
Or introduce another method that accepts array of Int and returns sum. Something as below,
func anotherSum(_ numbers : [Int]) -> Int {
return numbers.reduce(0, +)
}
func makeSomething(_ numbers : Int..., workFunction : ([Int]) -> Int) {
print(workFunction(numbers))
}

Parentheses in Function and Closure

I am bit confused on declaring parameter and return type in Swift.
does these parameter and return type have the same meaning? What is the use of those parentheses ()?
func myFunction() -> (()-> Int)
func myFunction() -> (Void-> Int)
func myFunction() -> Void-> Int
First... () and Void are the same thing you have two different ways of writing the same thing.
Second... The -> is right associative. So using parens as you have in your examples are meaningless, much like they are with an expression such as a + (b * c). That expression is identical to a + b * c.
Basically, the three examples in your question all define a function that takes no parameters and returns a closure that takes no parameters and returns an Int.
Some more examples to help:
func myFuncA() -> () -> Int -> String {
return { () -> Int -> String in return { (i: Int) -> String in String(i) } }
}
func myFuncB() -> () -> (Int -> String) {
return { () -> Int -> String in return { (i: Int) -> String in String(i) } }
}
func myFuncC() -> (() -> Int) -> String {
return { (f: () -> Int) in String(f()) }
}
In the above, myFuncA is identical to myFuncB, and they are both different than myFuncC.
myFuncA (and B) takes no parameters, and returns a closure. The closure it returns takes no parameters and returns another closure. This second closure takes an Int and returns a String.
myFuncC takes no parameters and returns a closure. The closure it returns takes a closure as a parameter and returns a String. The second closure takes no parameters and returns an Int.
Hopefully, writing it in Prose hasn't made it even more confusing.

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.

Swift: why 'subscript(var digitIndex: Int) -> Int' is a valid function signature?

This piece of code comes from Swift documentation https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html
extension Int {
subscript(var digitIndex: Int) -> Int {
var decimalBase = 1
while digitIndex > 0 {
decimalBase *= 10
--digitIndex
}
return (self / decimalBase) % 10
}
}
Apparently var is a reserved word, so why it is legal to declare: subscript(var digitIndex: Int) -> Int?
If I change the signature to subscript(#digitIndex: Int) -> Int, I will get this compiler error:
My questions are:
1) why the signature is valid?
2) why my change causes an exception?
Declaring a function argument with var means that it can be modified, is not a constant. In your case, without using var, you had a constant argument but you attempted to decrement it. Thus the error.
Your two cases are:
func foo (x: int) { /* x is a constant, like `let x: int` */ }
func foo (var x: int) { /* x is not a constant */ }