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")
}
Related
In swift, is it possible to have a function accepting another function of the same type as itself?
For example, I have this function in python:
lambda f: f(f)
How can I define a function like this in swift? And what will the type of f be?
From you question it sounds as if you're looking for a way to define the self-application combinator (/U combinator). I'm not certain it's possible to implement a U combinator behaviour in Swift, but you could, however, dwell down into the related fix-point combinator (/Y combinator) and recursive closures.
You can achieve the behaviour of the Y combinator by defining a function that takes a function to function higher order function as parameter, say f: (T->U) -> (T->U), and returns the same type of function, i.e. (T->U). Using this approach, your function can take functions such as result from itself as an argument.
The short version is that the Y combinator computes the fixed point of
a functional -- a function that consumes (and in this case, produces)
another function.
The trick is to define recursive functions as the fixed points of
non-recursive functions, and then to write a fixed-point finder -- the
Y combinator -- without using recursion.
From http://matt.might.net/articles/js-church/.
Now, since you return a function, your return will be "nested" in two steps; the outer defining the return of the closure, and the inner the return of the type. The key is the inner, recursive, return; where you call the input (parameter) function itself without explicitly using its name: you make use of the function parameter which is---as described above---constructed as a closure type that can hold the functions itself.
func myCombinator<T,U>(f: (T->U) -> (T->U)) -> (T->U) {
return {
(x: T) -> U in
return f(myCombinator(f))(x)
}
}
Using this function, you can, e.g., calculate factorial of a number without the functions explicitly referring to their own name
func factorialHelper(recursion: Int -> Int)(n: Int) -> Int {
switch n {
case 0: return 1
default: return n * recursion(n-1)
}
}
let factorial = myCombinator(factorialHelper)
print("\(factorial(4))") // 24
For reference on the Y combinator and recursive closures in the context of Swift, see e.g.
https://xiliangchen.wordpress.com/2014/08/04/recursive-closure-and-y-combinator-in-swift/
https://gist.github.com/kongtomorrow/e95bea13162ca0e29d4b
http://rosettacode.org/wiki/Y_combinator#Swift
It's the second reference above from which the example in this answer is taken.
Returning shortly to the U combinator, there is one simple "native" swift case (however, quite useless) that at least simulates the form lambda f: f(f).
Consider a void function, say f, taking an empty tuple type as single function parameter. The empty tuple () is a type (typealias Void refers to type ()) as well as the single value of that type. Since f is void (no explicit return) it implicitly returns an empty tuple () as a value.
Hence---although not really related to the U combinator---you could write something like
func f(_: ()) { }
var lambda_f = f(f())
lambda_f = f(f(f()))
Question:
Are there any possible explicit uses for the empty tuple (), as a value (and not as a type) in Swift 2.x?
I know that these empty tuples can be used in the standard sense to define void functions. When I mistakenly defined a variable with a empty tuple value var a = () (of type ()), I started wondering if these empty tuple values can be used in some context. Does anyone know of such an application?
Example: possible application with array and optionals?
As an example, we can create an optional array of empty tuples that, naturally, can only hold either nil or ():
/* Optionals */
var foo: ()? = ()
print(foo.dynamicType) // Optional<()>
var arr : [()?] = [foo]
for i in 2...8 {
if i%2 == 0 {
arr.append(nil)
}
else {
arr.append(foo)
}
}
print(arr) // [Optional(()), nil, Optional(()), ... ]
With the small memory footprint of empty tuple, this could seem neat for micro-memory-management for a "boolean nil/not nil", but since type Bool have the same small footprint, I can't really see any direct use here, even in the (unlike) scenario that we really need to go bit-low optimization on our operations.
Perhaps I'm just chasing my own tail with some narrow unusable applications, but anyway: are there any possible explicit uses for these void () beings (as instances, not types)?
There are lots of places that () can be useful when playing around with "CS" problems, which often have the form "implement X using Y even though you really already have X." So for instance, I might say, implement Set using Dictionary. Well, a Dictionary is a Key/Value pair. What should the type of the Value be? I've actually seen this done in languages that have Dictionaries but not Sets, and people often use 1 or true as the value. But that's not really what you mean. That opens up ambiguity. What if the value is false? Is it in the set or not? The right way to implement Set in terms of Dictionary is as [Key: ()], and then you wind up with lines of code like:
set[key] = ()
There are other, equivalent versions, like your Optional<()>. I could also implement integers as [()] or Set<()>. It's a bit silly, but I've done things like that to explore number theory before.
That said, these are all almost intentionally impractical solutions. How about a practical one? Those usually show up when in generic programming. For example, imagine a function with this kind of form:
func doThingAndReturn<T>(retval: T, f: () -> Void) -> T {
f()
return retval
}
This isn't as silly as it sounds. Something along these lines could easily show up in a Command pattern. But what if there's no retval; I don't care about the return? Well, that's fine, just pass a () value.
func doThing(f: () -> Void) {
doThingAndReturn((), f: f)
}
Similarly, you might want a function like zipMap:
func zipMap<T, U>(funcs: [(T) -> U], vals: [T]) -> [U] {
return zip(funcs, vals).map { $0($1) }
}
This applies a series of functions that take T to values of type T. We could use that even if T happens to (), but we'd have to generate a bunch of () values to make that work. For example:
func gen<T>(funcs: [() -> T]) -> [T] {
return zipMap(funcs, vals: Array(count: funcs.count, repeatedValue: ()))
}
I wouldn't expect this to come up very often in Swift because Swift is mostly an imperative language and hides its Void in almost all cases. But you really do see things like this show up in functional languages like Scala when they bridge over into imperative programming.
Suppose you have two functions overloading the same name:
func foo()
func foo() -> Int
The first doesn't return anything, the second returns some kind of value. Attempting to call either of these will in most cases get you a compiler error about ambiguity.
foo()
let a = foo()
You'd think that the compiler would know that the first call unambiguously refers to the first function, because it assumes no return value. But in actuality, the return type of a function with no declared return type is Void, or (). So the first call is actually more like this:
let _ = foo()
And absent a type annotation for the discarded lvalue, the compiler can't infer which foo to call. You can use explicit type annotations to disambiguate:
let b: Void = foo()
let c: Int = foo()
Okay, it's not a very great or common use case for Void, because it's a situation you'd tend to avoid getting into in the first place. But you asked for a use... and it is a use of () as a value and not just a type, because you can retrieve it from b after assignment (for all the good that does you).
Just beware, when you look deeply into the Void, the Void also looks into you. Or something like that.
In Swift Programming Language Guide, under Function Type section, it says “Because the parameter type and the return type can be a tuple type, function types support functions and methods that take multiple parameters and return multiple values.”
Note the use of word "can be" - does it mean parameter type can be something else as well? Or parameter type has to be tuple only?
you can either call a function with tuples OR with arguments
e.g.
func sum(a: Int, b: Int) -> Int {
return a + b
}
you could call this:
let numbers = (40,2)
sum(numbers)
or the old way like
sum(40,2)
A tuple means a set of parameters instead of "single" parameters.
The default way means one value per parameter like this:
func setValue( myValue:Int ) { ... }
setValue( 3 )
On the other hand a tuple can be more than one parameter:
func setValues( myValues:(Int,String) ) { ... }
setValues( (1, "Hello") )
So tuples are possible, but the common way is to use only single values
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...
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