Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


artigo - Linguagens de Programação - Scheme e Lisp, Manuais, Projetos, Pesquisas de Cultura

artigo final do trabalho da disciplina de Linguagens de Programação do 4º período de Engenharia de Computação do Ceunes-Ufes. Eu estudei as linguagens Scheme e Common Lisp, que são os dialetos mais comuns do lisp na atualidade. Este artigo faz um apanhado geral de ambas linguagens, falando sobre a sintaxe, histórico, métodos de implementação, amarrações, sistema de tipo, exceções, etc. disciplina ministrada pelo prof. Ayrton Monteiro Cristo.

Tipologia: Manuais, Projetos, Pesquisas

Antes de 2010

Compartilhado em 13/09/2008

eliezer-de-souza-da-silva-8
eliezer-de-souza-da-silva-8 🇧🇷

4.8

(9)

16 documentos

1 / 15

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Scheme e Common Lisp
Eliezer de Souza da Silva
7 de julho de 2008
UFES - Universidade Federal do Esp´ırito Santo
Centro Universit´ario Norte do Esp´ırito Santo
Departamento de Engenharia e Ciˆencia Exatas
Engenharia de Computa¸ao
S. Mateus - ES - Brasil
Resumo
LISP foi a primeira linguagem de programa¸ao a implementar concei-
tos de programa¸ao funcional. Scheme e Common Lisp ao os dialetos do
Lisp com uso mais generalizado atualmente. Este trabalho pretende fazer
uma descri¸ao destas duas linguagens enfatizando os conceitos, ecnicas e
propriedades gerais de Linguagens de Programa¸ao implementadas nestas
linguagens.
Palavras-chave: Linguagens de Programa¸ao, LISP, Scheme, Com-
mon Lisp.
1 Introdu¸ao
O advento da linguagem de programa¸ao LISP, idealizada por John McCarthy
entre 1956 e 1958 com o objetivo de ser usada em Inteligˆencia Artificial (IA)
e em processamento alg´ebrico simb´olico, marcou o in´ıcio do chamado para-
digma funcional de programa¸ao. Os fundamentos matem´aticos deste para-
digma encontram-se no alculo-lambda, criado por Alonzo Church, na ecada
de 30. A estrutura do LISP permite que sejam feitas modifica¸oes e extens˜oes
`a linguagem, ou at´e mesmo a cria¸ao de novos dialetos da linguagem, com uma
certa facilidade. Devido a esta caracter´ıstica particular, diversos dialetos do
LISP apareceram em institui¸oes de ensino, empresas privadas, grupos de pes-
quisas ou at´e mesmo como projetos pessoais, sendo que, inicialmente, pouca ou
nenhuma padroniza¸ao foi adotado para o LISP. Muitos destes dialetos se tor-
naram obsoletos ou ao encontrados somente em alguns sistemas operacionais
ou softwares espec´ıficos. Scheme e Common Lisp ao os dois maiores dialetos
do LISP em uso atualmente. Neste artigo iremos, `a luz do conceitos de lin-
guagens de programa¸ao, estudar as principais caracter´ısticas das linguagens de
programa¸ao Scheme e Common Lisp.
1
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Pré-visualização parcial do texto

Baixe artigo - Linguagens de Programação - Scheme e Lisp e outras Manuais, Projetos, Pesquisas em PDF para Cultura, somente na Docsity!

Scheme e Common Lisp

Eliezer de Souza da Silva

7 de julho de 2008

UFES - Universidade Federal do Esp´ırito Santo Centro Universit´ario Norte do Esp´ırito Santo Departamento de Engenharia e Ciˆencia Exatas Engenharia de Computa¸c˜ao S. Mateus - ES - Brasil

Resumo LISP foi a primeira linguagem de programa¸c˜ao a implementar concei- tos de programa¸c˜ao funcional. Scheme e Common Lisp s˜ao os dialetos do Lisp com uso mais generalizado atualmente. Este trabalho pretende fazer uma descri¸c˜ao destas duas linguagens enfatizando os conceitos, t´ecnicas e propriedades gerais de Linguagens de Programa¸c˜ao implementadas nestas linguagens.

Palavras-chave: Linguagens de Programa¸c˜ao, LISP, Scheme, Com- mon Lisp.

1 Introdu¸c˜ao

