10

How can you optionally pass in a function to another function? Concretely, assume functionA accepts as a parameter functionB. If functionB is not nil, how can you execute functionB inside of functionA?

Crashalot
  • 33,605
  • 61
  • 269
  • 439

1 Answers1

17

Hard to see what's hard about this, so maybe this isn't what you mean, as it seems so trivially obvious; but anyway, here goes:

func optionalFunctionExpecter(f:(()->())?) {
    f?()
}

Here's how to call it with an actual function:

func g() {
    println("okay")
}
optionalFunctionExpecter(g)

Or, calling it with an actual anonymous function:

optionalFunctionExpecter { println("okay2") }

Here's how to call it with nil:

optionalFunctionExpecter(nil)

Observe that in my implementation of optionalFunctionExpecter, when called with nil, nothing will happen: we won't call f, we won't crash, we won't do anything. If you need to know that nil was passed, you can readily find out: just ask, in optionalFunctionExpecter, whether f == nil and proceed on that basis as desired. For more flexibility, we could rewrite like this:

func optionalFunctionExpecter(f:(()->())?) {
    if let f = f {
        f()
    } else {
        // ... nil was passed, respond to that fact ...
    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Sorry for the confusion. What if someone passes nil into optionalFunctionExpecter? In other words, sometimes a function will get passed, and other times, no function gets passed. Doesn't "f?()" throw an exception if the function is nil? – Crashalot May 01 '15 at 05:31
  • 1
    No – `f?()` is optional chaining (in a similar fashion to `maybeObj?.property` or `maybeArray?[0]`. If will check if `f` is `nil`, and if not, execute it. The return value will be wrapped in an optional, and be `nil` if `f` was `nil` and not executed. – Airspeed Velocity May 01 '15 at 05:40
  • 1
    @Crashalot check out http://stackoverflow.com/a/29717211/3925941 for a long list of optional-handling techniques – Airspeed Velocity May 01 '15 at 05:46
  • @Crashalot added an alternative implementation that lets you respond consciously to nil being passed in, if desired – matt May 01 '15 at 16:05
  • @matt, thanks so much! do you happen to be familiar with spritekit btw? – Crashalot May 01 '15 at 18:22
  • May I ask, where do I find this in the Swift documentation? It may seem trivial, but to someone learning the language, it might not be! =] – Relequestual Feb 02 '16 at 08:30
  • @Relequestual "where do I find this" What is "this"? What part is hard or surprising? Functions as parameters? Optionals? Give me some idea what you need to know. – matt Feb 02 '16 at 13:23
  • @matt You said "Hard to see what's hard about this..." so I'm realting to the same "this". The subject of this question this. More specifically however, where do I find `(f:(()->())?)` explained in the documentation, or how did you gleam such from which documentation? – Relequestual Feb 02 '16 at 14:20
  • @Relequestual I'm happy to help if you will be specific. Which part of `f:(()->())?` do you need explanation for? – matt Feb 03 '16 at 02:09
  • Thanks @matt. I understand what the `f:` part does, but I'm not sure on my understanding on the rest. Is it saying, this function should take a function which returns a function? if that is the case, and I'm reading it right, where do I find this in the Swift documentation? – Relequestual Feb 03 '16 at 13:41
  • 1
    @Relequestual it says that the parameter `f` is a function taking no parameters and returning no value, wrapped up in an Optional — which is what the OP asked for. Here's the discussion of functions as parameters from my book: http://www.apeth.com/swiftBook/ch02.html#_function_as_value – matt Feb 03 '16 at 20:40
  • Awesome thankyou! I'll be sure to check out your book! =] – Relequestual Feb 03 '16 at 22:55