views:

1197

answers:

4

Jamie Zawinski uses that term in his (now ten years old) article "java sucks" as if you should know what it means:

I really hate the lack of downward-funargs; anonymous classes are a lame substitute. (I can live without long-lived closures, but I find lack of function pointers a huge pain.)

It seems to be Lisper's slang, and I could find the following brief definition here, but somehow, I think I still don't get it:

Many closures are used only during the extent of the bindings they refer to; these are known as "downward funargs" in Lisp parlance.

Were it not for Steve Yegge, I'd just feel stupid now, but it seems, it might be OK to ask:

Jamie Zawinski is a hero. A living legend. [...] A guy who can use the term "downward funargs" and then glare at you just daring you to ask him to explain it, you cretin.

-- XEmacs is dead, long live XEmacs

So is there a Lisper here who can compile this for C-style-programmers like me?

+7  A: 

There's a pretty descriptive article on Wiki called Funarg problem

"A downwards funarg may also refer to a function's state when that function is not actually executing. However, because, by definition, the existence of a downwards funarg is contained in the execution of the function that creates it, the activation record for the function can usually still be stored on the stack."

Ólafur Waage
+22  A: 

Downward funargs are local functions that are not returned or otherwise leave their declaration scope. They only can be passed downwards to other functions from the current scope.

Two examples. This is a downward funarg:

function () {
    var a = 42;
    var f = function () { return a + 1; }
    foo(f); // `foo` is a function declared somewhere else.
}

While this is not:

function () {
    var a = 42;
    var f = function () { return a + 1; }
    return f;
}
Konrad Rudolph
The first example should say var foo = function ...
Christian Berg
Christian: Well, the first implies that `foo` is a function defined *anywhere*, not necessarily locally. I'll clarify this.
Konrad Rudolph
The main point is that a is on the stack when f is executed, so there is no need to store it somewhere else (usually together with f on the heap in a so-called closure). So "downward funarg" is the easy part of "funarg".
starblue
Hm, I could have sworn that the first version of your answer read "foo(x)" not "foo(f)", but the edit history says otherwise... Thanks for clarifying, anyways.
Christian Berg
Christian, I'm sorry for the confusion. The first version *was* using `x`, I changed it within the 5 minutes interval, that's why it doesn't show up in the edit history (see the SO FAQ for details). I figured `f` is a better name for a function than `x`.
Konrad Rudolph
+6  A: 

In Common Lisp:

(let ((a 3))
  (mapcar (lambda (b) (+ a b))
          (list 1 2 3 4)))

->  (4 5 6 7)

In above form the lambda function is passed DOWNWARD. When called by the higher-order function MAPCAR (which gets a function and a list of values as arguments, and then applies the function to each element of the list and returns a list of the results), the lambda function still refers to the variable 'a' from the LET expression. But it happens all within the LET expression.

Compare above with this version:

(mapcar (let ((a 3))
          (lambda (b) (+ a b)))
        (list 1 2 3 4))

Here the lambda function is returned from the LET. UPWARD a bit. It then gets passed to the MAPCAR. When MAPCAR calls the lambda function, its surrounding LET is no longer executing - still the function needs to reference the variable 'a' from the LET.

Rainer Joswig
+8  A: 

To better understand where the term comes from, you need to know some history.

The reason why an old Lisp hacker might distinguish downward funargs from funargs in general is that downward funargs are easy to implement in a traditional Lisp that lacks lexical variables (such as Emacs Lisp), whereas the general case is hard.

Traditionally a local variable was implemented in a Lisp interpreter by adding a binding (the symbol name of the variable, paired with its value) to the environment. Such an environment was simple to implement using an association list. Each function had its own environment, and a pointer to the environment of the parent function. A variable reference was resolved by looking in the current environment, and if not found there, then in the parent environment, and so on up the stack of environments until the global environment was reached.

In such an implementation, local variables shadow global variables with the same name. For example, in Emacs Lisp, print-length is a global variable that specifies the maximum length of list to print before abbreviating it. By binding this variable around the call to a function you can change the behaviour of print statements within that function:

(defun foo () (print '(1 2 3 4 5 6))) ; output depends on the value of print-length

(foo) ; use global value of print-length
  ==>  (1 2 3 4 5 6)

(let ((print-length 3)) (foo)) ; bind print-length locally around the call to foo.
  ==>  (1 2 3 ...)

You can see that in such an implementation, downward funargs are really easy to implement, because variables that are in the environment of the function when it's created will still be in the environment of the function when it's evaluated.

Variables that act like this are called special or dynamic variables, and you can create them in Common Lisp using the special declaration.

Gareth Rees