views:

191

answers:

6

Ok, so it is possible to pass a function to another function. http://stackoverflow.com/questions/148982/passing-a-function-to-another-function-in-actionscript-3

This is obviously very powerful, but a more important question is, when would it make sense to do so, as there are performance overheads whenever you call another function?

+1  A: 

1 example is a javascript AJAX call

namespace.class.method(parm1, parm2, callback,onErr);

The method will run asynchrously on the server, and once it is complete it will run the callBack method which is passed

function callback(result) {
      $('#myDiv').innerHTML = result;
}

There are a host of other examples, just look at event handling as an example.

Paul Creasey
+3  A: 

A function that takes a function as its argument is called a higher-order function. Google has a lot of information on these.

Examples of higher-order functions:

function compose(f, g) {
  return function(x) {
    return f(g(x));
  };
}

function map(f, xs) {
  var ys = [];
  for(var i = 0; i < xs.length; ++i)
    ys.push(f(xs[i]));
  return ys;
}

With that, you can transform an array with two functions in a row:

var a = ["one", "two", "three"];
var b = map(compose(toUpperCase, reverse), a);
// b is now ["ENO", "OWT", "EERHT"]
Apocalisp
+4  A: 

If you have much actionscript knowledge you probably use one example of this all the time without even noticing.

The addEventListener of the EventDispatcher class actually requires a function be passed into it when it's called:

addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

http://livedocs.adobe.com/flex/3/langref/flash/events/EventDispatcher.html

Passing functions around is used a hell of a lot for callbacks. There are numerous other uses but this highlights one of the more simple scenarios.

James Hay
+4  A: 

The performance overhead is no worse than calling a virtual method in any contemporary OO language.

It makes sense to pass procedures to other procedures when it makes your code smaller. Less code has fewer bugs and is easier to maintain. Here's an example. These are two functions that respectively sum a list of numbers and multiple a list of numbers.

  (define sum
    (lambda (ls)
      (if (null? ls)
          0
          (+ (car ls) (sum (cdr ls))))))

  (define product
    (lambda (ls)
      (if (null? ls)
          1
          (* (car ls) (product (cdr ls))))))

They're identical except the operators + and - and the corresponding identity value (0 and 1). We've unfortunately duplicated a lot of code.

We can reduce complexity by abstracting the operator and the identity. The rewritten code looks like this.

  (define fold
    (lambda (proc id)
      (lambda (ls)
        (if (null? ls)
            id
            (proc (car ls) (fold (cdr ls) proc id))))))

  (define sum (fold + 0))
  (define product (fold * 1))

It's easier now to see the essential difference between sum and product. Also, improvements to the core code only have to be made in one place. Procedural abstraction is a fabulous tool, and it depends on being able to pass procedures to other procedures.

Mike Ashley
+1  A: 

Another reason to pass a function to a function is if you want the receiving function to be flexible in the work that it does, for instance I had a recursive function that would process a directory tree, on each directory it would call the supplied function and pass it the current directory. This way I could use the same structure to scan a directory, copy a directory or delete a directory. And the "work" function just had to be complicated enough to process one directory not a tree. This is mostly with procedural programming with OO there are preferred ways to do this, inheritance, delegates, etc.

Ken Lange
A: 

Another very common example is sorting where you pass a predicate i.e. how to sort e.g.

(sort > list-to-sort)

Here > is the function to apply whilst sorting. This is a very simple example using greater than so your list must be numeric but it could be anything e.g.

(sort (lambda(a b) (> (string-length a) (string-length b))) list-to-sort)

Here a closure is passed that does a greater than comparison on string lengths so assumes the list contains strings.

These types of things just suck in languages without closures or HOFs because of all the object/interface/type nonsense that is required to acheive the same.

Andrew