Lisp & Common Lisp
Carlos CunhaJoabe Jesus
{ceac, jbjj}@cin.ufpe.br
Roteiro
Motivação Histórico Common Lisp
Linguagem CLOS Aplicações
Motivação
Poder de Abstração de Linguagens Funcionais
Relacionada ao projeto de pesquisa - Linguagem da implementação do núcleo do Z-EVES (provador de teoremas)
Histórico
Concebida por John McCarthy no MIT em 1959
Influenciado pelo Cálculo Lambda de Alonzo Church Manipulação formal de funções
matemáticas
Acrônimo para List Processing
Histórico - Lisp e seus dialétos
Existiam vários dialetos: MacLisp Common Lisp Scheme ...
Hoje LISP está padronizado e referenciado como COMMON LISP
O que é o Common Lisp?
Uma das implementações de Lisp Um “SDK” de domínio público
Interpretador Compilador para executáveis até 5
vezes mais rápidos Conjunto de funções padrões
Common Lisp - Modularidade
Lisp permite: O empacotamento (packaging) de
programas em módulos Sistema de objetos, funções genéricas
com a possibilidade de combinação de métodos
Definição de Macros
Common Lisp
Tipos de dados
Common Lisp - Tipos de dados
números, caracteres, strings, arrays, listas, símbolos, estruturas, streams, ...
Todos com tamanho ilimitado (a precisão e o tamanho de uma variável não necessita de ser declarado, o tamanho de listas e arrays altera-se dinamicamente)
Integers de precisão arbitrária, precisão de ponto flutuante ilimitada
Common Lisp - “API”
Funções genéricas: 88 funções aritméticas para todos os
tipos de número (integers, ratios, floating point numbers, complex numbers)
44 funções de busca/filtro/ordenação para listas, arrays e strings
Common Lisp - Características
Tipagem em tempo de execução O programador geralmente não precisa
se preocupar com declarações de tipo, mas ele recebe mensagens de erro caso haja violações de tipo (operações ilegais)
Gerenciamento automático de memória (garbage collection)
Common Lisp - Tipos de Dados
Booleano LISP utiliza t e nil para representar
verdadeiro e falso Lisp tem funções booleanas-padrão,
como and, or e not. Sendo os conetivos and e or são curto-circuitantes
Common Lisp - Tipos de Dados
Símbolos Um símbolo é somente um string de
caracteresabc1foobar
Qualquer símbolo cujo nome inicia com dois pontos (:_) é uma palavra-chave
Exemplo - Símbolos
Ex:> (setq a 5) ; store a number as the value of a symbol5> a ; take the value of a symbol5> (let ((a 6)) a) ;bind the value of a symbol temporarily to 66> a ; the value returns to 5 once the let is finished5> (+ a 6) ; use the value of a symbol as an argument11> b ; try to take the value of a symbol which has no valueError: Attempt to take the value of the unbound symbol b.
Common Lisp - Tipos de Dados
Números Um inteiro é um string de dígitos
opcionalmente precedido de um + ou -. Um real parece com um inteiro, só que possui
um ponto decimal e pode opcionalmente ser escrito em notação científica.
Um racional se parece com dois inteiros com um / entre eles.
LISP suporta números complexos que são escritos como: #c(r i)
Common Lisp - Tipos de Dados
Conses – Associações Produto Cartesiano -> Dupla Os campos são chamados de "car" e
"cdr", ao invés de first e second> (cons 4 5) ; Aloca uma dupla, car = 4 e cdr = 5(4 . 5)> (car (cons 4 5))4> (cdr (cons 4 5))5
Common Lisp - Tipos de Dados
Listas (encadeadas) Construídas a partir de conses
O car de cada cons aponta para um dos elementos da lista e
O cdr aponta ou para outro cons ou para nil. Ex:
> (list 4 5 6)(4 5 6)
OBS: LISP imprime listas de uma forma especial, omitindo os pontos e parênteses internos dos conses
Common Lisp - Tipos de Dados
Listas (encadeadas) nil corresponde à lista vazia
O car e cdr de nil são definidos como nil. O car de um átomo é o próprio átomo. O cdr de um átomo é nil.
Se o cdr de um cons é nil, Lisp não se preocupa em imprimir o ponto ou o nil
Se o cdr de cons A é cons B, então lisp não se preocupa em imprimir o ponto para A nem o parênteses para B
Common Lisp - Tipos de Dados
Listas (encadeadas) e Conses Ex:> (cons 4 nil)(4)> (cons 4 (cons 5 6))(4 5 . 6)> (cons 4 (cons 5 (cons 6 nil)))(4 5 6)
Common Lisp - Tipos de Dados
Ordenação de Listas LISP provê duas primitivas para ordenação:
sort e stable-sort. O primeiro argumento para sort é uma lista, o segundo é a função de comparação. Ex:
> (sort '(2 1 5 4 6) #'<)(1 2 4 5 6)> (sort '(2 1 5 4 6) #'>)(6 5 4 2 1) OBS: A função de comparação não garante
estabilidade: se há dois elementos a e b tais que (and (not (< a b)) (not (< b a))), sort vai arranjá-los de qualquer maneira
Common Lisp - Tipos de Dados
A função stable-sort é exatamento como sort, só que ela garante que dois elementos equivalentes vão aparecer na lista ordenada exatamente na mesma ordem em que aparecem lista original
Common Lisp - Tipos de Dados
Funções de Lista Úteis> (append '(1 2 3) '(4 5 6)) ;concatena listas (1 2 3 4 5 6)> (reverse '(1 2 3)) ;reverte os elementos(3 2 1)> (member 'a '(b d a c)) ;pertinência a conjunto ;retorna
primeira cauda cujo car é o elemento desejado(A C)> (find 'a '(b d a c)) ;outro set membershipA> (find '(a b) '((a d) (a d e) (a b d e) ()) :test #'subsetp)(A B D E) ;find é mais flexível
Common Lisp - Tipos de Dados
Funções de Lista Úteis> (subsetp '(a b) '(a d e)) ;set containmentNIL> (intersection '(a b c) '(b)) ;set intersection(B)> (union '(a) '(b)) ;set union(A B)> (set-difference '(a b) '(a)) ;diferença de conjuntos(B)
Common Lisp
Igualdade
Common Lisp - Igualdade
LISP tem muitos conceitos diferentes de igualdade. Igualdade numérica é denotada por =
Como em Smalltalk ou em Prolog, existem os conceitos de identidade (mesmo objeto) e igualdade (objetos distintos, porém iguais)
Common Lisp - Igualdade
Dois símbolos são eq se e somente se eles forem idênticos (identidade). Duas cópias da mesma lista não são eq (são dois objetos diferentes) mas são equal (iguais)> (eq 'a 'a)T> (eq 'a 'b)NIL> (= 3 4)T> (eq '(a b c) '(a b c))NIL> (equal '(a b c) '(a b c))T> (eql 'a 'a)T> (eql 3 3)T
Common Lisp - Igualdade
O predicado eql é equivalente a eq para símbolos e a = para números. É a identidade que serve tanto para números como para símbolos.
O predicado equal é equivalente eql para símbolos e números. Ele é verdadeiro para dois conses, se e somente se,
seus cars são equal e seus cdrs são equal. Ele é verdadeiro para duas estruturas se e somente
se as estruturas forem do mesmo tipo e seus campos correspondentes forem equal.
Common Lisp
Funções
Common Lisp - Funções
Definindo uma função:> (defun foo (x y) (+ x y 5))FOO> (foo 5 0) ;chamando a função10> (defun HELLO-WORLD () (print (list 'HELLO 'WORLD))) HELLO WORLD
Common Lisp - Funções
Funcall, Apply, e Mapcar São funções que pedem como
argumento uma função:> (funcall #'+ 3 4)7> (apply #'+ 3 4 '(3 4))14> (mapcar #'not '(t nil t nil t nil))(NIL T NIL T NIL T)
Common Lisp - Funções
Funcall chama seu primeiro argumento com os argumentos restantes como argumentos deste.
Apply é semelhante a Funcall, exceto que seu argumento final deverá ser uma lista. Os elementos desta lista são tratados como se fossem argumentos adicionais ao Funcall.
O primeiro argumento a mapcar deve ser uma função de um argumento. mapcar aplica esta função a cada elemento de uma lista dada e coleta os resulatdos em uma outra lista.
Utilidade de Funcall, apply e Mapcar
Funcall e apply são principalmente úteis quando o seu primeiro argumento é uma variável. Por exemplo, uma máquina de inferência
poderia tomar uma função heurística e utilizar funcall ou apply para chamar esta função sobre uma descrição de um estado.
As funções de ordenação de listas utilizam funcall para chamar as suas funções de comparação
Mapcar, juntamente com funções sem nome (lambda) pode substituir muitos laços
Common Lisp - Funções Lambda
É uma função temporária e não nomeada> #'(lambda (x) (+ x 3))(LAMBDA (X) (+ X 3))> (funcall * 5)8
Common Lisp - Funções Lambda
O poder de Lambda Ex:> (do ((x '(1 2 3 4 5) (cdr x)) (y nil)) ((null x) (reverse y)) (push (+ (car x) 2) y))(3 4 5 6 7)
> (mapcar #'(lambda (x) (+ x 2)) '(1 2 3 4 5))(3 4 5 6 7)
Common Lisp
Forms
Common Lisp - Forms
Forms e o Laço Top-Level Um Form é qualquer trecho digitado
pelo usuário para o interpretador
read-eval-print loop
Lisp salva os três últimos resultados de forms previamente digitados. Ele os armazena sob os símbolos *, ** e ***.
Common Lisp - Forms
Forms e o Laço Top-Level Em geral, um form é ou um átomo (p.ex.: um
símbolo, um inteiro ou um string) ou uma lista. Se o form for um átomo, LISP o avalia
imediatamente. Símbolos avaliam para seu valor, inteiros e strings avaliam para si mesmos.
Se o form for uma lista, LISP trata o seu primeiro elemento como o nome da função, avaliando os elementos restantes de forma recursiva. Então chama a função com com os valores dos elementos restantes como argumentos.
Common Lisp - Forms especiais
quote ‘ e function parecem chamadas a funções mas não são! Ex. quote:
> (setq a 3)3> a3> (quote a)A> 'a ; 'a is an abbreviation for (quote a)A
Common Lisp
Forms especiais Ex. function:
> (setq + 3)3> +3> '++> (function +)#<Function + @ #x-fbef9de>> #'+ ; #'+ is an abbreviation for (function +)#<Function + @ #x-fbef9de>
Common Lisp
Binding
Common Lisp - Binding
Binding é uma atribuição escopada lexicamente
Forms especiais let e let*: (let ((var1 val1) (var2 val2) ... ) body)
Let “atribui” val1 a var1, ..., e então executa os comandos de seu corpo
Let* permite que sejam referenciadas variáveis definidas anteriormente
Common Lisp - Dynamic Scoping
No escopo dinâmico se você atribui um valor a uma variável, TODA menção desta variável vai retornar aquele valor até que você atribua outro valor à mesma variável
Usa o form defvar
Common Lisp - Dynamic Scoping
Ex:> (defvar *special* 5)*SPECIAL*> (defun check-special () *special*)CHECK-SPECIAL> (check-special)5> (let ((*special* 6)) (check-special))6
Common Lisp
Fluxo de controle
Common Lisp - Fluxo de controle
Execução seqüencial em Lisp O form progn permite blocos de
comandos em seu corpo, que são executados sequencialmente e retornando o valor do último
Permite também declaração explícita de variáveis locais, além de retorno explícito
Common Lisp - Fluxo de controle
Ex:(defun F2.17a nil (prog (i j) ;define i e j como variáveis locais inic. com nil (setq i (read)) (setq j (read) (return (print (- i j))) ))
Common Lisp - Condicionais
Lisp possui um função para representar condicionais:> (if t 5 6)5> (if nil 5 6)6> (if 4 5 6)5
OBS: nil significa falso e qualquer outra coisa verdadeiro.
Common Lisp - Condicionais
If’s sem then ou sem else podem ser escritos utilizando-se when ou unless, respectivamente:> (when t 3)3> (when nil 3)NIL> (unless t 3)NIL> (unless nil 3)3
Common Lisp - Condicionais
Else If’s são descritos usando o form cond: Um cond consiste de símbolo con
seguido por um número de cláusulas-cond, cada qual é uma lista. O primeiro elemento de uma cláusula-cond é a condição, os lementos restantes são a ação.
Common Lisp - Condicionais
Ex:> (setq a 3)3> (cond ((evenp a) a) ; if a is even return a ((> a 7) (/ a 2)) ; else if a > 7 return a/2 ((< a 5) (- a 1)) ; else if a < 5 return a-1 (t 17) ; else return 17 )2
OBS: Se não há nenhuma ação na cláusula cond selecionada, cond retorna o valor verdadeiro
Common Lisp - Condicionais
Form case Ex:> (setq x 'b)B> (case x (a 5) ((d e) 7) ((b f) 3) (otherwise 9) )3
Common Lisp - Iteração
Lisp permite a utilização da função loop:> (setq a 4)4> (loop (setq a (+ a 1)) (when (> a 7) (return a)) )8> (loop (setq a (- a 1)) (when (< a 3) (return)) )NIL
Common Lisp - Iteração
dolist - ata uma variável aos elementos de uma lista na sua ordem e termina quando encontra o fim da lista: > (dolist (x '(a b c)) (print x))ABCNIL
Common Lisp - Iteração
Iteração com do e do*:> (do ((x 1 (+ x 1)) ;variável x, com valor inicial 1 (y 1 (* y 2)) ; variável y, com valor inicial 1 ) ((> x 5) y) ;retorna valor de y quando x > 5 (print y) ; corpo (print 'working) ; corpo )1WORKING 2 WORKING4WORKING 8WORKING16WORKING32
Common Lisp - Sáidas Não-Locais
O form especial return na seção de iteração é um exemplo de um return não-local. Outro exemplo é o form return-from, o qual retorna um valor da função que o envolve:> (defun foo (x) (return-from foo 3) x )FOO> (foo 17)3
Common Lisp - Blocos nomeados
Ex:> (block foo (return-from foo 7) 3 )7
Common Lisp - Gerando Erros
Ex:> (error "This is an error")Error: This is an error
Common Lisp - Extensões
Dados Avançados
Common Lisp - Dados Avançados
Estruturas: análogas a structs em "C" ou records em
PASCAL O exemplo abaixo define um tipo de dado
chamado FOO contendo 2 campos:> (defstruct foo bar quux )FOO
Define também 3 funções que operam neste tipo de dado:
make-foo, foo-bar e foo-quux
Common Lisp - Dados Avançados
Estruturas: make-foo - cria um novo objeto FOO. As outras acessam os campos de um
objeto do tipo FOO> (make-foo)#s(FOO :BAR NIL :QUUX NIL)> (make-foo :baa 3)#s(FOO :BAR 3 :QUUX NIL) > (foo-bar *)3> (foo-quux **)NIL
Common Lisp - “Atribuição”
O form especial setf usa seu primeiro argumento para definir um lugar na memória, avalia o seu segundo argumento e armazena o valor resultante na locação de memória resultante
Setf é a única maneira de se setar os valores de um array ou os campos de uma estrutura
Common Lisp - “Atribuição”
Ex:> (setf a (make-array 1)) ; setf on a variable is equivalent to
setq#(NIL)> (push 5 (aref a 1)) ;push can act like setf(5)> (pop (aref a 1)) ; so can pop5> (setf (aref a 1) 5) 5> (incf (aref a 1)) ; incf reads from a place, increments, and
writes back6> (aref a 1)6
Common Lisp
A extensão CLOS
CLOS
Extensão do Common Lisp para Orientação a Objetos
Características: Herança múltipla Funções genéricas Meta-classe e meta-objeto Técnica de criação e iniciação de
objetos que permite controle do processo por parte do usuário
Classes CLOS
Definida usando o form DEFCLASS Ex:
(DEFCLASS nodeDeClasse (nomeDeSuperclasse*) (slot*) opções*)
Se nomeDeSuperclasse* for vazio a superclasse padrão é STANDARD-OBJECT
Slots em CLOS
Um slot tem a forma:
(nomeDoSlot slotOption*)
As opções mais úteis são: :ACCESSOR function-name :INITFORM expression :INITARG symbol
Exemplo DEFCLASS
Um DEFCLASS:(defclass person () ((name :accessor person-name :initform 'bill :initarg :name) (age :accessor person-age :initform 10 :initarg :age)))
DEFCLASS DEFSTRUCT
Sintaxe um pouco diferente Considere o DEFSTRUCT:
(defstruct person (name 'bill) (age 10))
DEFCLASS DEFSTRUCT
DEFSTRUCT definiria automaticamente campos com expressões para: computar valores iniciais default funções de acesso (get e set) como
PERSON-NAME e uma função de inicialização (MAKE-
PERSON) que pegaria argumentos com palavras-chave como abaixo:
(make-person :name 'george :age 12)
DEFCLASS DEFSTRUCT
DEFCLASS dá maior controle sobre quais coisas são chamadas, pois: Permite especificar quais funções
auxiliares queremos, sendo mais flexível que o DEFSTRUCT
Objetos em CLOS
Instâncias são criadas através da função MAKE-INSTANCE Similar às funções MAKE-x definidas por
DEFSTRUCT Permite que você passe a classe a ser
instanciada como argumento EX:
(MAKE-INSTANCE class {initarg value}*)
Objetos de Classe (“static”)
Uma classe, uma vez definida, também é um objeto
Para obter um objeto-classe a partir de seu nome, usa-se:
(FIND-CLASS name)
Métodos em CLOS
Um DEFMETHOD(DEFMETHOD generic-function-name
specialized-lambda-list
form*)
Métodos em CLOS
Ex.:(defmethod test ((x number) (y number)) '(num num))(defmethod test ((i integer) (y number)) '(int num)) (defmethod test ((x number) (j integer)) '(num int))
(test 1 1) => (int num), not (num int) (test 1 1/2) => (int num) (test 1/2 1) => (num int) (test 1/2 1/2) => (num num)
Combinação de Métodos
:before methods are all called before the primary
method, with the most specific :before method called first
:after methods are all called after the primary method,
with the most specific :after method called last. :around
methods run before the other methods. As with primary methods, only the most specific is called and call-next-method calls the next most specific
Combinação de Métodos - Ex.
(defclass food () ()) (defmethod cook :before ((f food)) (print "A food is about to be
cooked."))(defmethod cook :after ((f food)) (print "A food has been cooked."))
(defclass pie (food) ((filling :accessor pie-filling :initarg :filling :initform 'apple)))
(defmethod cook ((p pie)) (print "Cooking a pie.") (setf (pie-filling p) (list 'cooked (pie-filling p))))
(defmethod cook :before ((p pie)) (print "A pie is about to be cooked."))
(defmethod cook :after ((p pie)) (print "A pie has been cooked."))
(setq pie-1 (make-instance 'pie :filling 'apple))
Combinação de Métodos – Ex.
Saída> (cook pie-1) "A pie is about to be cooked." "A food is about to be cooked." "Cooking a pie.“ "A food has been cooked." "A pie has been cooked." (cooked apple)
Lisp & Common Lisp
Aplicações
Aplicações
Utilizado para desenvolver o primeiro sistema computacional de matématica simbólica, o MACSYMA.
Linguagem de extensão do software do AutoCAD, desenvolvido pela AutoDesk; e do editor de textos Emacs
Estudos de semântica formal das línguas naturais e de programação
Aplicações
Sistema de reserva de passagens Orbitz da ITA. Utilizado por diversas companhias aérias
A Simbolics criou um sistema de modelagem 3D, adquirido pela IZWare e renomeado para Mirai, que foi utilizado nos efeitos de Senhor dos Anéis
Sistema de e-commerce da viaweb (por Paul Graham) que posteriormente foi vendida para o Yahoo por US$ 40 milhões, na época da bolha da internet
Referências
Introdução à Linguagem Lisp http://www.inf.ufsc.br/~awangenh/Funcional/
Funcional.html http://www.gia.ist.utl.pt/Lisp9596/Lisp9596.html http://pt.wikipedia.org/wiki/Lisp
Common Lisp http://www.dca.ufrn.br/~adelardo/lisp/ http://pt.wikipedia.org/wiki/Common_Lisp
CLOS http://www.aiai.ed.ac.uk/~jeff/clos-guide.html
Lisp & Common Lisp
Dúvidas?
Top Related