Search code examples
lispcommon-lisplet

Understanding "let" expression in LISP


I am extremely new to lisp, had previous experience with functional programming (Haskell, SML). Why is this code returning 14, and not 10 (i.e. 1 + 2y + 3 + 1)?

(defvar x 1)

(defun g (z)
  (+ x z))

(defun f (y)
  (+ (g 1)
     (let ((x (+ y 3)))
        (g (+ y x)))))

(f 2)

Solution

  • Because you used (DEFVAR X 1), which declares X to be a global special variable. This then causes every other later binding of X to use dynamic binding: here in (LET ((X ....

    Style & Convention in Lisp

    Convention in Lisp: use *X* instead of X for special variables.

    (defvar *x* 1)
    

    Your code then is:

    (defvar *x* 1)   ; global special variable *X*
    
    (defun g (z)
      (+ *x* z))     ; use special variable *X*
    
    (defun f (y)
      (+ (g 1)
         (let ((x (+ y 3)))    ; lexical binding of X
            (g (+ y x)))))     ; use lexical binding of X
    

    run:

    ? (f 2)
    10