Lisp Evaluation

Discussion of Emacs Lisp
Post Reply
psholtz
Posts: 5
Joined: Sun May 01, 2011 1:41 pm

Lisp Evaluation

Post by psholtz » Sun May 01, 2011 1:45 pm

I can use the following code in Scheme:

Code: Select all

(define (a-plus-abs-b a b)
 ((if (> b 0) + -) a b))
It basically looks at whether b is positive or not, and accordingly selects the "+" or "-" operation to apply to the arguments a and b.

It runs fine in Scheme:

Code: Select all

(a-plus-abs-b 1 1) 
;; 2

(a-plus-abs-b 1 -1)
;; 2
However, when I try to define the same procedure in Emacs Lisp, the code crashes:

Code: Select all

(defun a-plus-abs-b (a b)
 ((if (> b 0) + -) a b))
Why is this?

Does Emacs Lisp evaluate expressions in a different manner than Scheme?

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Lisp Evaluation

Post by ramarren » Sun May 01, 2011 11:47 pm

psholtz wrote:Does Emacs Lisp evaluate expressions in a different manner than Scheme?
Lisp is a family of very varied languages and you should generally not expect more than surface similarities. Emacs Lisp is a Lisp-2 with dynamic binding and focus on side-effects, and so very different from Scheme. It would be likely most effective to learn Emacs Lisp from scratch (documentation) rather than trying to adapt any Scheme knowledge.

To answer the direct question: in Lisp-2, like Common Lisp and Emacs Lisp, there is a separate namespace for operators. The operator position of a form must be a name in that namespace, which is either a symbol naming a function or a lambda form. All other forms are an error.

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Lisp Evaluation

Post by nuntius » Wed May 04, 2011 8:11 pm

In a lisp-2, the idiomatic form is

Code: Select all

(defun a-plus-abs-b (a b)
  (if (> b 0)
    (+ a b)
    (- a b)))
or maybe

Code: Select all

(defun a-plus-abs-b (a b)
  (+ a (if (> b 0) b (- b)))) ; explicit (abs b)
The literal translation of your code is

Code: Select all

(defun a-plus-abs-b (a b)
  (funcall (if (> b 0) '+ '-) a b))

findinglisp
Posts: 447
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX
Contact:

Re: Lisp Evaluation

Post by findinglisp » Sat Jun 04, 2011 7:21 am

To give a bit longer answer, there is a notion in the Lisp family of languages of Lisp-1 vs. Lisp-2. In a Lisp-1 variant (e.g., Scheme), symbols have only a single value. If you see the symbol LIST, for instance, it's always bound to the same thing. This is true whether the symbol appears in the first position of a function call form or anyplace else. In a Lisp-2 variant (e.g., Common Lisp, Emacs Lisp), the symbol LIST can evaluate to two different values depending on where it appears. As the first symbol in a function call, it evaluates to the function associated with the symbol. In any other position, it evaluates to the data value associated with the symbol. This is convenient, because it allows you to have variable names that would otherwise clash with the names of functions. For instance:

Code: Select all

(defun foo (list)    ; LIST is a variable here, no conflict with the LIST function
    (list 'a list))  ; First LIST is a call to the LIST function. Second LIST is a reference to the LIST variable.
If you want to access the function associated with a symbol when the reference would otherwise select the data, preface the symbol with pound-tick: #'SYMBOL.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

spacebat
Posts: 3
Joined: Sun Jan 10, 2010 2:49 am
Location: Adelaide, South Australia

Re: Lisp Evaluation

Post by spacebat » Sun Aug 19, 2012 12:56 am

Good explanation, but there's a minor distinction when it comes to emacs lisp that one doesn't notice much in typical use.
findinglisp wrote:If you want to access the function associated with a symbol when the reference would otherwise select the data, preface the symbol with pound-tick: #'SYMBOL.
That's true for common lisp, but only at compile time for emacs lisp. In both cases #'x acts like (function x).

In emacs lisp, (function x) is just like (quote x) except at compile time, when it indicates that x should be compiled. This matters when the argument x is a lambda expression. For compatibility, forms like funcall and apply that expect a function argument will also happily accept a symbol and get the function object to call from its function slot.

Code: Select all

ELISP> (defun add (a b) (+ a b))
add
ELISP> #'add
add
ELISP> 'add
add
ELISP> (function add) ;; acts like (quote add) except at compile time
add
ELISP> (symbol-function 'add) ;; gives the actual function object from the function slot of the symbol
(lambda
  (a b)
  (+ a b))
ELISP> (funcall #'add 2 3) ;; funcall gets the add symbol and pulls out the function
5
ELISP> (funcall 'add 2 3) ;; ditto
5
ELISP> (funcall (function add) 2 3) ;; ditto
5
ELISP> (funcall (symbol-function 'add) 2 3) ;; funcall is passed the actual function object
5
Parenthetically speaking, that is.

Post Reply