O advento da linguagem de programa¸c˜ao LISP, idealizada por John McCarthy entre 1956 e 1958 com o objetivo de ser usada em Inteligˆencia Artificial (IA) e em processamento alg´ebrico simb´olico, marcou o in´ıcio do chamado para- digma funcional de programa¸c˜ao. Os fundamentos matem´aticos deste para- digma encontram-se no c´alculo-lambda, criado por Alonzo Church, na d´ecada de 30. A estrutura do LISP permite que sejam feitas modifica¸c˜oes e extens˜oes a linguagem, ou at´e mesmo a cria¸c˜ao de novos dialetos da linguagem, com uma certa facilidade. Devido a esta caracter´ıstica particular, diversos dialetos do LISP apareceram em institui¸c˜oes de ensino, empresas privadas, grupos de pes- quisas ou at´e mesmo como projetos pessoais, sendo que, inicialmente, pouca ou nenhuma padroniza¸c˜ao foi adotado para o LISP. Muitos destes dialetos se tor- naram obsoletos ou s˜ao encontrados somente em alguns sistemas operacionais ou softwares espec´ıficos. Scheme e Common Lisp s˜ao os dois maiores dialetos do LISP em uso atualmente. Neste artigo iremos,a luz do conceitos de lin- guagens de programa¸c˜ao, estudar as principais caracter´ısticas das linguagens de programa¸c˜ao Scheme e Common Lisp.

1.1 Hist´orico

