Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elisp: Bind a lambda in a Let and execute it [duplicate]

Tags:

emacs

lisp

elisp

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))
like image 277
Tahir Hassan Avatar asked Mar 16 '16 15:03

Tahir Hassan


1 Answers

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.

like image 119
Joshua Taylor Avatar answered Nov 05 '22 20:11

Joshua Taylor