Este documento discute paradigmas de programação funcional em Lisp. Resume os principais tópicos abordados: 1) Manipulação de variáveis e argumentos, incluindo escopo, variáveis opcionais e default; 2) Formatação de saída e forms especiais; 3) Tipos de dados como vetores, strings e estruturas.
2. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
PARTE 3 - PARADIGMA FUNCIONAL
PROGRAMAÇÃO FUNCIONAL EM LISP
AULA 2
2 / 47
3. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Roteiro
1 Manipulação de Variáveis e Argumentos
2 Formatação de Saída e Forms
3 Tipos de Dados Complexos
4 Iteratividade
3 / 47
4. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Escopo das Variáveis
Não podemos usar variáveis fora do escopo (funções onde foram criadas). O processo
de se associar um valor a um símbolo durante um certo escopo léxico é chamado em
LISP de ateamento.
4 / 47
5. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Variáveis - Opcionais
Você pode especificar também argumentos opcionais para funções. Qualquer
argumento após o símbolo &optional é opcional. Ex.
1 (defun bar (x &optional y) (if y x 0))
Uso:
1 >(bar 2)
2 0
3 > (bar 2 3)
4 2
5 / 47
6. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Argumentos Default Não São Ideia Nova
O trecho de código abaixo define argumentos por padrão (default) para variáveis.
1 (defun opts (& optional (x 3) (z 10)) (+ x z))
Uso
1 > (opts)
2 13
3 > (opts 1)
4 11
5 > (opts 1 4)
6 5
7 >
6 / 47
7. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Quantidade de Argumentos Também pode ser Opcional
Neste caso tudo o que for dado além do x é y.
1 > (defun foo (x &rest y) y)
2 FOO
3 > (foo 1)
4 NIL
5 > (foo 1 2)
6 (2)
7 > (foo 1 2 3)
8 (2 3)
9 > (foo 1 2 3 4)
10 (2 3 4)
11 > (foo 1 2 3 4 5)
12 (2 3 4 5)
7 / 47
8. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Argumentos Com Nome
Parâmetros podem ser associados a palavras chaves (key) e portanto podem ser
passados em qualquer ordem.
1 >(defun foo (&key x y) (cons x y))
2 FOO
3 > (foo :x 5 :y 3)
4 (5 . 3)
5 > (foo :y 3 :x 5)
6 (5 . 3)
7 > (foo :y 3)
8 (NIL . 3)
9 > (foo)
10 (NIL)
8 / 47
9. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Um Parâmetro do Tipo &key Também Ter um Valor Default
Exemplo de Uso do Key com valores default.
1 > (defun foo (&key (x 5)) x)
2 FOO
3 > (foo :x 7)
4 7
5 > (foo)
9 / 47
10. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Impressão
Além da função write temos também a função printque imprime o argumento e a
retorna.
1 >(print 5)
2 5
3 5
10 / 47
11. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Impressão com Formatação
formatação da saída.
1 > (format nil "imprimindo um átomo ~s " nil)
2 imprimindo um átomo NIL
3 > (format nil "imprimindo um átomo ~s " 3)
4 imprimindo um átomo 3
5 > (format nil "imprimindo um atomo ~s " (setq a 2))
6 imprimindo um atomo 2
7 > (format nil "imprimindo um número ~D " 3.4)
8 imprimindo um número 3.4
9 > (format nil "imprimindo um número ~D e outro ~D" 3.4 4.5)
10 imprimindo um número 3.4 e outro 4.5
11 > (format nil "Número ~D ~%e outro em outra linha ~D" 3.4 4.5)
12 Número 3.4
13 e outro em outra linha 4.5
11 / 47
12. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
t = terminal nil = nada nome = referência para arquivo em disco
1 >(format nil "Número ~D ~%e outro em outra linha ~D" 3.4 4.5)
2 "Número 3.4
3 e outro em outra linha 4.5"
4 > (format t "Número ~D ~%e outro em outra linha ~D" 3.4 4.5)
5 Número 3.4
6 e outro em outra linha 4.5
7 NIL
12 / 47
13. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Forms Especiais
Tudo que se digita é um form. Os forms são avaliados e geram respostas. Respostas
antigas podem ser recuperados com *,**,***. Ex.
1 > (setq a 3)
2 3
3 > (setq b 4)
4 4
5 > (+ a b)
6 7
7 > ***
8 3
9 > **
10 7
11 > *
12 7
13 / 47
14. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Forms Especiais - quotes e function
quotes são aspas simples. Evitam que um argumento seja avaliado.
1 > (quote a)
2 A
3 > ’a
4 A
Da mesma forma ao se definir algo como function ele não será mais avaliado.
1 > (function -)
2 #<SYSTEM -FUNCTION ->
3 > #’-
4 #<SYSTEM -FUNCTION ->
14 / 47
15. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Binding - Atribuição
Binding é uma atribuição que ocorre com as variáveis de uma lista de parâmetros de
uma função sempre que a função é chamada. Pode ser feito em qualquer parte com o
let.(Atenção para escopo local).
1 > (let ((a 2)
2 (b 3)
3 (c 0))
4 (setq c (+ a b)) c)
5 5
6 > (setq c 4)
7 4
8 > (let ((c 5)) c)
9 5
10 > c
11 4
15 / 47
16. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Definindo Conjunto de Valores nil
Duas formas diferentes de fazer
1 > (let ((a nil) (b nil))
2 (format nil " ~s ~s " a b))
3 " NIL NIL "
4 > (let (a b) (format nil " ~s ~s " a b))
5 " NIL NIL "
16 / 47
17. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Observações
• Variáveis definidas no let não tem acesso a outras também definidas no let.
• Variáveis já existentes podem provocar efeitos inesperados quando reutilizadas no
let. Para resolver este problema usa-se o let *.
1 > (setq a 2)
2 2
3 > (setq b 2)
4 2
5 > (let* ((x a) (y b)) (format nil " ~s ~s " x y))
6 " 2 2 "
17 / 47
18. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Escopo Dinâmico
Variáveis de escopo dinâmico em Lisp são variáveis cujo valor é determinado pela pilha
de chamadas ativas em vez de seguir a estrutura de blocos do programa, como as
variáveis de escopo léxico. Em outras palavras, o valor de uma variável de escopo
dinâmico é determinado pelo contexto de execução atual, não pelo contexto de
definição do bloco onde a variável foi declarada. (Trata-se de uma espécie de variável
global)
18 / 47
19. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Exemplo de Uso de Variáveis de Escopo Dinâmico
1 (defvar *variavel -dinamica* 10) ; Declaracao de uma variavel de
escopo dinamico
2 (defun funcao -a ()
3 (setq *variavel -dinamica* 20) ; Define o valor da variavel
dinamica
4 (funcao -b))
5 (defun funcao -b ()
6 (format t "Valor da variavel dinamica em funcao -b: ~a~%"
*variavel -dinamica *))
7 (format t "Valor da variavel dinamica em funcao -a: ~a~%"
*variavel -dinamica *)
8 (funcao -a)
9 (format t "Valor da variavel dinamica apos chamar funcao -a: ~a~%"
*variavel -dinamica *)
19 / 47
20. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Saídas
Saídas do programa anterior:
1 Valor da variavel dinamica em funcao -a: 10
2 Valor da variavel dinamica em funcao -b: 20
3 Valor da variavel dinamica apos chamar funcao -a: 20
20 / 47
21. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Vetores - Arrays
A função make-array faz um array. A função aref acessa seus elementos. Todos os
elementos de um array são inicialmente setados para nil.
1 > (make -array ’(3 3))
2 #2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
3 > (aref * 1 1)
4 NIL
5 > (make -array 4)
6 #(NIL NIL NIL NIL)
7 > (setq matriz (make -array ’(3 3)))
8 #2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
9 > matriz
10 #2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
11 > (setf (aref matriz 1 2) 10)
12 10
13 > (print (aref matriz 1 2))
14 10
21 / 47
22. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Strings
Um string é uma sequência de caracteres entre aspas duplas. LISP representa um
string como um array de tamanho variável de caracteres.Você pode escrever um string
que contém a aspa dupla, precedendo-a de um backslash . Um backslash duplo
representa um :
"abcd"tem 4 caracteres
"”"tem 1 caractere
""tem 1 caractere
22 / 47
23. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Funções Para Manipulação de Strings
1 > (concatenate ’string "abcd" "efg")
2 "abcdefg"
3 > (char "abc" 1)
4 #b ;LISP precede os caracteres por #
5 #b
6 >
7 #b
8 > (char "abc" 2)
9 #c
10 > (concatenate ’string ’(#a #b) ’(#c))
11 "abc"
12 > (concatenate ’list "abc" "de")
13 (#a #b #c #d #e)
14 > (concatenate ’vector ’#(3 3 3) ’#(3 3 3))
15 #(3 3 3 3 3 3)
23 / 47
24. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Structs - Estruturas
Para criar estruturas usamos a função defstruct.
1 >(defstruct estudante
2 nome
3 endereco
4 telefone)
5 ESTUDANTE
Automaticamente o lisp cria as funções make-estudante, estudante-nome,
estudante-endereco, estudante-telefone.
24 / 47
25. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Structs - Estruturas
Estruturas em Lisp são análogas as estruturas em C. Ex.
1 > (make -estudante)
2 #S(ESTUDANTE :NOME NIL :ENDERECO NIL :TELEFONE NIL)
3 > (make -estudante :nome "Josefina"
4 #S(ESTUDANTE :NOME "Josefina" :ENDERECO NIL :TELEFONE NIL)
5 > (make -estudante :nome "Siriema" :endereco "rua abaete 43"
:telefone "0212121")
6 #S(ESTUDANTE :NOME "Siriema" :ENDERECO "rua abaete 43" :TELEFONE
"0212121")
25 / 47
26. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
setf
Alguns forms em LISP naturalmente definem uma locação na memória. Por exemplo,
se x é uma estrutura do tipo estudante, então (estudante-nome x) define o campo
nome do valor de x. Se o valor de y é um array unidimensional, então (aref y 2) define
o terceiro elemento de y. 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.
26 / 47
27. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Exemplos do setf
1 >(setq a (make -array 3))
2 #(NIL NIL NIL)
3 > (aref a 1)
4 NIL
5 > (setf (aref a 1) 3)
6 3
7 > a
8 #(NIL 3 NIL)
9 > (aref a 1)
10 3
27 / 47
28. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
setf
Setf é a única maneira de se setar os valores de um array ou os campos de uma
estrutura.
1 > (defstruct foo bar)
2 FOO
3 > (setq a (make -foo))
4 #S(FOO :BAR NIL)
5 > (foo -bar a)
6 NIL
7 > (setf (foo -bar a) 3)
8 3
9 > a
10 #S(FOO :BAR 3)
28 / 47
29. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
setf
Variações no uso
1 >(setf a (make -array 1)) ;setf em uma variável equivale ao
setq
2 #(NIL)
3 > (push 5 (aref a 0)) ;push pode agir como o setf
4 (5)
5 > (pop (aref a 0)) ;pop também
6 5
7 > (setf (aref a 0) 5)
8 5
9 [46]> (incf (aref a 0))
10 6
11 [49]> (aref a 0)
12 6
29 / 47
30. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Mais Sobre Booleanos e Condicionais
• LISP usa o símbolo auto-avaliante NIL para significar FALSO. Qualquer outra
coisa significa VERDADEIRO.
• Usualmente utiliza-se o símbolo t para significar TRUE.
• AND não vai avaliar argumentos à direita daquele que faz a função avaliar para
NIL, enquanto OR não avalia nenhum à direita do primeiro verdadeiro.
• LISP também provê uma série de forms para execução condicional. O mais
simples é o IF, onde o primeiro argumento determina se o segundo ou o terceiro
será avaliado. Ex.
1 > (if t 5 6)
2 5
3 > (if nil 5 6)
4 6
5 > (if 4 5 6)
6 5
30 / 47
31. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
When e Unless
when e unless podem substituir o if em muitos casos:
1 >(when t 3)
2 3
3 > (when nil 3)
4 NIL
5 > (unless t 3)
6 NIL
7 > (unless nil 3)
8 3
9 > (when t ; when admite múltiplos comandos
10 (setq a 5)
11 (+ a 6)
12 )
31 / 47
32. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Multiplos Comandos com Progn
Para colocar mais de um comando em uma das cláusulas usa-se o form progn
1 > (setq a 7)
2 7
3 > (setq b 0)
4 0
5 > (setq c 5)
6 5
7 > (if (> a 5)
8 (progn
9 (setq a (+ b 7))
10 (setq b (+ c 8)))
11 (setq b 4)
12 )
13 13
32 / 47
33. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Macros
Além de progn existem MACROS em LISP para definir blocos. Uma muito usada é
prog. Prog permite, entre outras coisas, a declaração explícita de variáveis locais, além
de retorno explícito. Ex.
1 >(defun F2.17a nil
2 (prog (i j) ;define i e j como variáveis locais inicializadas com
nil
3 (setq i (read))
4 (setq j (read))
5 (return (print (- i j)))
6 ))
7 F2.17A
8 > (F2.17a)
9 3
10 5
11 -2
12 -2
33 / 47
34. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Lista de Exercícios
Faça programas em lisp para:
1. Ler dois números, imprimir sua soma e acrescentar 3 ao resultado. Assim 5 e 11
devem produzir 16 e 19 na tela.
2. Ler dois valores e imprimir sua soma como uma lista. Deste modo 6 e 7 devem
produzir a lista (13).
3. Ler três números e imprimí-los como uma lista.
4. Ler três números e imprimir a soma dos dois primeiros e o produto desta pelo
terceiro como uma lista.
34 / 47
35. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Lista de Exercícios - Cont
Escreva funções em lisp para:
5. Devolva o valor 1 se seu parâmetro for maior que zero, -1 se for negativo, 0 se for
zero..
6. Leia um nome. Se este for o mesmo nome que o dado como parâmetro, a função
deve imprimir uma saudação simples e devolver o valor t. Se for diferente, não
deve imprimir nada e devolver nil..
7. Dados três parâmetros, se o primeiro for um asterisco, os outros dois serão
multiplicados; se for uma barra, o segundo deve ser dividido pelo terceiro; se não
for nenhum dos dois, imprima uma mensagem de erro e assuma o valor zero. A
função deve devolver como valor o resultado da operação aritmética.
8. Ler três números e imprimir a soma dos dois primeiros e o produto desta pelo
terceiro como uma lista.
35 / 47
36. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Lista de Exercícos - Cont
9. Devolva t se seu primeiro parâmetro estiver no conjunto de valores especificado
pelo seu segundo e terceiro parâmetros e nil se não estiver. Asim: (func-4 5 5
7) = t e (func-4 6 5 7) = nil.
10. Aceite um valor simples e uma lista como parâmetros. Devolva t se o valor estiver
na lista, nil caso nao esteja (este exercício pode ser resolvido de forma recursiva -
pense um pouco...).
36 / 47
37. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Soluções
37 / 47
38. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
LOOPs explícitos - Iterações
A construção de iteração mais simples em LISP é loop: um loop repetidamente
executa seu corpo até que ele encontre um form especial do tipo return.
1 > (setq a 4)
2 4
3 > (loop
4 (setq a (+ a 1))
5 (when (> a 7) (return a))
6 )
7 8
8 > (loop
9 (setq a (- a 1))
10 (when (< a 3) (return))
11 )
12 NIL
38 / 47
39. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
dolist
Uma dolist liga uma variável aos elementos de uma lista para realização de atividades
iterativas.(map)
1 >(dolist (x ’(a b c)) (print x))
2 A
3 B
4 C
5 NIL
dolist sempre retorna NIL.
39 / 47
40. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
do
Form de iteração mais complicado. Ex.
1 (do ((x 1 (+ x 1)) ;variável x, com valor inicial 1
2 (y 1 (* y 2))) ;variável y, com valor inicial 1
3 ((> x 4) y) ;retorna valor de y quando x > 4
4 (print y) ;corpo
5 (print ’trabalhando)) ;corpo
6 1
7 TRABALHANDO
8 2
9 TRABALHANDO
10 4
11 TRABALHANDO
12 8
13 TRABALHANDO
14 16
40 / 47
41. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Detalhes do do
• A primeira parte do do especifica quais variáveis que devem ser ligadas, os seus
valores iniciais e como eles devem ser atualizados.
• A segunda parte especifica uma condição de término e um valor de retorno.
• A última parte é o corpo.
• do* muda a forma de avaliação das variáveis para imediata.
41 / 47
42. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Diferenças entre do e do*
Experinente o código abaixo usando o do e o do*
1 (let ((x 1) (y 2))
2 (do ((x y (1+ x)) ; expressão de atribuição para x
3 (y x (1+ y))) ; expressão de atribuição para y
4 ((> x 10) x) ; condição de saída
5 (print (list x y)))) ; expressão a ser executada
42 / 47
43. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Saídas Não Locais
O form especial return mencionado na seção de iteração é um exemplo de um return
não-local (execução interrompida). Outro exemplo é o form return-from, o qual
retorna um valor da função que o envolve.
1 > (defun foo (x)
2 (return -from foo 3)
3 x
4 )
5 FOO
6 > (foo 17)
7 3
8 > (foo 13)
9 3
43 / 47
44. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Blocos Nomeados
Blocos podem ser nomeados inclusive com nil podendo ser utilizados com o return-from
1 > (block foo
2 (return -from foo 7) ; retorna 7 do bloco foo
3 3
4 )
5 7
6 > (block nil
7 (return 7) ; retorna 7 do bloco nil
8 3
9 )
10 7
44 / 47
45. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Error
Outro tipo de saída não local: erro..
1 >(error "isto é um erro")
2
3 *** - isto é um erro
4 The following restarts are available:
5 ABORT :R1 Abort main loop
6 Break 1 [19]>
O interpretador entra em Debug.
45 / 47
46. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
Exercicios
A completar
46 / 47
47. Manipulação de Variáveis e Argumentos Formatação de Saída e Forms Tipos de Dados Complexos Iteratividade
FIM
47 / 47