N˜ao se pretende fazer uma descri¸c˜ao hist´orica detalhada do LISP, visto que existe na literatura artigos que j´a a fizeram. McCarthy [2] divide a hist´oria do LISP em trˆes per´ıodos, o primeiro ´e denominado “pr´e-hist´oria” do LISP, entre o ver˜ao de 1956 e 1958, durante o qual as principais ideias da linguagem foram concebidas, entre 1958 e 1962, durante o qual a linguagem foi implementada e utilizada na resolu¸c˜ao de problemas de inteligˆencia artificial e ap´os 1962, que v´arias ideias foram incorparadas `a linguagem e diversas implementa¸c˜oes foram feitas, em geral cada uma seguindo caminhos distintos. A principal motiva¸c˜ao de McCarthy na concep¸c˜ao da linguagem era de facilitar experimentos com um sistema proposto ao grupo de Inteligˆencia Artificial do MIT, chamado Advice Taker. O sistema deveria receber instru¸c˜oes declarativas e imperativas e exibir senso comum aos cumprir as instru¸c˜oes. Fazia-se necess´ario ent˜ao um sistema de programa¸c˜ao capaz de manipular express˜oes simb´olicas que representassem as senten¸cas declarativas e imperativas, de modo que o Advice Taker pudesse fazer dedu¸c˜oes. A estrutura de dados para representar as express˜oes e os dados esco- lhida foi as chamadas S-Expressions (express˜oes simb´olicas). Uma S-expression ´e um express˜ao que contem os seguintes s´ımbolos ’(’ e ’)’ delimitando o come¸co e o fim da express˜ao, e ´atomos, que s˜ao sequˆencias de letras que tem como ´unica propriedade serem iguais se forem escritas da mesma maneira. Os operadores de uma express˜ao-S s˜ao pr´e-fixados. Steele e Gabriel [1] partem do artigo de MacCarthy e fazem uma digress˜ao hist´orica entre as principais implementa¸c˜oes e dialetos do LISP que apareceram entre 1960 e 1993, culminando nos esfor¸cos de padroniza¸c˜ao do LISP e o aparecimento do Common Lisp. E feito um estudo´ da evolu¸c˜ao de algumas caracter´ısticas espec´ıficas da linguagem ao longo dos anos.

Scheme foi projetada em 1975,por Guy Steele e Gerald Sussman, enquanto trabalhavam do Laborat´orio de Inteligˆencia Artificial do MIT. Scheme foi pro- jetado para ter uma sintaxe e semˆantica simples e trazer conceitos modernos de linguagem de programa¸c˜ao para a comunidade Lisp (mais precisamente estru- tura de blocos aninhados ALGOL-like, procedimentos, fun¸c˜oes e continua¸c˜oes como objetos de primeira classe, escopo est´atico, etc).

O Common Lisp ´e fruto de um esfor¸co de diversas equipes de projetistas de LP, cientistas e entusisatas da comunidade LISP, na produ¸c˜ao de um dialeto LISP que padronizasse as principais variantes do LISP. E uma linguagem grande, que´ surgiu como tentativa de juntar em uma especifica¸c˜ao contribui¸c˜oes de prati- camente todos os maiores dialetos do LISP (sucessor do MacLisp, fortemente influenciado pelo ZetaLisp e em parte pelo Scheme e InterLisp).

2 Propriedades e Caracter´ısticas Gerais de Scheme

e Common Lisp

Nesta se¸c˜ao iremos tratar das caracter´ısticas e propriedades do Scheme e Com- mon Lisp segundo crit´erios usuais em estudo de Linguagens de Programa¸c˜ao.

  • Reusabilidade: defini¸c˜oes de fun¸c˜oes gen´ericas, polim´orficas e a tipagem dinˆamica e fraca permitem muita reutiliza¸c˜ao de c´odigo.
  • Modificabilidade:
  • Portabilidade:

2.2 Paradigmas da LP e M´etodos de Implementa¸c˜ao

O principal paradigma de programa¸c˜ao do LISP, Scheme e Common Lisp ´e o funcional, mas estas LPs n˜ao s˜ao consideradas puramente funcionais, visto que existem constru¸c˜oes na linguagem que s˜ao caracter´ısticas do paradigma imperativo por envolverem mudan¸ca de estado na mem´oria (em Scheme temos, por exemplo, o (set! a b) que muda o estado da vari´avel a). O Common Lisp tamb´em suporta programa¸c˜ao orientada a objetos. O subconjunto da linguagem que ´e puramente funcional ´e usualmente denominado “Lisp Puro”.

O m´etodo mais de comum de implementa¸c˜ao das linguagens em estudo ´e a interpreta¸c˜ao. Devido a sintaxe simples e ao uso da mesma representa¸c˜ao ex- terna para dados e c´odigo de programas (espress˜oes-S), ´e relativamente f´acil implementar um interpretador. Existem tamb´em compiladores para Scheme e CL (Common Lisp). O pr´oprio Steele projetou um compilador para Scheme chamado Rabbit. Existem diversos compiladores para o CL. O CLISP ´e uma implementa¸c˜ao do Common Lisp, que inclue um interpretador e um compi- lador byte-code, ´e um software gratuito e faz parte do Projeto GNU e est´a dispon´ıvel sob a licen¸ca GPL (GNU General Public License). Um outro compi- lador gratuito de CL ´e o GNU Common Lisp (GCL) que compila para um codigo intermedi´ario em C, e depois chama o compilador de C que gera o execut´avel.

3 Amarra¸c˜oes

Uma amarra¸c˜ao ´e uma associa¸c˜ao entre entidades de programa¸c˜ao. O tempo de amarra¸c˜ao ´e o momento que esta vincula¸c˜ao se desenvolve. Ambos con- ceitos s˜ao importantes na semˆantica das linguagens de programa¸c˜ao. Neste t´opicos iremos tratar de como s˜ao feitas as amarra¸c˜oes em Scheme e CL. Antes de come¸carmos a efetivamente explorar o assunto devemos saber como referir a uma entidade de programa¸c˜ao. Usualmente na defini¸c˜ao da linguagem s˜ao escolhidas maneiras de se referir a uma entidade de programa¸c˜ao atrav´es dos identificadores, que geralmente s˜ao cadeias de caracteres que servem de “nome” para uma entidade. N˜ao ´e qualquer cadeia de caracter que serve de identifica- dor. Do universo de todas sequˆencias de caracteres ´e definido um subconjunto, fazendo uso de algumas regras, que poder˜ao ser utilizadas como identificadores v´alidos. Em Scheme este conjunto de identificadores v´alidos pode variar um pouco em implementa¸c˜oes diferentes, no entanto todas implementa¸c˜oes devem seguir algumas regras gerais na forma¸c˜ao de identificadores. Como regra geral um identificador v´alido n˜ao pode come¸car com um n´umero, portanto qualquer sequˆencia de caracteres que tenha como primeiro caracter uma letra ou um “ca- racter especial” ( & $ % { } ˆ ˜ ! * / : < = > ?) ´e um identificador v´alido. A sintaxe formal dos indentificadores em Scheme escrita na Forma Extendida

de Backus-Naur (EBNF) pode ser encontrada por exemplo na se¸c˜ao 7.1.1 do Revised^5 Report (R^5 RS). Scheme e CL n˜ao s˜ao case sensitive.

3.1 Ambientes de Amarra¸c˜ao e Escopo

O ambiente de amarra¸c˜ao em um ponto ´e o conjunto de todas amarra¸c˜oes vis´ıveis neste ponto. ´E atrav´es do ambiente de amarra¸c˜ao que ´e determinado o significado de cada identificador ao longo do programa. Nem toda amarra¸c˜ao ´e vis´ıvel em todo programa, uma amarra¸c˜ao est´a sujeita a um escopo de visibili- dade, que ´e uma regi˜ao do programa onde a amarra¸c˜ao ´e vis´ıvel. Este escopo pode ser est´atico ou dinˆamico. No escopo est´atico o ambiente de amarra¸c˜ao ´e determinado antes da execu¸c˜ao do programa, pela organiza¸c˜ao do texto, e por- tanto estaticamente. O projeto da linguagem Scheme rompeu com a tradi¸c˜ao dos dialetos anteriores do LISP e adotou escopo est´atico e, seguindo o projeto do Algol, uma estrutura de blocos aninhadas. Essa mudan¸ca de atitude em rela¸c˜ao ao escopo de vari´aveis foi muito influente na comunidade LISP, de modo que o Common Lisp adotou tamb´em por padr˜ao o escopo est´atico, embora exista a possibilidade de uma vari´avel ter escopo dinˆamico se ela for explicitamente de- clarada como uma vari´avel “especial”. Uma vari´avel pode ser declarada como “especial” usando o procedimento defvar. Vari´aveis “especiais” s˜ao normal- mente utilizadas como vari´aveis globais.

Embora seja um conceito ligeiramente distinto do de ambiente de amarra¸c˜ao, citaremos o conceito de namespace existente em CL, que ´e um conjunto de amarra¸c˜oes restritas a algum tipo. Um objeto do tipo package determina um namespace, ele faz o mapeamento de um nome de s´ımbolo para um s´ımbolo. Em CL podemos ter identificadores no mesmo programa que pertencem a na- mespaces diferentes, por exemplo, fun¸c˜oes e vari´aveis pertencem a namespaces diferentes. Tomemos o seguinte exemplo, (defun x (x) (+ x 1)). Neste caso o identificador x depois de defun designa o nome da fun¸c˜ao, e portanto pertence ao namespace das fun¸c˜oes, o x usado como vari´avel ligada pertence ao names- pace das vari´aveis e, portanto n˜ao existe conflito algum referente `a denota¸c˜ao do identificador em cada ponto do programa. Se o argumento de uma fun¸c˜ao ´e uma outra fun¸c˜ao, ela deve ser explicitamente declarada como tal, usando o operador especial “function” ou a sua abrevia¸c˜ao #’. J´a em Scheme n˜ao existe distin¸c˜ao entre namespace de fun¸c˜oes e de vari´aveis, o que proporciano uma certa flexi- bilidade ao programador na hora de criar fun¸c˜oes mais gen´ericas. Existe uma controv´ersia na comunidade LISP se um namespace de fun¸c˜oes separados do de vari´aveis ´e, de fato, uma desvantagem, essa controv´ersia ´e conhecida como Debate Lisp-1 vs. Lisp-2.

