Accessing number of parameters in a closure in Swift - swift

Suppose I have a function:
func test(closure: (closureArgs: Double ...) -> Double){
//some logic
}
Then later, I call it with:
test({$0 + $1 + $2 + $3})
Is it possible to get the number of closureArgs provided within test? The goal would be to do overloading. For example, test could include some code like:
func test(closure: (closureArgs: Double ...) -> Double){
//somehow get access to number of arguments in closureArgs within the closure that was passed.
}
To clarify - I mean I need to access closureArgs's length INSIDE test but OUTSIDE closure

Is it possible to get the number of closureArgs provided within test?
The Short Answer
No.
Slightly Longer Answer
No, it is not. Here's why:
The function is taking a closure as it's argument that by definition takes a variadic number of arguments. There's no possible way for someone calling the function to designate how many arguments the closure should take ahead of time. For example, if I were to call your function, it might look like this:
test() { (closureArgs: Double...) -> Double in
var n: Double = 0
for i in closureArgs {
n += i
}
return n
}
As you'll notice, I don't define the number of arguments anywhere because the number of arguments is only specified when the closure is called. Then the number can be determined inside, or possibly returned.
Basically, the closure is called within test, so only you the caller know how many arguments it takes. Anyone consuming this function has no control over it.

The only way I can think of is to have the closure return a tuple that contains the number of arguments and a function that gives the answer, like this:
func test(c: (Double...) -> (Int, (Double...) -> Double)) {
let (argCount, function): (Int, (Double...) -> Double) = { c($0) }()
switch argCount {
// do something with function here
}
}
func sum(a: Double...) -> (Int, ((Double...) -> Double)) {
return (a.count, { reduce(a, 0, +) })
}
Something like that might work, but I'm not in a place where I can test it.
Edit: I'm trying to test this now, and it's close, but it doesn't work yet...
Edit: Okay, this works, but maybe not in the way that you want...
func test(c: (Int, Double)) {
let (argCount, result) = c
switch argCount {
case 2:
println("2 args were passed")
println("The result was \(result)")
default:
println("nothing")
}
}
func sum(a: Double...) -> (Int, Double) {
return (a.count, reduce(a, 0, +))
}
Now test(sum(2, 4)) will print that the number of arguments was 2 and the result was 6.
The thing is, when you are passing a closure that already has arguments supplied (and it needs arguments to know how to calculate the count) then you're closure function already evaluates to a result. So have the closure return the number of arguments that it used to calculate the result along with the result. Then in test you can work with both the number of arguments and the result.
I don't know...it's hard to know exactly what you are after because I'm not sure what kind of logic you need to implement once you know the number of arguments...
Edit: Sorry I keep going on and on, but it seems like you know how many arguments are going to be included when you call test, right? I mean, in your example you supplied 4 arguments:
test({$0 + $1 + $2 + $3})
(Although, you really need to rewrite that as:
test({ return $0[0] + $0[1] + $0[2] + $0[3] })
...cuz remember, variadic parameters are passed as an array...)
So if you know how many arguments are going to be in the closure when you pass it to test, just include the number of arguments as a parameter in test, like this:
func test(count: Int, closure: (Double...) -> Double) {
switch count {
case 1:
// do what you want if there is only one argument
case 2:
// do what you want if there are two arguments...etc.
}
}
Now when you call test, you just pass the number of arguments as an Int:
test(4, { return $0[0] + $0[1] + $0[2] + $0[3] })
In other words, you always know how many arguments you are passing to the closure when you pass it. If you want test to know, just include that as a parameter.

The answer goes back to how Swift passes arguments to varargs functions, which is as an array. Generally speaking, the function definition:
func takesVarArgs(args: Double...)
Is syntactic sugar, providing for simpler invocation, for the declaration:
func takesVarArgs(args:[Double])
So, in your case, your closure will be invoked as:
func test(closure: (closureArgs:[Double]) -> Double)) -> Double
Then, within your closure you could get the number of arguments with:
closureArgs.count

Related

