Antes de começar, gostaria de pedir um pouco de tolerância e boa vontade do leitor, pois não sei programar em Lisp, só conheço o básico, portanto vou me arrastar pelo artigo tentando dizer algo útil… =/
Lisp é uma linguagem de programação funcional muito usada em projetos de IA. Há também algumas aplicações conhecidas feitas em Lisp, como Emacs e AutoCAD.
Antes de ser padronizada como Common Lisp, havia muitos dialetos.
Se você possui um sistema GNU/Linux a mão, podemos começar a experimentar:
bash$ clisp
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2006
[1]>
Os comandos em Lisp são chamados forms e representados sempre entre parêntesis. Por exemplo:
[1]> (print "Olá Mundo!")
"Olá Mundo!"
"Olá Mundo!"
[2]>
A primeira impressão é o resultado do form
print
, a segundo é o retorno.Para criar uma variável podemos usar
setq
:[2]> (setq foo 12)
12
[3]> foo
12
[4]>
Outra forma é com
let
, que faz atamento, mas então a variável só existe no escopo:[4]> (let ((bar 15)) (print foo) (print bar))
12
15
15
[5]>
O último
15
é o retorno de let
, que é o mesmo retorno do último form do escopo – (print bar)
.Agora veja:
[5]> foo
12
[6]> bar
*** - EVAL: variable BAR has no value
The following restarts are available:
USE-VALUE :R1 You may input a value to be used instead of BAR.
STORE-VALUE :R2 You may input a new value for BAR.
ABORT :R3 ABORT
Break 1 [7]> abort
[8]>
Há alguns símbolos especiais, como
t
(verdadeiro), nil
(nulo) e as palavras-chave, iniciadas por :
:[8]> :teste-de-lisp
:TESTE-DE-LISP
[9]>
Lisp possui uma estrutura de par chamada cons:
[9]> (cons 3 4)
(3 . 4)
[10]>
Listas em Lisp são conses aninhados:
[10]> (cons 1 (cons 2 (cons 3 (cons 4 nil))))
(1 2 3 4)
[11]>
Um apelido para isso é:
[11]> (list 1 2 3 4)
(1 2 3 4)
[12]>
O form
car
retorna o primeiro elemento do cons e o form cdr
retorna o segundo:[12]> (car (list 1 2 3 4))
1
[13]> (cdr (list 1 2 3 4))
(2 3 4)
[14]>
Só alguns forms – nem de longe tudo:
push
– coloca um elemento no começo de uma lista, retornando a lista;pop
– remove o primeiro elemento de uma lista, retornando-o;defun
– define e retorna uma função;format
– imprime e/ou retorna uma string;if
,case
,cond
ewhen
– forms condicionais;block
,prog
eprogn
– bloco;loop
– ciclo (loop) incondicional;dolist
– equivale mais ou menos aofor
de Python;lambda
– lambda!!!sort
– ordenação;=
,eq
eequal
– igualdade;find
– procura elemento numa lista.
Uma coisa curiosa de Lisp é sua sintaxe extremamente funcional:
[14]> (if (= foo 12) "sim" "não")
"sim"
[15]>
Repare em
(= foo 12)
! Primeiro a função a ser executada – igualdade –, depois os parâmetros.Para terminar de forma interessante esse artigo, segue o crivo de Aristóstenes:
(let ((c 0) (noprime (list)) (index 1) (max 5000))
(loop
(setq index (+ index 1))
(if (not (find index noprime))
(progn
(format t "~D~4@T" index)
(setq c (+ c 1))
(let* ((j (* index 2)))
(loop
(pushnew j noprime)
(when (>= j max) (return))
(setq j (+ j index))))))
(when (>= index max) (return)))
(format t "~%Contagem de primos: ~D~%" c))
[update 2008-06-13]Código sugerido pelo Pedro:
(defun primos (max) (let ((c 0) (noprime ())) (loop for index-1 from 2 to max unless (member index-1 noprime) do (format t "~D~4@T" index-1) (incf c) (loop for index-2 from (* index-1 2) to max by index-1 do (pushnew index-2 noprime))) (format t "~%Contagem de primos: ~D~%" c)))
Valeu Pedro![/update]
Em outro momento explicarei comando a comando. Por ora, espero que achem Common Lisp tão interessante quanto achei. Para mais informações, vejam em meu del.icio.us, principalmente esse tutorial.
[]'s
Cacilhas, La Batalema