3.2 Defini¸c˜ao de Constantes e Vari´aveis

N˜ao existe uma maneira de declarar ou definir constantes explicitamente em Scheme e CL. E poss´´ ıvel criar uma amarra¸c˜ao entre um identificador e um valor. Este valor ser´a constante, mas a qualquer momento ´e poss´ıvel criar uma nova amarra¸c˜ao com este mesmo identificador a um novo valor. Mesmo amarra¸c˜oes pr´e-definidas podem ser refeitas. Em Scheme fun¸c˜oes e vari´aveis pr´e-definidas podem ser redefinidas (´e perfeitamente legal a defini¸c˜ao (define sin 7)). Em CL somente vari´aveis pr´e-definidas podem ser redefinidas, um package pode

(define nomefunc (lambda (argumentos) corpo)) (define (nomefunc argumentos) corpo)

Em CL a defini¸c˜ao de fun¸c˜oes ´e feita usando o macro defun. Segue a sintaxe de defini¸c˜oes de fun¸c˜oes em CL: (defun nomefunc (argumentos) corpo)

3.5 Defini¸c˜oes Sequˆenciais e Recursivas

A defini¸c˜ao de fun¸c˜oes em LPs cujo principal paradigma ´e o funcional, em geral se d´a atrav´es de defini¸c˜oes recursivas. Scheme e CL n˜ao fogem a regra, de modo que, n˜ao obstante em ambas linguagens haver fun¸c˜oes especiais que permitem fazer repeti¸c˜oes no estilo imperativo, usando itera¸c˜oes com loops, o uso de recurs˜ao nestes casos e generalizado em ambas linguagens. E poss´´ ıvel fazer defini¸c˜oes sequˆenciais utilizando o let, lambda e begin em Scheme. (define (somavarios g) (let (x 2) (y (+ x 1)) (- (* y x) g)))

