O Common Lisp permite ao programador escrever "comentários" que são ignorados pelo computador.
Os comentários de uma só linha começam com um ou mais pontos e vírgulas (;) e, ocasionalmente, podes ver o seguinte:
(code...) ; => value
Aqui, o comentário é usado para indicar o valor que o Common Lisp devolve depois de executar o código dessa linha.
É idiomático usar um único ponto e vírgula para um comentário curto no fim de uma linha, dois para um comentário mais longo acima de uma secção de código, três para um comentário extenso que descreve algo como uma função e quatro para um comentário do tipo cabeçalho no topo de um ficheiro de código-fonte.
Todos os objetos do Common Lisp são "átomos" (valores únicos e indivisíveis) ou "conses" (criados pela função construtora "cons").
Um cons é composto por duas partes: o primeiro elemento e o resto dos elementos.
Por razões históricas, estas duas partes chamam-se car e cdr.
Quando estes conses são avaliados como código, o primeiro elemento (car) representa a função que está a ser chamada, enquanto o resto dos elementos
(cdr) representa os argumentos dessa função:
(<function> <arg1> <arg2> ... <argN>)
; ^ car ^ | ^ cdr ^
Todo o código do Common Lisp é feito de S-Expressões (Expressões Simbólicas). Chamam-se sexprs, para abreviar. Cada sexpr é um átomo ou um cons. Quando as S-Expressões são avaliadas, devolvem automaticamente um valor que toma o lugar da expressão. Quando escreves as tuas próprias funções (com defun), o último valor dentro do corpo do defun é devolvido automaticamente:
;; Defining a new function
(defun gimme-foo () 'foo)
;; Calling the function as an S-Expression
(gimme-foo) ; => FOO
Os símbolos em Common Lisp são valores especiais que podem apontar para outros valores ou, no caso das keywords, para si próprios. Quando o Lisp avalia os símbolos, estes são substituídos pelos valores para os quais apontam:
foo ; => <whatever-foo-points-to>
:foo ; => :FOO
Repara que as keywords são indicadas por dois pontos (:) no início.
O quoting, ou seja, a adição de ' antes de uma S-expressão, diz ao Lisp para não avaliar essa expressão.
Ao usar quoting com 'foo no nosso exemplo do defun, evitámos que o Lisp tentasse procurar (e não encontrasse) aquilo para que FOO deveria apontar, devolvendo, em vez disso, o próprio valor FOO.
Se FOO não estiver definido em nenhum lugar do nosso programa:
foo ; => <ERROR! Lisp doesn't know what foo points to!>
'foo ; => FOO
Por agora, podes considerar isto apenas como uma forma de devolver símbolos a partir de uma função, mas vamos voltar ao quoting e explorar melhor as suas implicações em futuros exercícios de conceitos.
Tu! Sim, tu, destemido programador de Lisp! Lenny, o alienígena lisp precisa da tua ajuda! O Lenny quer ir andar com todos os outros alienígenas lisp, mas os pais disseram-lhe que não vai a lado nenhum enquanto o quarto não estiver limpo.
O problema é que o Lenny quase não consegue ver o chão! O Lenny não consegue distinguir os seus átomos dos seus conses, os seus símbolos das suas palavras-chave, os seus cars dos seus cdrs!
Consegues ajudar o Lenny a arrumar esta confusão? Não te esqueças dos teus parênteses, vais precisar deles!
Antes de o Lenny começar, precisa de relembrar o aspeto dos símbolos e das palavras-chave: já há algum tempo que não arruma nada... Ajuda o Lenny definindo duas funções: lennys-favorite-food, que avalia para um símbolo, e lennys-secret-keyword, que avalia para uma palavra-chave. Por exemplo:
(lennys-favorite-food) ; => LASAGNA
(lennys-secret-keyword) ; => :ALIENS-ARE-REAL
Repara que podes devolver o símbolo ou a palavra-chave que quiseres (se não fores fã de lasanha ou não acreditares em alienígenas).
Depois de relembrar os símbolos e as palavras-chave, está na hora de arrumar! Para organizar todas as S-Expressions espalhadas pelo quarto, o Lenny precisa de ajuda para determinar o que é um cons e o que é um átomo. Podes ajudar implementando duas funções, is-an-atom-p e 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 secção, há várias funções incorporadas de Lisp que podes achar úteis. Além disso, por agora, podes simplesmente considerar T como verdadeiro e NIL como falso.
Por fim, os conses do Lenny são demasiado volumosos para arrumar como deve ser, por isso é preciso dividi-los em partes mais pequenas. Podes ajudar definindo mais duas funções para dividir os conses (first-thing e rest-of-it)?
(first-thing '(first second third)) ; => FIRST
(rest-of-it '(first second third)) ; => (SECOND THIRD)
Mais uma vez, algumas funções incorporadas do Common Lisp podem dar jeito aqui.
Inscreve-te no Exercism para aprenderes e dominares Common Lisp com 27 conceitos92 exercícios, e mentoria humana real, tudo grátis.