How does this function call this closure when each returns just a single Int?

I find this code very confusing:
let myClosure = { (number1: Int, number2: Int) -> Int in
return number1 * number2
}
func useClosure(closure: (Int, Int) -> Int) {
let result = closure(2, 3)
print(result) // prints 6
}
useClosure(closure: myClosure)
The func useClosure takes 2 Ints with the parameter name closure which is the closure myClosure but myClosure has only 1 returned Int, so how can it be the parameter of useClosure?
And where is myClosure getting number1 and number2 from? From useClosure?
On the surface, it seems 2 and 3 are being passed to myClosure but it's not clear how that is happening.
It all seems circular to me and makes little sense.
I haven't really tried anything to "resolve" this as it doesn't really need resolution. The code works fine. I'm just struggling to understand it – from where I am in my journey as a developer.
If you look at the declaration of myClosure - or even better, option+click on it - you'll see that its type is (Int, Int) -> Int. Which is exactly the type of the input argument useClosure expects.
That type signature represents a closure, which takes two Ints as input and returns an Int.
The func useClosure takes 2 Ints with the parameter name closure
useClosure takes a closure as its input, not a pair of Ints as you claim.
You are passing the values inside useClosure to the input argument, closure.
When looking at type signatures, everything on the left-hand side of -> represents the input arguments to the function, while everything on its right hand side represents the return type.

Tuple and Function Argument in Swift

In Swift, how is tuple related to function argument?
In the following two examples the function returns the same type even though one takes a tuple while the other takes two arguments. From the caller standpoint (without peeking at the code), there is no difference whether the function takes a tuple or regular arguments.
Is function argument related to tuple in some ways?
e.g.
func testFunctionUsingTuple()->(Int, String)->Void {
func t(x:(Int, String)) {
print("\(x.0) \(x.1)")
}
return t
}
func testFuncUsingArgs()->(Int, String)->Void {
func t(x:Int, y:String) {
print("\(x) \(y)")
}
return t
}
do {
var t = testFunctionUsingTuple()
t(1, "test")
}
do {
var t = testFuncUsingArgs()
t(1, "test")
}
There is also inconsistencies in behavior when declaring tuple in function argument in a regular function (rather than a returned function):
func funcUsingTuple(x:(Int, String)) {
print("\(x.0) \(x.1)")
}
func funcUsingArgs(x:Int, _ y:String) {
print("\(x) \(y)")
}
// No longer works, need to call funcUsingTuple((1, "test")) instead
funcUsingTuple(1, "test")
funcUsingArgs(1, "test3")
UPDATED:
Chris Lattner's clarification on tuple:
"x.0” where x is a scalar value produces that scalar value, due to odd
behavior involving excessive implicit conversions between scalars and
tuples. This is a bug to be fixed.
In "let x = (y)”, x and y have the same type, because (x) is the
syntax for a parenthesis (i.e., grouping) operator, not a tuple
formation operator. There is no such thing as a single-element
unlabeled tuple value.
In "(foo: 42)” - which is most commonly seen in argument lists -
you’re producing a single element tuple with a label for the element.
The compiler is currently trying hard to eliminate them and demote
them to scalars, but does so inconsistently (which is also a bug).
That said, single-element labeled tuples are a thing.
Every function takes exactly one tuple containing the function's arguments. This includes functions with no arguments which take () - the empty tuple - as its one argument.
Here is how the Swift compiler translates various paren forms into internal representations:
() -> Void
(x) -> x
(x, ...) -> [Tuple x ...]
and, if there was a tuple? function, it would return true on: Void, X, [Tuple x ...].
And here is your proof:
let t0 : () = ()
t0.0 // error
let t1 : (Int) = (100)
t1.0 -> 100
t1.1 // error
let t2 : (Int, Int) = (100, 200)
t2.0 -> 100
t2.1 -> 200
t2.2 // error
[Boldly stated w/o a Swift interpreter accessible at the moment.]
From AirSpeedVelocity
But wait, you ask, what if I pass something other than a tuple in?
Well, I answer (in a deeply philosophical tone), what really is a
variable if not a tuple of one element? Every variable in Swift is a
1-tuple. In fact, every non-tuple variable has a .0 property that is
the value of that variable.4 Open up a playground and try it. So if
you pass in a non-tuple variable into TupleCollectionView, it’s legit
for it to act like a collection of one. If you’re unconvinced, read
that justification again in the voice of someone who sounds really
confident.
Remember the 'philosophical tone' as we've reached the 'I say potato; your say potato' phase.
A function in Swift takes a tuple as parameter, which can contain zero or more values. A parameterless function takes a tuple with no value, a function with one parameter takes a tuple with 1 value, etc.
You can invoke a function by passing parameters individually, or by grouping them into an immutable tuple. For example, all these invocations are equivalent:
do {
let t1 = testFunctionUsingTuple()
let t2 = testFuncUsingArgs()
let params = (1, "tuple test")
t1(params)
t1(2, "test")
t2(params)
t2(3, "test")
}