(define somavarios (lambda (g) (define x 2) (define y (+ x 1)) (- (* y x) g)))

4 Tipos de Dados

Discutiremos inicialmente o sistema de tipos de dados do Scheme, e em se- guida faremos uma breve discuss˜ao dos tipos de dados do CL, visto este ser extenso e complexo. Scheme ´e uma linguagem fracamente tipada e a verfica¸c˜ao de tipos ´e feita dinamicamente em tempo de execu¸c˜ao. Temos fun¸c˜oes que se aplicam a qualquer tipo de lista, funcionam para praticamente todos os tipos da hierarquia de tipos num´ericos e que aceitam praticamente qualquer tipo de parˆametro (eval). O R^5 RS define uma disjun¸c˜ao dos seguintes tipos de dados em Scheme: number symbol(atoms) char vector pair (lists) string port procedure (function) Nenhum valor ou objeto Scheme pode pertencer a mais de dos tipos supracita- dos.

4.1 N´umeros

A comunidade Lisp tradicionalmente nunca se dedicou muito `a computa¸c˜ao num´erica. No projeto do Common Lisp foram adotadas estrat´egias cuidado- samente elaboradas pensando na otimiza¸c˜ao de c´odigo e organiza¸c˜ao da com- puta¸c˜ao num´erica. Scheme adota estas recomenda¸c˜oes e implementa um sis- tema simplificado e generalizado de tipos num´ericos do CL consistente com os prop´ositos do projeto da linguagem. O sistema de tipos num´ericos formam uma torre de subtipos, segundo uma classifica¸c˜ao matem´atica relativa a classe de n´umeros que estes subtipos representam: number complex real rational integer

Os n´umeros em Scheme s˜ao tratados como dados abstratos e toda opera¸c˜ao sobre os n´umeros tenta se afastar o m´aximo poss´ıvel da sua representa¸c˜ao na m´aquina. E feita uma distin¸´ c˜ao entre os n´umeros Scheme e sua representa¸c˜ao na m´aquina, podendo haver at´e duas representa¸c˜oes de um n´umero, por exemplo usando ponto flutuante (flonum) e ponto fixo (fixnum).

Uma propriedade importante dos n´umeros Scheme, ´e a distin¸c˜ao entre n´umeros exatos e inexatos. Um n´umero ´e exato se pode ser escrito como uma constante exata, ou derivado de um conjunto de opera¸c˜oes exatas sobre n´umeros exatos, caso contr´ario ´e inexato. Qualquer n´umero da torre de subtipos num´ericos pode ser exato ou inexato, a exatid˜ao n˜ao ´e propriedade do tipo do n´umero, mas sim de como o n´umero foi definido (ou das opera¸c˜oes que deram como resultado o n´umero).

No R^5 RS n˜ao ´e requerido que uma implementa¸c˜ao de Scheme suporte toda a torre de subtipos num´ericos, no entanto ela deve implementar um subcon- junto coerente da torre. Quanto `a cardinalidade dos tipos n˜ao ´e feita nenhuma exigˆencia, exceto que uma implementa¸c˜ao deve dar suporte a n´umeros intei- ros exatos de cardinalidade suficiente para serem usados como ´ındices de listas, vetores e strings. E recomendado que as implementa¸´ c˜oes suportem n´umeros exa- tos de tamanho praticamente ilimitado e que, caso suportem n´umeros de ponto flutuante, sigam as recomenda¸c˜oes das padr˜ao de 32-bit e 64-bit da IEEE.

4.2 Pares e Listas

