Reputation: 1201
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)
Upvotes: 5
Views: 2790
Reputation: 139401
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
Upvotes: 11
Reputation: 994531
The reason is that you are using a Lisp dialect with dynamic binding (link to a good description of this from the Emacs Lisp documentation).
In detail, your program behaves the way it does is because the new binding for x
created by the let
expression takes the place of the (defvar x 1)
when g
is called from within the let
expression. So, instead of adding 1 to its argument, the g
function adds the current value of x
, which is 5 when inside the let
expression.
Upvotes: 4