Common Lisp le permite a quien programa escribir «comentarios» que la computadora ignora.
Los comentarios de una sola línea comienzan con uno o más puntos y coma (;) y, de vez en cuando, puedes ver lo siguiente:
(code...) ; => value
Donde el comentario se usa para indicar qué valor devuelve Common Lisp después de ejecutar el código de esa línea.
Es idiomático usar un solo punto y coma para un comentario corto al final de una línea, dos para un comentario más largo encima de una sección de código, tres para un comentario largo que describe algo como una función y cuatro para un comentario como un encabezado en la parte superior de un archivo fuente.
Todos los objetos de Common Lisp son «átomos» (valores únicos e indivisibles) o «conses» (construidos por la función constructora «cons»).
Un cons se compone de dos partes: el primer elemento y el resto de los elementos.
Por razones históricas, estas dos partes se llaman el car y el cdr.
Cuando estos conses se evalúan como código, el primer elemento (car) representa la función que se llama, mientras que el resto de los elementos
(cdr) representan los argumentos de esa función:
(<function> <arg1> <arg2> ... <argN>)
; ^ car ^ | ^ cdr ^
Todo el código de Common Lisp está hecho de S-Expressions (expresiones simbólicas). Para abreviar, se llaman sexprs. Cada sexpr es un átomo o un cons. Cuando se evalúan las S-Expressions, automáticamente devuelven un valor que ocupa el lugar de la expresión. Cuando escribes tus propias funciones (usando defun), el último valor dentro del cuerpo del defun se devuelve automáticamente:
;; Defining a new function
(defun gimme-foo () 'foo)
;; Calling the function as an S-Expression
(gimme-foo) ; => FOO
Los símbolos en Common Lisp son valores especiales que pueden apuntar a otros valores o, en el caso de las palabras clave, a sí mismos. Cuando Lisp evalúa los símbolos, estos se reemplazan con los valores a los que apuntan:
foo ; => <whatever-foo-points-to>
:foo ; => :FOO
Ten en cuenta que las palabras clave se denotan con dos puntos (:) al principio.
La cita, es decir, agregar ' antes de una S-Expression, le indica a Lisp que no evalúe esa expresión.
Al citar 'foo en nuestro ejemplo de defun, evitamos que Lisp intentara buscar (y no encontrara) aquello a lo que se supone que apunta FOO; en lugar de eso, devuelve el valor FOO en sí mismo.
Si FOO no se ha definido en ninguna parte de nuestro programa:
foo ; => <ERROR! Lisp doesn't know what foo points to!>
'foo ; => FOO
Por ahora, puedes considerar esto simplemente como una forma de devolver símbolos desde una función, pero volveremos a tratar la cita y exploraremos más a fondo sus implicaciones en futuros ejercicios de concepto.
¡Tú! Sí, tú, ¡valiente lisper! ¡Lenny, el alienígena de Lisp necesita tu ayuda! Lenny quiere ir a pasar el rato con los demás alienígenas de Lisp, pero sus padres le han dicho que no va a ir a ningún lado hasta que su cuarto esté limpio.
El problema es que Lenny apenas puede ver el piso. No distingue sus átomos de sus conses, ni sus símbolos de sus palabras clave, ni sus car de sus cdr.
¿Puedes ayudar a Lenny a ordenar este desastre? ¡No olvides tus paréntesis, los vas a necesitar!
Antes de que Lenny pueda empezar, necesita repasar cómo se ven los símbolos y las palabras clave; hace mucho que no ordena nada... Ayuda a Lenny definiendo dos funciones: lennys-favorite-food, que evalúa a algún símbolo, y lennys-secret-keyword, que evalúa a alguna palabra clave. Por ejemplo:
(lennys-favorite-food) ; => LASAGNA
(lennys-secret-keyword) ; => :ALIENS-ARE-REAL
Ten en cuenta que puedes devolver cualquier símbolo o palabra clave que quieras (si no eres fan de la lasaña o no crees en los alienígenas).
Una vez que Lenny haya repasado los símbolos y las palabras clave, ¡es hora de limpiar! Para revisar todas las S-Expressions que están regadas por su cuarto, Lenny necesita ayuda para determinar qué es un cons y qué es un átomo. Puedes ayudar implementando dos funciones, is-an-atom-p y is-a-cons-p:
(is-an-atom-p 'one-thing) ; => T
(is-an-atom-p '(two things)) ; => NIL
(is-a-cons-p 'one-thing) ; => NIL
(is-a-cons-p '(two things)) ; => T
Para esta sección, hay varias funciones integradas de Lisp que te pueden resultar útiles. Además, por ahora, puedes simplemente considerar T como verdadero y NIL como falso.
Por último, los conses de Lenny son demasiado voluminosos para guardarlos ordenadamente, así que necesita dividirlos en partes más pequeñas. ¿Puedes ayudar definiendo dos funciones más para separar sus conses (first-thing y rest-of-it)?
(first-thing '(first second third)) ; => FIRST
(rest-of-it '(first second third)) ; => (SECOND THIRD)
De nuevo, algunas de las funciones integradas de Common Lisp te pueden venir bien aquí.
Regístrate en Exercism para aprender y dominar Common Lisp con 27 conceptos92 ejercicios y mentoría humana real, todo gratis.