Um Pair(par) ´e uma estrutura de registro com dois campos chamadas (por motivos hist´oricos) de car (Address Register) e cdr (Decrement Register). Para criar um valor do tipo par, usamos a fun¸c˜ao (cons a b) e para acessarmos os campos car e cdr, usamos fun¸c˜oes homˆonimas aos campos.

Este tipo de dado ´e usado para definir listas recursivamente. Um lista ´e empty (que ´e um tipo especial) ou ´e uma par cujo campo cdr contem uma lista. Os objetos nos campos car s˜ao os elementos da lista. Lista ´e a estrutura de dados usada para representar tanto dados como programas.

5 Vari´aveis e Constantes

Na se¸c˜ao de amarra¸c˜oes vimos como criar um vari´avel em Scheme e Common Lisp, usando os macros define, let e setf. Nesta se¸c˜ao iremos concentrar no entendimento do conceito de vari´aveis e constantes tendo em vista um modelo de armazenamento de vari´aveis e constantes.

Conceitualmente podemos pensar nas vari´aveis como ponteiros para valores na mem´oria. Estes valores s˜ao imut´aveis, o valor do n´umero 1 ´e uma entidade na mem´oria que ´e ´unica e n˜ao pode ser alterada, da mesma forma o valor do symbol ’2. Se fizermos (define x 1)estamos criando a vari´avel x e fazendo ela apontar para o valor do n´umero 1. Se em seguida for avaliado o comando (set! x ’a), o valor 1 n˜ao foi alterado, ele s´o deixou de ser referenciado e a vari´avel x passou a referenciar um outro valor. Um procedimento que tem argumentos num´ericos e retorna um n´umero na verdade est´a recebendo um ponteiro para um n´umero e retornando um ponteiro para um n´umero. Para o programador e o usu´ario final n˜ao importa se est˜ao sendo utilizados ponteiros ou valores. O fato ´e que ao passarmos ponteiros para as fun¸c˜oes, por exemplo, as opera¸c˜oes matem´aticas se tornam mais coerentes, visto que matematicamente falando um n´umero ´e uma entidade ´unica,e portanto ao usarmos este modelo de armazenamento nos aproximamos do ponto de vista matem´atico.

5.1 Objetos no Monte (Heap)

A maior parte das vari´aveis em Scheme e CL, principalmente as criadas atrav´es do define, defun, let e setf, s˜ao apontadores para objetos que s˜ao alo- cados no monte. Os objetos contˆem um campo de prop´osito geral chamado de value cell (c´elula de valor), este campo pode conter qualquer valor: um valor imediato (um n´umero, symbol) ou um apontador para uma outra localiza¸c˜ao da mem´oria (campo cdr de uma lista n˜ao vazia). Os pares (pair ) s˜ao exemplos de objetos que contem dois campos, cada podendo armazenar qualquer valor.

Este modelo de armazenamento facilita a aloca¸c˜ao de novos objetos na mem´oria, no entanto ´e necess´ario ter uma gerˆencia dos objetos na mem´oria que efetiva- mente est˜ao sendo usados pelo programa para que o sistema n˜ao fique sem mem´oria. O Garbage Collector (Coletor de Lixo) ´e o componente do sistema respons´avel por fazer o trabalho de reclamar a mem´oria de objetos que n˜ao s˜ao mais utilizados pelo programa.

6 Express˜oes e Comandos

Como LPs cujo principal foco ´e a programa¸c˜ao funcional, Scheme e CL s˜ao orientadas a express˜oes - grande parte das constru¸c˜oes da linguagem retornam um valor. Embora tenha alguns comandos, estes s˜ao poucos. As express˜oes e comandos podem ser divididas em primitivos e derivados.

6.1 Tipos Primitivos de Express˜oes e Comandos

