8. Variables
As in other languages, we have local and global variables. However, the scope of variables in Common Lisp is very important and has particularities that you must know.
Local variables
They are defined with the let or let* function, and are only accessible within the block where they are defined.
(let ((x 10)
(y 20))
(+ x y)) ; 30
If I try to perform the same arithmetic operation outside the let block, I will get an error:
(let ((x 10)
(y 20)))
(+ x y) ; Error: Variable X is unbound.
No matter how deep your code is, the variables will be accessible as long as they are inside the let block.
However, you should know that variables do not respect the order in which you define them. For example:
(let ((x 1)
(y 2)
(z (+ x y))) ; Error: Variable X is unbound.
z)
You get an error because x and y are not defined at the moment z is calculated. The solution is to evaluate them, and for that there is let*:
(let* ((x 1)
(y 2)
(z (+ x y))) ; Now it works correctly.
z) ; 3
The difference between let and let* is that let evaluates all the variable initializations in parallel, while let* evaluates them sequentially, allowing previously defined variables to be used in later initializations.
When should I use each one?
letby default since it is more efficient, andlet*only when you need one variable to depend on another.
Dynamic variables
We could consider them global variables, but with a scope that is dynamic.
They are defined with defparameter or defvar.
(defparameter *mi-variable* 42)
(defvar *otra-variable* "Hola, mundo!")
Their differences are subtle but important.
defparameter always initializes the variable, even if it already exists. defvar only initializes the variable if it does not already exist.
For example, if you run:
(defparameter *mi-variable* 100)
*mi-variable* ; 100
(defparameter *mi-variable* 200)
*mi-variable* ; 200
The variable *mi-variable* is 200 because defparameter has redefined it.
(defvar *otra-variable* "Hola mundo!")
(defvar *otra-variable* "Nos vemos luego!")
*otra-variable* ; "Hola mundo!"
The variable *otra-variable* still holds "Hola mundo!" because it was already defined. To overwrite it you must use setf:
(setf *otra-variable* "Nos vemos luego!")
*otra-variable* ; "Nos vemos luego!"
A good practice is not to change the values of dynamic variables unless it is strictly necessary, since it can lead to unexpected behavior in the code. Instead, instantiate local variables inside functions or let blocks.
(defparameter *impuesto* 21)
(defun calcular-precio-con-impuesto-reducido (precio)
(let ((*impuesto* 10)) ; Local variable
(* precio (+ 1 (/ *impuesto* 100)))))
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Desafíos de programación atemporales y multiparadigmáticos
Te encuentras ante un librillo de actividades, divididas en 2 niveles de dificultad. Te enfrentarás a los casos más comunes que te puedes encontrar en pruebas técnicas o aprender conceptos elementales de programación.
Buy the bookWill you buy me a coffee?
This is how I keep writing without ads or paywalls.
Sure, it's on me!
Comments
There are no comments yet.