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)
let and let* create new variable bindings and execute a series of forms that use these bindings. let performs the bindings in parallel and let* does them sequentially. first evaluates the expressions init-form-1, init-form-2, and so on, in that order, saving the resulting values.
In Scheme, you can use local variables pretty much the way you do in most languages. When you enter a let expression, the let variables will be bound and initialized with values. When you exit the let expression, those bindings will disappear.
LISP expressions are called symbolic expressions or s-expressions. The s-expressions are composed of three valid objects, atoms, lists and strings. Any s-expression is a valid program. LISP programs run either on an interpreter or as compiled code.
1.9. 2 Using setq This special form is just like set except that the first argument is quoted automatically, so you don't need to type the quote mark yourself. Also, as an added convenience, setq permits you to set several different variables to different values, all in one expression.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With