S˜ao classificadas como express˜oes e comandos primitivos as seguintes ex- press˜oes:

  • Referˆencia a uma vari´avel: Uma express˜ao que contem uma vari´avel. (define x 1) x ;;refer^encia `a vari´avel => 1
  • Express˜ao Literal E uma express˜^ ´ ao criada usando quote ou a combina¸c˜ao de listas e sym- bols formando uma representa¸c˜ao externa de um objeto ou constru¸c˜ao da linguagem. (quote (+ 1 2)) => (+ 1 2) ’(a b c) => ’(a b c) ’1 => 1
  • Chamada de um Procedimento Se uma fun¸c˜ao foi definida para retornar um valor, a chamada deste pro- cedimento para dada entrada ´e uma express˜ao. Sintaxe: (func arg1 arg2 ...) (+ 1 2) => 3 (car (list 1 2 3 4)) => 1
  • Procedimentos A defini¸c˜ao de express˜oes lambda s˜ao express˜oes. Sintaxe: (lambda (parametros) corpo) Parˆametros ´e uma lista de parˆametros formais e e o corpo ´e uma sequˆencia de uma ou mais express˜oes (lambda (x y z) (* (+ x y) z))
  • Express˜oes Condicionais S˜ao formas especiais que retornam um valor dependendo do valor l´ogico de uma express˜ao.

Sintaxe: (if (teste) consequente) (if (teste) consequente alternativo) Teste ´e uma express˜ao que deve retornar um valor l´ogico. Caso verdadeiro a express˜ao condicional retorna o valor da express˜ao consequente, caso contr´ario, retorna o resultado da express˜ao alternativo. (if (> x 0) x (- 0 x)) ;;valor absoluto

  • Atribui¸c˜ao O comando de atribui¸c˜ao em Scheme ´e o set! , ele modifica o valor na mem´oria apontado por uma vari´avel e esta vari´avel necessariamente tem que estar definida no mesmo escopo onde foi chamado o set!. O retorno de set! n˜ao ´e especificado. Em CL temos o procedimento (setf x y) , que ´e uma express˜ao cujo retorno ´e o valor da express˜ao y, e atribui `a vari´avel x o valor de y.

puta¸c˜ao” em um ponto do programa. Atrav´es do uso do procedimento call-with-current-continuation ´e poss´ıvel “empacotar” um est´agio de uma computa¸c˜ao dentro de uma fun¸c˜ao e retornar a continua¸c˜ao para uma ou- tra fun¸c˜ao que eventualmente poder´a invocar a continua¸c˜ao da primeira fun¸c˜ao. Em Scheme as continua¸c˜oes tˆem status de objetos de primeira classe, podendo ser passados como parˆametros de fun¸c˜oes, atribuidos a vari´aveis e retornados por fun¸c˜oes, contudo s˜ao elementos perigosos pois s˜ao considerados os “gotos” do Scheme. Common Lisp provˆe express˜oes categ´oricas tais como o typeof, typep, type,etc

7 Modulariza¸c˜ao e Polimorfismo

7.1 Modulariza¸c˜ao

Scheme e CL provˆem mecanismos diferentes de modulariza¸c˜ao compat´ıveis com a filosofia do projeto de cada um. Em Scheme o mecanismo b´asico de modulariza¸c˜ao ´e a abstra¸c˜ao de processos atrav´es de fun¸c˜oes. Scheme n˜ao provˆe mecanismos espec´ıficos para a abstra¸c˜ao de dados, mas essa pode ser emulada atrav´es do uso de listas, vetores e fun¸c˜oes.

Nos subprogramas Scheme a dire¸c˜ao de passagem de parˆametro ´e unidirecional de entrada, normalmente ´e utilizada o modo normal (eager ) de avalia¸c˜ao, no qual o parˆametro real ´e avaliado no momento da chamada da fun¸c˜ao. E poss´´ ıvel simular “lazy evaluation” atrav´es de uma sintaxe especial que explicitamente suspende a computa¸c˜ao (os procedimentos delay e force). Todos os parˆametros s˜ao passados por valor.

O Common Lisp possui alguns mecanismos extras de implementar Modula- riza¸c˜ao. Atrav´es do seu sistema de tipo, usando os procedimentos de especi- fica¸c˜ao de tipos novos, ou de dados estruturados (defstruct) ´e implementado abstra¸c˜ao de dados. Com o defstruct ´e definido uma estrutura de dados seme- lhantes ao struct do C: um registo com alguns campos definidos.