Translating Swift Into English

I'm attempting to teach myself to code in Swift but I'm having a difficult time translating what I'm reading into something that resembles English. Here's an example:
func createAdder(numberToAdd: Int) -> (Int) -> Int
{
func adder(number: Int) -> Int
{
return numberToAdd + number
}
return adder
}
var addTwo = createAdder(2)
addTwo(4)
How do I read that first line of code and can you explain how this function is executed?
createAdder is a function that returns a function. The placement of the parentheses is a little off-putting - it makes more sense like this:
func createAdder(numberToAdd: Int) -> (Int -> Int)
So it returns a function of type Int -> Int. What does that mean? Take a look at this function:
func addTwo(n: Int) -> Int {
return n + 2
}
That function takes an integer - n - and returns another integer. So the type of the function is:
Int -> Int
In this case, this function just adds two to whatever it was given. But say you wanted to generalise (it doesn't make much sense in this contrived example, but this kind of thing is very powerful in other scenarios). Say you wanted to have a bunch of functions, each of them adding a number to a number they were given. To do that, you'd need to write something like what you've written in your example:
func createAdder(numberToAdd: Int) -> (Int) -> Int
{
func adder(number: Int) -> Int
{
return numberToAdd + number
}
return adder
}
The createAdder function takes a number, and then defines a new function - adder - which it returns.
The final bit that might be confusing is the line
var addTwo = createAdder(2)
Usually, you define functions with the word func. However, that's just syntax. Functions are variables just like every other type in Swift, and they can be treated as such. That's why you're able to return a function, and that's why you're able to assign it using var.
So what does it do? Well, if you call createAdder(2), what you get back is equivalent to
func addTwo(n: Int) -> Int {
return n + 2
}
If you did something like:
var addThree = createAdder(3)
It would be equivalent to:
func addThree(n: Int) -> Int {
return n + 3
}
And in both cases, you'd use them just like normal functions:
addThree(1) // returns 4
So I said the example was a little contrived - and it is - so where would this kind of thing be useful? In general, functions that either take or return functions are called "higher-order" functions. They're massively useful, and if you go down the functional programming route they can get very powerful and a bit philosophical pretty quickly. Keeping it grounded, the first place most people come across them in Swift is with the function .map(). map() is a higher-order function - it takes a function as its parameter. However, it also takes something else - in this example, it's going to be an array. What it does is apply the function it's given to every element of the array. So, let's use the createAdder() to give us a function that adds 1 to a number:
let addOne = createAdder(1)
Right, then let's get an array of other numbers:
let nums = [1, 2, 3, 4]
Then, let's put it all together with map:
let mapped = nums.map(addOne) // [2, 3, 4, 5]
As you can see, that's a pretty powerful way to process and manage arrays. There's a whole host of functions like this - filter(), flatMap(), reduce() - and they all rely on this concept.
It reads: declare a function named "createAdder" that takes an Int as an argument, this function returns a function which itself takes an Int as an argument; and this function itself, what is returned from "createAdder", returns an Int.
-> (Int) -> Int
means "returns a function -taking an Int- which will return an Int".
The first line of code reads:
A function createAdder that takes as an argument a numberToAdd of type Integer and returns a function that receives an Integer as an argument and returns an Integer. In this case, the function that is returned is the adder function that is created within the createAdder.

Running methods inside a block in Swift

This is probably a dumb question, but still... I'm calling a function inside a block like this:
let makeRocks = SKAction.sequence([SKAction.runBlock(self.createMyNode),<---- here should be ()
SKAction.waitForDuration(0.1, withRange: 0.15)])
func createMyNode() {
// blabla
}
I don't get it. There should be parentheses after self.createMyNode but this still compiles. How is that so?
You're not in fact calling the function, createMyNode will be called inside SKAction.runBlock, you're simply passing it as an argument.
Take a look at the type SKAction.runBlock accepts, from the SKAction documentation:
class func runBlock(_ block: dispatch_block_t) -> SKAction
And from the GCD documentation:
typealias dispatch_block_t = () -> Void
Therefore, SKAction.runBlock accepts a function (or closure, they're the same thing), which takes no arguments and returns Void; which is exactly what you're suppling with createMyNode.
With this information it's clear to see why you don't add parentheses after createMyNode - because that would call the function, thus passing Void (the return type of createMyNode) to SKAction.runBlock, which SKAction.runBlock won't accept.
To clarify, here's another example. Say you had the function:
func takesAFunc(c: (Int, Int) -> Int) -> Void {
print(c(1, 2))
}
And you wanted to pass in a function that added the two numbers. You could write:
takesAFunc { num1, num2 in
num1 + num2
}
// Prints: 3
But alternatively, you could just pass in the + operator that accepts Ints - that's a function too. Take a look at the definition:
func +(lhs: Int, rhs: Int) -> Int
That matches the type required by takesAFunc, therefore you can write:
takesAFunc(+) // Prints: 3
runBlock wants a function as parameter which you provide here (so self.createMyNode is only a reference to the function itself).
But you can also wrap the function call in a closure like so:
let makeRocks =
SKAction.sequence([SKAction.runBlock{ self.createMyNode() },
SKAction.waitForDuration(0.1, withRange: 0.15)])

Values accepted in a tuple in swift

I am a completely newbie in swift and in functional Programming.
My silly question is the following:
Can a tuple return a set of functions?
Is it a function like that accepted?
someFunction(param: Bool) -> ((Int) -> Int, (Float) ->Float) -> Double)
Thanks for your reply
You can have a tuple of any type, and functions are types, so you can have tuples of functions.
For example, here’s a 2-tuple of two functions, one that takes two Ints and returns an Int, and one that takes two Doubles and returns a Double:
// a 2-tuple of the addition functions for ints and doubles
let tupleOfFunctions: ((Int,Int)->Int, (Double,Double)->Double) = (+,+)
When you say, “can a tuple return a set of functions?”, I’m guessing you mean, “can a function return a tuple of functions?”. And the answer is also yes:
func returnTwoFunctions(param: Bool) -> ((Int,Int)->Int, (Double,Double)->Double) {
// use the argument to drive whether to return some addition
// or some subtraction functions
return param ? (+,+) : (-,-)
}
Your example, though, is a bit scrambled – if you added a func keyword to the front, it’d be a function declaration, but you’ve got mismatched parentheses. What it looks most like is a function (someFunction) that takes one boolean argument, and returns a function that itself takes two functions and returns a double:
func someFunction(param: Bool) -> (Int->Int, Float->Float) -> Double {
let i = param ? 1 : 2
// this declares and returns a function that itself takes two functions,
// and applies them to pre-determined number
return { f, g in Double(g(Float(f(i)))) }
}
// h is now a function that takes two functions and returns a double
let h = someFunction(false)
// ~ and + are two unary functions that operate on ints and floats
h(~,+) // returns -3.0 (which is +(~2) )
Whether this is what you were intending, and whether you have a use-case for this kind of function, I’m not sure...