We've been in the process of changing how our AS3 application talks to our back end and we're in the process of implementing a REST system to replace our old one.

Sadly the developer who started the work is now on long term sick leave and it's been handed over to me. I've been working with it for the past week or so now and I understand the system, but there's one thing that's been worrying me. There seems to be a lot of passing of functions into functions. For example our class that makes the call to our servers takes in a function that it will then call and pass an object to when the process is complete and errors have been handled etc.

It's giving me that "bad feeling" where I feel like it's horrible practice and I can think of some reasons why but I want some confirmation before I propose a re-work to system. I was wondering if anyone had any experience with this possible problem?

  • 23
    Why do you feel like that? Do you have any experience with functional programming? (I'll assume not, but you should take a look) – Phoshi Aug 20 '14 at 9:48
  • 8
    Then consider this a lesson! What academia teaches and what is actually useful often have surprisingly little overlap. There's a whole world of programming techniques out there that don't conform to that sort of dogma. – Phoshi Aug 20 '14 at 11:18
  • 34
    Passing functions to other functions is such a fundamental concept that when a language doesn't support it, people will go out of their way to create trivial "objects" whose sole purpose is to contain the function in question as a stopgap. – Doval Aug 20 '14 at 11:28
  • 38
    Back in my day we called these pass through functions "Callbacks" – Mike Aug 20 '14 at 14:29
  • 11
    @BlueHat read this en.wikipedia.org/wiki/Callback_(computer_programming) – Mike Aug 20 '14 at 14:29

It isn't a problem.

It is a known technique. These are higher order functions (functions that take functions as parameters).

This kind of function is also a basic building block in functional programming and is used extensively in functional languages such as Haskell.

Such functions are not bad or good - if you have never encountered the notion and technique they can be difficult to grasp at first, but they can be very powerful and are a good tool to have in your toolbelt.

  • Thanks for that, I've no real experience with functional programming so I'll look into it. It just didn't sit well because from my little knowledge, when you declare something as a private function then only that class should have access to it and public ones should be called with reference to the object. I'll take a look into it properly and I expect I'll come appreciate it a bit more! – Elliot Blackburn Aug 20 '14 at 9:53
  • 3
    Reading about continuations, continuation passing style, monads (functional programming) should also be useful. – Basile Starynkevitch Aug 20 '14 at 9:58
  • 8
    @BlueHat you declare something to be private if you want control over how it is used, if that use is as a callback for specific functions then that is fine – ratchet freak Aug 20 '14 at 10:00
  • 5
    Exactly. Marking it private means you don't want someone else coming in and accessing it by name any time they like. Passing a private function to someone else because you specifically want them to call it in the way they document for that parameter, is absolutely fine. It need not be any different from passing the value of a private field as a parameter to some other function, which presumably doesn't sit badly with you :-) – Steve Jessop Aug 21 '14 at 1:54
  • 2
    Worth noting that if you find yourself writing concrete classes with functions as constructor parameters you are probably doing it wrong tm. – Gusdor Aug 21 '14 at 7:24

They're not just used for functional programming. They can also be known as callbacks:

A callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time. The invocation may be immediate as in a synchronous callback or it might happen at later time, as in an asynchronous callback.

Think about asynchronous code for a second. You pass in a function that, for example, sends data to the user. Only when the code has completed do you invoke this function with the result of the response, which the function then uses to send the data back to the user. It's a mindset change.

