Nome: ? | Matrícula: ?

Programação funcional: Lisp (1958)

Programação simbólica, programação funcional.

Diversas implementações e dialetos: Common Lisp, Scheme, Racket, Clojure.

Usado como linguagem de script no AutoCAD, no Audacity (editor de áudio), no GIMP (editor de imagens) e no Emacs (editor de texto).

Observações

Clique em qualquer expressão de código para avaliar com o interpretador Lisp e ver o resultado no console do navegador.

Referências:

Lisp: teoria

Dados em Lisp são expressões simbólicas (chamadas de s-expressions, ou sexps, do inglês symbolic expressions) que podem ser átomos ou listas.

Átomo: sequência de letras e dígitos e outros caractees que não são usados em Lisp. Ex.: 1, altura, print, +.

Lista: ( seguido de zero ou mais átomos separados por espaços, seguido de ). Exemplo: (a), (+ 2 3), (print 5).

Expressões podem ser avaliadas para um valor. Em particular, alguns átomos possuem valor. Exemplos: 1 (número um), -3.14 (número 3,14 negativo). Outros átomos, como abc, não possuem valor, a princípio.

Listas também podem ser avaliadas para valores. Em particular, um núcleo básico de Lisp pode ser definido a partir de regras de reescrita de listas que começam com os seguintes símbolos: quote car cdr cons equal atom cond lambda label:

Note, a princípio, uma lista não tem valor definido, a não ser se enquadre em um dos casos listados acima.

Exemplos e contra-exemplos:

Para evitar definir uma função toda vez que ela é usada, podemos defini-la usando (defun f (v1 ... vn) e). Depois disso, (f x1 ... xn) é avaliado através da avaliação de e com as variáveis v1 … vn assumindo os valores x1 … xn. Exemplo:

function(str, info) { return simplesEval(str, info); }
function(str, info) { return simplesEval(str, info); }

Esse conjunto de regras define o núcleo da linguagem Lisp. Outras construções da linguagem podem ser definidas com base nessas regras.

Abreviações comuns

Manipulação de strings

Usamos aspas para representar strings. Exemplo: "alo mundo".

Números e matemática

Escopo

def defun let let*

(defun alo-mundo () (print "Alo, mundo!"))
(defun alo (nome pontuacao)
    (print (concat "Alo, " nome pontuacao)))
(alo-mundo)
(alo "Brasil" "!!!")
(def pi 3.14159265359)
(print (cos (* 2 pi)))

Uso: (let ((v1 e1) ... (vn en)) corpo) – avalia a expressão “corpo” usando as constantes v1 … vn (com valores e1 … en) definidas localmente.

(let
    ((pi 3.14159265359)
    (raio 30))
    (print (* pi raio raio)))

Se existir dependência entre as definições de constantes (isto é, pelo menos uma das constantes é definida com base em uma constante definida anteriormente), é necessário usar let*. Exemplo:

function(str, info) { return simplesEval(str, info); }

Prática

Definimos a função print para imprimir no console do navegador.

function(str, info) { return multiEval(str, info); }
function(str, info) { return multiEval(str, info); }

Função map

function(str, info) { return multiEval(str, info); }

Agora é com você. Defina as seguintes funções:

Função (length l) (retorna o comprimento da lista l, isto é, seu número de elementos):

function(str, info) { return multiEval(str, info); }

Função (filter f l) (retorna uma cópia da lista l contendo apenas os elementos para os quais a função f retorna true):

function(str, info) { return multiEval(str, info); }

Função (all f l) (indica se a função f retorna verdadeiro para todos os elementos de l):

function(str, info) { return multiEval(str, info); }

Função (atom-list l) (indica se todos os elementos de l são átomos):

function(str, info) { return multiEval(str, info); }

Função (member x l) (indica se o elemento x está presente na lista l):

function(str, info) { return multiEval(str, info); }

Função (freq x l) (indica quantas vezes o elemento x aparece na lista l):

function(str, info) { return multiEval(str, info); }

Função (is-set l) (indica se l é um conjunto, isto é, uma lista na qual todos os elementos são distintos) – use a função member:

function(str, info) { return multiEval(str, info); }

Função (reduce f l i) (aplica a função f sobre um acumulador para cada valor da lista l, da esquerda pra direita, para reduzi-la a um único valor; o valor inicial do acumulador é i):

function(str, info) { return multiEval(str, info); }

Reescreva a função (all f l) usando reduce:

function(str, info) { return multiEval(str, info); }