10

I am attempting to understand the lambda notion found within Emacs Lisp.

In ielm, executing:

((lambda (x) (* x x)) 5)

gives us 25, and

(let ((x 4)) (* x x))

gives us 16. However when I do:

(let ((f (lambda (x) (* x x)))) (f 7))

it does not give me 49, but instead informs me:

*** Eval error ***  Symbol's function definition is void: f

Don't know why, I am sure the syntax is right and f is defined in the let?

Using cl-flet to define let-ed function

We can actually do this without using funcall. The cl module includes standard functions from Common Lisp. We first import it:

(require 'cl)

Thereafter we can use cl-flet to define our function:

(cl-flet ((f (x) (* x x)))
  (f 7))
Tahir Hassan
  • 5,715
  • 6
  • 45
  • 65
  • 1
    Does `(let ((f (lambda (x) (* x x)))) (funcall f 7))` work? – Joshua Taylor Mar 16 '16 at 15:23
  • 1
    I think you may find http://stackoverflow.com/a/17108245/1281433 helpful, though the question is a bit more complex. – Joshua Taylor Mar 16 '16 at 15:24
  • @sds That definitely describes some of the issue, but it doesn't mention **funcall** or **apply**, so it doesn't really answer the question, in my opinion. – Joshua Taylor Mar 16 '16 at 15:29
  • @sds Don't think it is a duplicate, not reached the level where I even know what `Lisp-1` and `Lisp-2` are. – Tahir Hassan Mar 16 '16 at 15:29
  • @TahirHassan: that question tells you what you need to learn to be able to answer your question yourself. – sds Mar 16 '16 at 15:33
  • @sds you are right, but it will be a long road ahead for me to even see *why* you are right. – Tahir Hassan Mar 16 '16 at 15:34
  • @JoshuaTaylor: that question is much more high level. It teaches the user how to fish instead of giving them the fish, so to speak. – sds Mar 16 '16 at 15:34
  • 1
    @TahirHassan: this is the road you need to take ASAP. Good luck! :-) – sds Mar 16 '16 at 15:35
  • @sds But looking at the documentation for funcall and apply would also lead to the understanding that's needed, as well as the subtle differences that might exist between different Lisps in the different categories. E.g., I don't know offhand whether Elisp uses spreadable arglists like CL's apply does. – Joshua Taylor Mar 16 '16 at 15:36

1 Answers1

19

I'd be surprised if this isn't a duplicate, but I can't find it readily here on Stack Overflow. In "Lisp-2" languages (e.g., Emacs Lisp and Common Lisp), there are separate namespaces for functions and variables. A function call looks like:

((lambda ...) ...) ; call the lambda function

or

(f ...) ; call the function binding of f

If you want to call the function that is the value of a variable, then you need to use funcall or apply:

(apply f ...)

(funcall f ...)

The difference between apply and funcall is well documented in other places, but the quick difference is that apply expects an argument list (in some Lisps, a "spreadable argument list"), whereas funcall takes the arguments directly. E.g.,

(let ((f (lambda (a b) (+ a b))))
  (funcall f 1 2)      ; arguments directly
  (apply f '(1 2)))    ; arguments in a list

In a "Lisp-1", (like Scheme), you don't need funcall, since there's only one space for bindings. In Scheme you can do:

(let ((f (lambda (a b) (+ a b))))
  (f 1 2))

The difference between Lisp-1 and Lisp-2 languages is described more in What is the difference between Lisp-1 and Lisp-2?. The big difference is when the system sees a function call, how it figures out what function to call. In a Lisp-1, variables have values, and that's all. So when the system sees something like:

(f ...)

f is a variable, and the only possible thing to call is the value of f. In a Lisp-2, the systems tries to call the function value of f, which doesn't have to have anything do with the value of the variable f. That can be a bit confusing at first, but it's actually pretty handy in many cases, because it makes it harder to accidentally obscure functions with common names. E.g., in a Lisp-1, you'll see lots of people use lst as an argument name instead of list, because if they named the argument list, then they couldn't use the (standard) function list within the function.

Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Thank you for your answer. I see that the difference between `funcall` and `apply` is that of JS's `call` and `apply` (except there is no such thing as a `this` reference). – Tahir Hassan Mar 16 '16 at 16:03
  • @TahirHassan I'd phrase it the other way around (i.e., that JS's call and apply are like Lisp's funcall and apply) because Lisp is older, but yes, it's the same principle. – Joshua Taylor Mar 16 '16 at 20:00