neerav512
(Neerav Kothari)
1
I've a variable which is a function type. Now, in an other function I want to set a parameter as a function type. Instead of mentioning its (the parameter function's) parameter type and return type, I simple want to set the variable as a parameter type. why doesn't this work?
In playgrounds I get an error saying 'cannot find the function in scope'.
Basically what I'm saying is to use the new variable as a type for the parameter instead of the original functions definition (parameter and return type).
Thanks
Neerav
eskimo
(Quinn “The Eskimo!”)
2
Can you post some code snippets that illustrate this problem?
Make sure to use a code block (triple backquotes) so that the code is easy to read.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
tera
3
Yep, an example of what you want would make your question clearer.
I guess you are asking (to simplify) why do we need to write ": Bool" type declaration explicitly below:
func proc(v: Bool = true) {...}
instead of just:
func proc(v = true) {...}
although I am not sure I've interpreted your question right.
neerav512
(Neerav Kothari)
4
You have not interpreted my question right, yet, you might have solved my query. Allow me to explain...
I think the reason we need to write...
func proc(function: ()->void) { /*do something*/}
instead of
func f1() { /*do something*/ }
var f2 = f1
func proc(function: f2) { /*do something*/ }
is that the parameter function in proc sould be able to accept any function of the type () -> void and not just f1 ??
That brings us to the question, can we write (a function type as default parameter)...
func f1() { print("hello f1") }
var f2 = f1
func proc(function: () = f2()) {function}
this didn't print anything in the playground console!
tera
6
You probably want this:
func f1() { print("hello f1") }
var f2 = f1
func proc1(function: () -> Void = f1) { function() }
func proc2(function: () -> Void = f2) { function() }
Note, you still can't write just:
func proc1(function = f1) { function() }
for the same reason you can't omit ": Bool" in my example (whatever that reason is).
neerav512
(Neerav Kothari)
7
I forgot to make a call to proc()
Now, its working fine.
So basically we want the function as a default parameter and it works!
here's the code...
func f1() { print("hello f1") }
var f2 = f1
func proc(function: () = f2()) {function}
proc()
output..
hello f1
tera
8
It works but not the way you think it does :-)
Change "{function}" to "{}" it see what I mean – it'd still print that. You are not calling "function" when write it without "()". The proper type signature for a function taking no parameters and returning nothing is
() -> Void
Note that you can't omit the "-> Void" part here even if you could do it when declaring a function:
func foo() -> Void
func foo() // same
By having a default parameter the way you wrote it:
func proc(function: () = f2())
you are saying that your parameter is of type "()" (aka Void) and that it's default value is a callout to a function "f2()" – that's that callout that leads to printing the output string. The way you wrote it you can't do anything useful with the passed parameter, it's a value of type Void – no way to call it, etc.
neerav512
(Neerav Kothari)
9
I'm not sure I fully understand you. Can you elaborate the last part. I actually tried it in Playgrounds and it worked. I copied the code and the output from there.
Are you saying I should write ()->void and not just () to be sure I'm telling the compiler that the parameter function is a function type and not a void type?
Also, while experimenting more with it, I tried this and it works...
func f1(toPrint string: String) { print(string) }
var f2 = f1
func proc(function: (String) -> () = f1(toPrint:)) {
function("function as default parameter")
}
proc()
Output...
function as default parameter
tera
10
Yes!
Note that when you have "()" as a parameter type (instead of a proper "() -> Void") you can't pass a variable of a function type:
func proc(function: () = f2) // 🛑 compilation error
which hints you to correct mistake:
func proc(function: () -> Void = f2) // ✅
This is better. Note that you are writing return type of the function parameter (the "-> ()") part. It's same as "-> Void" and you could use both forms interchangeably. Also note that compiler would permit:
func proc(function: (String) -> () = f1)
in this case as there is no ambiguity which f1 to use.
neerav512
(Neerav Kothari)
11
I retested this and its working fine...
func f1() { print("hello") }
var f2 = f1
func proc(function: () = f2()) {
function
}
proc()
Output
hello
You can check it in playgrounds...

tera
12
This is the wrong way that accidentally leads you to the wanted result. Remove "function" from the body - the behaviour will be the same. Or add a few more "function; function; function" in the body - you'll still have just one "hello" in the output. You are not using "function" in the body sensibly. Let me write the equivalent of your fragment with a slight modified function that returns Int (hopefully would be easier to see):
func f1() -> Int { print("hello"); return 42 }
var f2 = f1
func proc(function: Int = f2()) { function }
proc() // outputs one "hello"
func proc(function: Int = f2()) { 42 }
proc() // still outputs one "hello"
func proc(function: Int = f2()) { /* nothing in the body */ }
proc() // still outputs one "hello"
func proc(function: Int = f2()) { function; function; function }
proc() // still outputs one "hello"
func proc(function: Int = f2()) { function() } // 🛑 compilation error: not a function
proc(f2) // 🛑 compilation error, not an Int
1 Like
neerav512
(Neerav Kothari)
13
Got it!
I tried this and what you said was right...
func f1() { print("hello") }
var f2 = f1
func proc(function: () = f2()) {
print(function)
}
proc()
So, here (function: () = f2()) first evaluates f2() as a call, which prints hello and then assigns the value Void OR () to the parameter function; then prints (), right?
And this just prints hello...
func f1() { print("hello") }
var f2 = f1
func proc(function: ()->() = f2) {
function()
}
proc()
tera
14
Right.
When unfamiliar with something I find it helpful to consider a different less confusing example:
() -> () // 🤔
(String) -> Int // 💡
e.g. coming from a different language you may assume that f and f() are the same (IIRC some languages allow omitting empty brackets and still call a function), but you won't assume that f and f(parameter) is the same (as parameter is obviously required).
print(foo())
print(foo) // 🤔 I came from language X, does this still call a function in Swift?
print(bar("hello"))
print(bar) // 💡I came from language X, but this can't possibly call a function with a parameter in Swift
// unless that parameter has a default value, but let's not complicate things at this point.
There are a few potentially confusing points to Swift newcomers in this area:
- In here:
() -> ()
"Void" could be used to substitute the second "()" but not the first
- While you can omit
"-> Void" or, equally "-> ()" when declaring a function:
func foo() -> Void {}
func foo() -> () {} // the same
func foo() {} // the same
you can't do it when declaring a type:
var x: () -> Void
var y: () // not the same!
- Uniquely to
() it could mean both the type and the value (there is nothing else like this in Swift):
var y: () = ()
var x: ((), ()) = ((), ())
-
Tuples have similar syntax as function parameters.
-
On top of everything you could enclose expression in () without changing of their meaning.
0
(0) // same
((0)) // same
If we could go back and time we could've change swift to at least not use () as a substitute for Void and void constants. Too late now.
Some highly confusing declarations for you (valid Swift):
var x: () -> () -> () -> ()
var y: ((()), ((()))) -> ((())) -> ((())) -> (((())))
1 Like
neerav512
(Neerav Kothari)
15
var x: () -> () -> () -> ()
var y: ((()), ((()))) -> ((())) -> ((())) -> (((())))
Can tou explain this please? 
bbrk24
16
x is a function that, when called, returns another function, that in turn returns another function. x is () -> () -> () -> Void; x() is () -> () -> Void; x()() is () -> Void.
y has a lot more parentheses than it needs, and is really (Void, Void) -> () -> () -> Void. This is a chained function in the same way that x is, but the first call has to be y((),()) rather than just y().