Um suporte maior `a modulariza¸c˜ao em CL pode ser alcan¸cado atrav´es dos pacotes (packages). O package ´e uma estrutura de dados que faz um mapea- mente entre nome (strings) e symbols, ele define um namespace. Em um dado momento um package ´e o package atual do sistema e ´e utilizado pelo lisp re- ader na tradu¸c˜ao de strings para symbols. O package atual do sistema ´e, por defini¸c˜ao, definido pelo valor da vari´avel global package.

O mapeamento de strings para symbols dispon´ıvel em um pacote ´e dividido em duas classes: externos e internos. Os s´ımbolos externos fazem parte da interface p´ublica do pacote, e devem ser declarados especialmente como tal, atrav´es da palavra chave export. O sistema de pacotes ´e multi-camada, podendo ter pacotes que herdam namespace de outros pacotes. Um novo pacote ´e definido atrav´es do procedimento defpackage, atrav´es do qual pode ser definido o tamanho do pacote (n´umero de s´ımbolos), apelidos, s´ımbolos internos e externos, etc. O procedimento use-package permite o uso de um pacote espec´ıfico.

7.2 CLOS e Polimorfismo

O CL possui um sistema orientada a objetos chamado Common Lisp Object System (CLOS). O CLOS ´e baseado em fun¸c˜oes gen´ericas, heran¸ca m´ultipla, combina¸c˜ao declarativa de m´etodos e um protocolo de meta-objetos. Os objetos fundamentos do CLOS s˜ao classes,instˆancias,fun¸c˜oes gen´ericas e m´etodos. Um objetod do tipo class determina a estrutura e comportamento de outros objetos, que s˜ao chamadados de instˆancias desta classe. O conjunto de opera¸c˜oes que podem ser efetuados sobre um objeto pode ser determinado atrav´es da classe deste objeto.

Um fun¸c˜ao gen´erica ´e uma fun¸c˜ao cujo comportamento depende da classe dos argumentos da fun¸c˜ao. Este ´e um exemplo claro de polimorfismo param´etrico universal de fun¸c˜oes, visto que podemos definir fun¸c˜oes gen´ericas que opera- rariam sobre objetos de diversas classes e comportariam para cada classe de uma maneira diferente. Fun¸c˜oes Gen´ericas s˜ao conhecidas tamb´em por multi- m´etodos. Um objeto generic funtion, entre outras informa¸c˜oes, contem um con- junto de m´etodos e um tipo de combina¸c˜ao de m´etodos. Um m´etodo define com- portamentos e opera¸c˜oes espec´ıficas a uma classe, diz-se que um m´etodo especi- aliza uma fun¸c˜ao gen´erica. Um objeto method contem uma fun¸c˜ao do m´etodo, uma sequˆencia de especializadores de parˆametros que determinam quando que o m´etodo ´e aplic´avel, e uma sequˆencia de qualificadores para que o combinador de m´etodos possa distinguir entre m´etodos diferentes que operam em classes di- ferentes. O combinador de m´etodos controla a sele¸c˜ao dos m´etodos, a order que s˜ao executados e os valores retornados pelas fun¸c˜oes gen´ericas. O CLOS provˆe um tipo de combina¸c˜ao de m´etodos padr˜ao ´e provˆe procedimentos de declarar nos tipos de combina¸c˜oes de m´etodos.

Cada classe do CLOS tem uma lista de precedˆencia de classes, que ´e uma ordena¸c˜ao da classe e o conjunto de suas superclasses. O ordem da lista ´e da mais espec´ıfica para a menos espec´ıfica. Esta lista ´e usada pelo Combinador de M´etodos para ordenar os m´etodos na ordem do mais espec´ıfico para o me- nos espec´ıfico. Algumas classes podem sobescrever ou cubrir caracter´ısticas e m´etodos de suas superclasses. A defini¸c˜ao de classes ´e feita usando o procedi- mento defclass. O CLOS ´e dinˆamico, de modo que as classes e os m´etodos do CLOS podem ser redefinidos em tempo de execu¸c˜ao, mesmo se j´a exista uma objetos instanciados da classe em quest˜ao.

8 Exce¸c˜oes

Em Scheme n˜ao existia nenhum tipo de procedimentos ou meios da pr´opria linguagem para manipula¸c˜ao de exce¸c˜oes, embora existisse meios de sinaliz´a- las, mas na ´ultima vers˜ao do Revised Report(R^6 RS), seguindo o projeto do Common Lisp, foi acrescentado `a linguagem, atrav´es da biblioteca padr˜ao, o tipo condition, um conjunto de fun¸c˜oes que permite a sinaliza¸c˜ao e manipula¸c˜ao de excep¸c˜oes, e uma s´erie de tipos de condi¸c˜oes padr˜ao. O tratamento de excep¸c˜oes pode ser feito com o uso dos procedimentos guard e raise. O R^6 RS ainda ´e novo, foi ratificado no final de 2007, e portanto n˜ao existem ainda muitas implementa¸c˜oes dele.