I wrote a library that retrieves Torrent data from your seedbox. You are using a non-blocking event loop to execute this library and get data, then return it to the user (say, in a websocket context). Imagine you have 5 people connected in this event loop, and one of the requests to get someone's torrent data stalls. That will block the whole loop. So you need to think asynchronously and use callbacks - the loop keeps running and the "giving the data back to the user" only runs when the function has finished execution, so there's no waiting for it. Fire and forget.

  • 2
    +1 For using the callback terminology. I encounter this term much more often than "higher order functions". – Rodney Schuler Aug 21 '14 at 14:41
  • I like this answer, because the OP seemed to be describing callbacks, specifically, and not just higher order functions in general: "For example our class that makes the call to our servers takes in a function that it will then call and pass an object to when the process is complete and errors have been handled etc." – Ajedi32 Aug 21 '14 at 15:48
  • Protocols are better than callbacks. Protocols support long-term assumptions over a single interaction "surface" between two or more objects. Think like if you have two abstract interfaces looking toward each other. A bidirectional polymorphism. I haven't heard about a good implementation of protocols. For me, experienced for more than 25 years in many languages, this "higher-order functions" are the same as "goto". Harmful. – Brian Cannard Nov 8 '20 at 5:03

This is not a bad thing. In fact, it is a very good thing.

Passing functions into functions is so important to programming that we invented lambda functions as a shorthand. For example, one may use lambdas with C++ algorithms to write very compact yet expressive code that allows a generic algorithm the ability to use local variables and other state to do things like searching and sorting.

Object-oriented libraries may also have callbacks which are essentially interfaces specifying a small number of functions (ideally one, but not always). One can then create a simple class that implements that interface and pass an object of that class through to a function. That is a cornerstone of event-driven programming, where framework-level code (perhaps even in another thread) needs to call into an object to change state in response to a user action. Java's ActionListener interface is a good example of this.

Technically, a C++ functor is also a type of callback object which leverages syntactic sugar, operator()(), to do the same thing.

Finally, there are C-style function pointers which should only be used in C. I will not go into detail, I just mention them for completeness. The other abstractions mentioned above are far superior and should be used in languages that have them.

Others have mentioned functional programming and how passing functions is very natural in those languages. Lambdas and callbacks are the way procedural and OOP languages mimic that, and they are very powerful and useful.

  • Also, in C# delegates and lambdas are both used extensively. – Evil Dog Pie Aug 21 '14 at 15:37

As already said, it isn't bad practice. It is merely a way of decoupling and separating responsibility. For example, in OOP you would do something like this:

public void doSomethingGeneric(ISpecifier specifier) {
    //do generic stuff
    //do some other generic stuff

The generic method is delegating a specific task - which it knows nothing about - to another object that implements an interface. The generic method only knows this interface. In your case, this interface would be a function to be called.

  • 1
    This idiom is simply wrapping the function in an interface, accomplishing something very similar to passing a raw function in. – user22815 Aug 21 '14 at 4:37
  • Yes it is, I just wanted to show that this isn't an uncommon practice. – Philipp Murry Aug 21 '14 at 6:34

In general, there's nothing wrong with passing functions to other functions. If you're making asynchronous calls and want to do something with the result, then you'd need some sort of callback mechanism.

There are a few potential drawbacks of simple callbacks though:

  • Making a series of calls can require deep nesting of callbacks.
  • Error handling can need repetition for each call in a sequence of calls.
  • Coordinating multiple calls is awkward, like making multiple calls at the same time and then doing something once they are all finished.
  • There's no general way of cancelling a set of calls.

With simple webservices the way you're doing it works fine, but it becomes awkward if you need more complex sequencing of calls. There are some alternatives though. With JavaScript for example, there's been a shift towards the use of promises (What's so great about javascript promises).

They still involve passing functions to other functions but asynchronous calls return a value that takes a callback rather than take a callback directly themselves. This gives more flexibility for composing these calls together. Something like this can be implemented fairly easily in ActionScript.

  • I would also add that unnecessary use of callbacks can make it harder to follow the flow of execution for anyone reading the code. An explicit call is easier to understand than a callback that was set in a distant part of the code. (Breakpoints to the rescue!) Nonetheless, this is how events fire in the browser and other event-based systems; then we need to understand the event emitter's strategy to know when and in what order event handlers will be called. – joeytwiddle Aug 22 '14 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.