Esquema (linguagem de programação)

Da Wikipédia, a enciclopédia livre
Ir para a navegação Saltar para pesquisar
Esquema
Lambda lc.svg
ParadigmasMultiparadigma : funcional , imperativo , meta
FamíliaLisp
Projetado porGuy L. Steele
Gerald Jay Sussman
Apareceu pela primeira vez1975 ; 47 anos atrás ( 1975 )
Versão estável
R7RS/2013 ; 9 anos atrás ( 2013 )
Disciplina de digitaçãoDinâmico , latente , forte
AlcanceLexical
Extensões de nome de arquivo.scm, .ss
Local na rede Internetwww.scheme-reports.org _ _
Principais implementações
Muitos
(consulte Implementações do esquema )
Influenciado por
ALGOL , Lisp , MDL
Influenciado
Clojure , Common Lisp , Dylan , EuLisp , Haskell , Hop , JavaScript , Julia , Lua , MultiLisp , R , Racket , Ruby , Rust , S , Scala , T

Scheme é um dialeto minimalista da família Lisp de linguagens de programação . Scheme consiste em um pequeno núcleo padrão com várias ferramentas para extensão de linguagem. [1]

Scheme foi criado durante a década de 1970 no MIT AI Lab e lançado por seus desenvolvedores, Guy L. Steele e Gerald Jay Sussman , através de uma série de memorandos agora conhecidos como Lambda Papers . Foi o primeiro dialeto de Lisp a escolher o escopo léxico e o primeiro a exigir implementações para realizar otimização de chamada de cauda , ​​dando suporte mais forte para programação funcional e técnicas associadas, como algoritmos recursivos. Foi também uma das primeiras linguagens de programação a suportar continuações de primeira classe . Ele teve uma influência significativa no esforço que levou ao desenvolvimento do Common Lisp . [2]

A linguagem Scheme é padronizada no padrão oficial IEEE [ 3] e um padrão de fato chamado de Revised n Report on the Algorithmic Language Scheme (R n RS). O padrão mais amplamente implementado é o R5RS (1998). [4] O padrão mais recente, R7RS, [5] fornece versões "pequenas" e "grandes" da linguagem Scheme; o padrão de linguagem "pequeno" foi ratificado em 2013. [6]Scheme tem uma base de usuários diversificada devido à sua compacidade e elegância, mas sua filosofia minimalista também causou grande divergência entre implementações práticas, tanto que o Scheme Steering Committee a chama de "linguagem de programação mais portátil do mundo" e "uma família de dialetos" em vez de um único idioma. [7]

História

Origens

Scheme começou na década de 1970 como uma tentativa de entender o modelo de ator de Carl Hewitt , para o qual Steele e Sussman escreveram um "pequeno intérprete de Lisp" usando Maclisp e depois "adicionaram mecanismos para criar atores e enviar mensagens". [8] Scheme foi originalmente chamado de "Schemer", na tradição de outras linguagens derivadas de Lisp , como Planner ou Conniver . O nome atual resultou do uso do sistema operacional ITS pelos autores , que limitava os nomes dos arquivos a dois componentes de no máximo seis caracteres cada. Atualmente, "Schemer" é comumente usado para se referir a um programador de Scheme.

R6RS

Um novo processo de padronização de linguagem começou no workshop Scheme de 2003, com o objetivo de produzir um padrão R6RS em 2006. Esse processo rompeu com a abordagem R n RS anterior de unanimidade.

O R6RS [9] apresenta um sistema de módulos padrão, permitindo uma divisão entre a linguagem central e as bibliotecas. Vários rascunhos da especificação R6RS foram lançados, sendo a versão final R5.97RS. Uma votação bem sucedida resultou na ratificação da nova norma, anunciada em 28 de agosto de 2007. [9]

Atualmente as versões mais recentes de várias implementações do Scheme [10] suportam o padrão R6RS. Existe uma implementação de referência portátil das bibliotecas de fase implícita propostas para R6RS, chamada psyntax, que carrega e se autoinicia adequadamente em várias implementações de Scheme mais antigas. [11]

Um recurso do R6RS é o descritor de tipo de registro (RTD). Quando um RTD é criado e usado, a representação do tipo de registro pode mostrar o layout da memória. Ele também calculou a máscara de bits do campo do objeto e as máscaras de bits do campo do objeto Esquema mutável e ajudou o coletor de lixo a saber o que fazer com os campos sem percorrer toda a lista de campos que são salvos no RTD. O RTD permite que os usuários expandam o RTD básico para criar um novo sistema de registro. [12]

O R6RS introduz inúmeras mudanças significativas na linguagem. [13] O código-fonte agora é especificado em Unicode e um grande subconjunto de caracteres Unicode pode agora aparecer em símbolos e identificadores de esquema, e há outras pequenas alterações nas regras lexicais. Os dados de caracteres agora também são especificados em Unicode. Muitos procedimentos padrão foram movidos para as novas bibliotecas padrão, que formam uma grande expansão do padrão, contendo procedimentos e formas sintáticas que anteriormente não faziam parte do padrão. Um novo sistema de módulos foi introduzido e os sistemas para tratamento de exceções agora são padronizados. As regras de sintaxe foram substituídas por uma facilidade de abstração sintática mais expressiva (caso de sintaxe) que permite o uso de todo o Scheme em tempo de expansão da macro. Implementações compatíveis agora são necessárias para suportar a torre numérica completa do Scheme , e a semântica dos números foi expandida, principalmente na direção do suporte para o IEEE 754padrão para representação numérica de ponto flutuante.

R7RS

O padrão R6RS causou polêmica porque se afastou da filosofia minimalista. [14] [15] Em agosto de 2009, o Scheme Steering Committee, que supervisiona o processo de padronização, anunciou sua intenção de recomendar a divisão do Scheme em duas linguagens: uma grande linguagem de programação moderna para programadores; e uma versão pequena, um subconjunto da versão grande mantendo o minimalismo elogiado por educadores e implementadores casuais. [7] Dois grupos de trabalho foram criados para trabalhar nessas duas novas versões do Scheme. O site do Processo de Relatórios do Esquema tem links para os estatutos dos grupos de trabalho, discussões públicas e sistema de rastreamento de problemas.

A nona minuta do R7RS (small language) foi disponibilizada em 15 de abril de 2013. [16] Uma votação ratificando esta minuta foi encerrada em 20 de maio de 2013, [17] e o relatório final está disponível desde 6 de agosto de 2013, descrevendo "a 'pequena' linguagem desse esforço: portanto, não pode ser considerado isoladamente como o sucessor do R6RS". [6]

1955 1960 1965 1970 1975 1980 1985 1990 1995 2000 2005 2010 2015 2020
 LISP 1, 1.5, LISP 2 (abandonado)
 Maclisp
 Interlisp
 MDL (linguagem de programação)
 Lisp Máquina Lisp
 Esquema  R5RS  R6RS  R7RS pequeno
 NADA
 ZIL (Linguagem de Implementação Zork)
 Franz Lisp
 Lisp comum
 Le Lisp
 Esquema do MIT
 T
 Esquema Chez
 Emacs Lisp
 AutoLISP
 PicoLisp
 EuLisp
 ISLISP
 OpenLisp
 Esquema PLT  Raquete
 GNU Guile
 Visual LISP
 Clojure
 Arco
 LFE
 Hy

Características distintivas

Scheme é principalmente uma linguagem de programação funcional . Ele compartilha muitas características com outros membros da família de linguagens de programação Lisp. A sintaxe muito simples do Scheme é baseada em s-expressions , listas entre parênteses nas quais um operador de prefixo é seguido por seus argumentos. Os programas de esquema consistem, portanto, em sequências de listas aninhadas. As listas também são a principal estrutura de dados no Scheme, levando a uma equivalência próxima entre o código-fonte e os formatos de dados ( homoiconicidade ). Os programas Scheme podem criar e avaliar facilmente partes do código Scheme dinamicamente.

A dependência de listas como estruturas de dados é compartilhada por todos os dialetos Lisp. Scheme herda um rico conjunto de primitivos de processamento de lista , como cons, carecdr de seus progenitores Lisp. Scheme usa variáveis ​​tipadas estritamente, mas dinamicamente, e suporta procedimentos de primeira classe . Assim, procedimentos podem ser atribuídos como valores a variáveis ​​ou passados ​​como argumentos a procedimentos.

Esta seção concentra-se principalmente em recursos inovadores da linguagem, incluindo os recursos que distinguem o Scheme de outros Lips. Salvo indicação em contrário, as descrições dos recursos referem-se ao padrão R5RS. Nos exemplos fornecidos nesta seção, a notação "===> resultado" é usada para indicar o resultado da avaliação da expressão na linha imediatamente anterior. Esta é a mesma convenção usada em R5RS.

Minimalismo

Scheme é uma linguagem muito simples, muito mais fácil de implementar do que muitas outras linguagens de poder expressivo comparável . [18] Essa facilidade é atribuída ao uso do cálculo lambda para derivar grande parte da sintaxe da linguagem de formas mais primitivas. Por exemplo, das construções sintáticas baseadas em expressões 23 s definidas no padrão R5RS Scheme, 14 são classificadas como formas derivadas ou de biblioteca, que podem ser escritas como macros envolvendo formas mais fundamentais, principalmente lambda. Como R5RS (§3.1) diz: "A mais fundamental das construções de ligação variável é a expressão lambda, porque todas as outras construções de ligação variável podem ser explicadas em termos de expressões lambda." [4]

Formas fundamentais : define, lambda, quote, if, define-syntax, let-syntax, letrec-syntax, sintaxe-rules, set!
Formas derivadas : do, let, let*, letrec, cond, case, and, or, begin, named let, delay, unquote, unquote-splicing, quasiquote

Exemplo: uma macro para implementar letcomo uma expressão usando lambdapara realizar as ligações de variáveis.

( define-sintaxe let 
  ( sintaxe-regras () 
    (( let (( var  expr )  ... )  corpo  ... ) 
      (( lambda ( var  ... )  corpo  ... )  expr  ... )))))

Assim, usar letcomo definido acima uma implementação de Scheme reescreveria " (let ((a 1)(b 2)) (+ b a))" como " ((lambda (a b) (+ b a)) 1 2)", o que reduz a tarefa de implementação àquela de instanciações de procedimentos de codificação.

Em 1998, Sussman e Steele observaram que o minimalismo de Scheme não era um objetivo de design consciente, mas sim o resultado não intencional do processo de design. "Na verdade, estávamos tentando construir algo complicado e descobrimos, por acaso, que havíamos projetado acidentalmente algo que atendeu a todos os nossos objetivos, mas era muito mais simples do que pretendíamos... percebemos que o cálculo lambda - um formalismo pequeno e simples - poderia servir como o núcleo de uma linguagem de programação poderosa e expressiva." [8]

Escopo lexical

Como a maioria das linguagens de programação modernas e ao contrário de Lisps anteriores, como Maclisp , Scheme tem escopo lexical: todas as ligações de variáveis ​​possíveis em uma unidade de programa podem ser analisadas lendo o texto da unidade de programa sem considerar os contextos em que ela pode ser chamada. Isso contrasta com o escopo dinâmico que era característico dos primeiros dialetos Lisp, por causa dos custos de processamento associados aos métodos primitivos de substituição textual usados ​​para implementar algoritmos de escopo lexical em compiladores e interpretadores da época. Nesses Lisps, era perfeitamente possível que uma referência a uma variável livre dentro de um procedimento se referisse a associações bastante distintas externas ao procedimento, dependendo do contexto da chamada.

O impulso para incorporar o escopo lexical, que era um modelo de escopo incomum no início dos anos 1970, em sua nova versão do Lisp, veio dos estudos de Sussman sobre ALGOL . Ele sugeriu que os mecanismos de escopo lexical do tipo ALGOL ajudariam a realizar seu objetivo inicial de implementar o modelo Actor de Hewitt em Lisp. [8]

Os principais insights sobre como introduzir o escopo lexical em um dialeto Lisp foram popularizados no Lambda Paper de Sussman e Steele em 1975, "Scheme: An Interpreter for Extended Lambda Calculus", [19] onde eles adotaram o conceito de fechamento lexical (na página 21). ), que havia sido descrito em um AI Memo em 1970 por Joel Moses , que atribuiu a ideia a Peter J. Landin . [20]

Cálculo lambda

A notação matemática de Alonzo Church , o cálculo lambda, inspirou o uso de "lambda" pelo Lisp como palavra-chave para a introdução de um procedimento, além de influenciar o desenvolvimento de técnicas de programação funcional envolvendo o uso de funções de ordem superior em Lisp. Mas as primeiras Lisps não eram expressões adequadas do cálculo lambda por causa de seu tratamento de variáveis ​​livres . [8]

Um sistema lambda formal tem axiomas e uma regra de cálculo completa. É útil para a análise usando lógica matemática e ferramentas. Nesse sistema, o cálculo pode ser visto como uma dedução direcional. A sintaxe do cálculo lambda segue as expressões recursivas de x, y, z, ..., parênteses, espaços, o ponto e o símbolo λ. [21] A função do cálculo lambda inclui: Primeiro, servir como ponto de partida de uma poderosa lógica matemática. Em segundo lugar, pode reduzir a exigência dos programadores de considerar os detalhes de implementação, porque pode ser usado para imitar a avaliação da máquina. Finalmente, o cálculo lambda criou uma meta-teoria substancial. [22]

A introdução do escopo lexical resolveu o problema fazendo uma equivalência entre algumas formas de notação lambda e sua expressão prática em uma linguagem de programação funcional. Sussman e Steele mostraram que a nova linguagem poderia ser usada para derivar elegantemente toda a semântica imperativa e declarativa de outras linguagens de programação, incluindo ALGOL e Fortran , e o escopo dinâmico de outras Lisps, usando expressões lambda não como simples instâncias de procedimento, mas como "controle estruturas e modificadores de ambiente". [23] Eles introduziram o estilo de passagem de continuaçãojuntamente com sua primeira descrição de Scheme no primeiro dos Lambda Papers, e em artigos subsequentes, eles passaram a demonstrar o poder bruto desse uso prático do cálculo lambda.

Estrutura do bloco

Scheme herda sua estrutura de blocos de linguagens estruturadas em blocos anteriores, particularmente ALGOL . No Scheme, os blocos são implementados por três construções de ligação : let, let*e letrec. Por exemplo, a construção a seguir cria um bloco no qual um símbolo chamado varé vinculado ao número 10:

( define var  "ganso" ) 
;; Qualquer referência a var aqui será vinculada a "goose" 
( let (( var  10 )) 
  ;; instruções vão aqui. Qualquer referência a var aqui será vinculada a 10. 
  ) 
;; Qualquer referência a var aqui será vinculada a "ganso"

Os blocos podem ser aninhados para criar estruturas de blocos arbitrariamente complexas de acordo com a necessidade do programador. O uso de estruturação de blocos para criar ligações locais alivia o risco de colisão de namespace que pode ocorrer de outra forma.

Uma variante de let, let*, permite que as associações se refiram a variáveis ​​definidas anteriormente na mesma construção, assim:

( let* (( var1  10 ) 
       ( var2  ( + var1  12 ))) 
  ;; Mas a definição de var1 não poderia se referir a var2 
  )

A outra variante, letrec, é projetada para permitir que procedimentos mutuamente recursivos sejam vinculados uns aos outros.

;; Cálculo das sequências masculinas e femininas de Hofstadter como uma lista de pares

( define ( hofstadter-masculino-feminino  n ) 
  ( letrec (( feminino  ( lambda ( n ) 
		     ( if ( = n  0 ) 
			 1 
			 ( - n  ( masculino  ( feminino  ( - n  1 ))))))) 
	   ( masculino  ( lambda ( n ) 
		   ( se ( = n  0 ) 
		       0 
		       ( - n  ( feminino ( masculino  ( - n  1 ))))))) 
    ( let loop  (( i  0 )) 
      ( if ( > i  n ) 
	  ' () 
	  ( cons ( cons ( feminino  i ) 
		      ( masculino  i )) 
		( loop  ( + eu  1 ))))))))

( hofstadter-macho-fêmea  8 )

===  > ( ( 1.0  )  ( 1.0 )  ( 2.1 ) ( 2.2 ) ( 3.2 ) ( 3.3 ) ( 4.4 ) ( 5.4 ) ( 5.5 ) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ )                       

(Veja as sequências masculina e feminina de Hofstadter para as definições usadas neste exemplo.)

Todos os procedimentos vinculados em um único letrecpodem se referir uns aos outros por nome, bem como a valores de variáveis ​​definidas anteriormente no mesmo letrec, mas não podem se referir a valores definidos posteriormente no mesmo letrec.

Uma variante de let, a forma "let com nome", tem um identificador após a palavra- letchave. Isso liga as variáveis ​​let ao argumento de um procedimento cujo nome é o identificador fornecido e cujo corpo é o corpo do formulário let. O corpo pode ser repetido conforme desejado chamando o procedimento. O let nomeado é amplamente usado para implementar iteração.

Exemplo: um contador simples

( let loop  (( n  1 )) 
  ( if ( > n  10 ) 
      ' () 
      ( cons n 
	    ( loop  ( + n  1 ))))))

===>  ( 1  2  3  4  5  6  7  8  9  10 )

Como qualquer procedimento em Scheme, o procedimento criado no let nomeado é um objeto de primeira classe.

Recursão de cauda adequada

Scheme tem uma construção de iteração, do, mas é mais idiomático em Scheme usar a recursão de cauda para expressar iteração . As implementações do Scheme em conformidade com o padrão são necessárias para otimizar as chamadas de cauda para suportar um número ilimitado de chamadas de cauda ativas (R5RS sec. 3.5) [4] — uma propriedade que o relatório do Scheme descreve como recursão de cauda adequada — tornando seguro para os programadores do Scheme escrever algoritmos iterativos usando estruturas recursivas, que às vezes são mais intuitivas. Os procedimentos recursivos de cauda e o formulário nomeadolet fornecem suporte para iteração usando recursão de cauda.

;; Construindo uma lista de quadrados de 0 a 9: 
;; Nota: loop é simplesmente um símbolo arbitrário usado como rótulo. Qualquer símbolo serve.

( define ( lista de quadrados  n ) 
  ( let loop  (( i  n )  ( res  ' ())) 
    ( if ( < i  0 ) 
        res 
        ( loop  ( - i  1 )  ( cons ( * i  i )  res )) )))

( lista de quadrados  9 ) 
===>  ( 0  1  4  9  16  25  36  49  64  81 )

Continuações de primeira classe

Continuações em Scheme são objetos de primeira classe . Scheme fornece o procedimento call-with-current-continuation(também conhecido como call/cc) para capturar a continuação atual empacotando-a como um procedimento de escape vinculado a um argumento formal em um procedimento fornecido pelo programador. (R5RS sec. 6.4) [4] As continuações de primeira classe permitem que o programador crie construções de controle não locais , como iteradores , corrotinas e retrocesso .

Continuações podem ser usadas para emular o comportamento de instruções de retorno em linguagens de programação imperativas. A seguinte função find-first, dada function funce list lst, retorna o primeiro elemento xem lsttal que (func x)retorna true.

( define ( find-first  func  lst ) 
  ( call-with-current-continuation 
   ( lambda ( return-imediately ) 
     ( for-each ( lambda ( x ) 
		 ( if ( func  x ) 
		     ( return imediatamente  x ))) 
	  lst ) 
     # f )))

( find-first  integer?  ' ( 1 /2  3 /4  5.6  7  8 /9  10  11 )) 
===>  7 
( find-first  zero?  ' ( 1  2  3  4 )) 
===>  #f

O exemplo a seguir, um quebra-cabeça de programador tradicional, mostra que Scheme pode tratar continuações como objetos de primeira classe, ligando-as a variáveis ​​e passando-as como argumentos para procedimentos.

( let* (( yin 
         (( lambda ( cc )  ( display "@" )  cc )  ( chamada com continuação de corrente ( lambda ( c )  c )))) 
       ( yang 
         (( lambda ( cc )  ( display "* " )  cc )  ( chamada com continuação de corrente ( lambda ( c )  c ))))) 
    ( yin  yang ))

Quando executado, este código exibe uma sequência de contagem:@*@**@***@****@*****@******@*******@********...

Namespace compartilhado para procedimentos e variáveis

Em contraste com Common Lisp, todos os dados e procedimentos em Scheme compartilham um namespace comum, enquanto que em Common Lisp funções e dados têm namespaces separados tornando possível que uma função e uma variável tenham o mesmo nome, e requer uma notação especial para se referir a um funcionar como um valor. Isso às vezes é conhecido como a distinção " Lisp-1 vs. Lisp-2 ", referindo-se ao namespace unificado de Scheme e aos namespaces separados de Common Lisp. [24]

No Scheme, as mesmas primitivas que são usadas para manipular e vincular dados podem ser usadas para vincular procedimentos. Não há equivalente de Common Lisp defune #'primitivos.

;; Variável vinculada a um número: 
( define f  10 ) 
f 
===>  10 
;; Mutação (alterando o valor do limite) 
( set! f  ( + f  f  6 )) 
f 
===>  26 
;; Atribuindo um procedimento à mesma variável: 
( set! f  ( lambda ( n )  ( + n  12 ))) 
( f  6 ) 
===>  18 
;; Atribuindo o resultado de uma expressão à mesma variável: 
( set! f ( f  1 )) 
f 
===>  13 
;; programação funcional: 
( apply +  ' ( 1  2  3  4  5  6 )) 
===>  21 
( set! f  ( lambda ( n )  ( + n  100 ))) 
( map f  ' ( 1  2  3 )) 
=== >  ( 101  102  103 )

Padrões de implementação

Esta subseção documenta as decisões de projeto que foram tomadas ao longo dos anos que deram ao Scheme um caráter particular, mas não são os resultados diretos do projeto original.

Torre numérica

Esquema especifica um conjunto comparativamente completo de tipos de dados numéricos, incluindo tipos complexos e racionais , que é conhecido em Esquema como a torre numérica (R5RS sec. 6.2 [4] ). O padrão trata isso como abstrações e não compromete o implementador com nenhuma representação interna específica.

Os números podem ter a qualidade da exatidão. Um número exato só pode ser produzido por uma sequência de operações exatas envolvendo outros números exatos – a inexatidão é, portanto, contagiosa. O padrão especifica que quaisquer duas implementações devem produzir resultados equivalentes para todas as operações que resultem em números exatos.

O padrão R5RS especifica procedimentos exact->inexacte inexact->exactque podem ser usados ​​para alterar a exatidão de um número. inexact->exactproduz "o número exato que é numericamente mais próximo do argumento". exact->inexactproduz "o número inexato que é numericamente mais próximo do argumento". O padrão R6RS omite esses procedimentos do relatório principal, mas os especifica como procedimentos de compatibilidade R5RS na biblioteca padrão (rnrs r5rs (6)).

No padrão R5RS, as implementações do Scheme não são necessárias para implementar toda a torre numérica, mas devem implementar "um subconjunto coerente consistente com os propósitos da implementação e com o espírito da linguagem Scheme" (R5RS sec. 6.2.3). [4] O novo padrão R6RS requer a implementação de toda a torre, e "objetos inteiros exatos e objetos de números racionais exatos de tamanho e precisão praticamente ilimitados, e para implementar certos procedimentos... " (R6RS sec. 3.4, sec. 11.7.1). [9]

Exemplo 1: aritmética exata em uma implementação que suporta números complexos racionais exatos.

;; Soma de três números reais racionais e dois números complexos racionais 
( defina x  ( + 1 /3  1 /4  -1 /5  -1 /3i  405 /50+2/3i )) 
x 
===>  509 /60+1/ 3i 
;; Verifique a exatidão. 
( exato? x ) 
===>  #t

Exemplo 2: Mesma aritmética em uma implementação que não suporta nem números racionais exatos nem números complexos, mas aceita números reais em notação racional.

;; Soma de quatro números reais racionais 
( defina xr  ( + 1 /3  1 /4  -1 /5  405 /50 )) 
;; Soma de dois números reais racionais 
( defina xi  ( + -1 /3  2 /3 )) 
xr 
===>  8,48333333333333 
xi 
===>  0,333333333333333 
;; Verifique a exatidão. 
( exato? xr ) 
===>  #f 
( exato? xi ) 
===>  #f

Ambas as implementações estão em conformidade com o padrão R5RS, mas a segunda não está em conformidade com o R6RS porque não implementa a torre numérica completa.

Avaliação atrasada

Esquema suporta a avaliação atrasada através do delayformulário e do procedimento force.

( define a  10 ) 
( define eval-aplus2  ( delay ( + a  2 ))) 
( set! a  20 ) 
( force eval-aplus2 ) 
===>  22 
( define eval-aplus50  ( delay ( + a  50 ))) 
( let (( a  8 )) 
  ( force eval-aplus50 )) 
===>  70 
( set! a  100 )
( force eval-aplus2 ) 
===>  22

O contexto lexical da definição original da promessa é preservado e seu valor também é preservado após o primeiro uso de force. A promessa só é avaliada uma vez.

Esses primitivos, que produzem ou manipulam valores conhecidos como promessas , podem ser usados ​​para implementar construções avançadas de avaliação lenta , como streams . [25]

No padrão R6RS, eles não são mais primitivos, mas são fornecidos como parte da biblioteca de compatibilidade R5RS (rnrs r5rs (6)).

Em R5RS, uma implementação sugerida de delaye forceé fornecida, implementando a promessa como um procedimento sem argumentos (um thunk ) e usando memoização para garantir que ela seja avaliada apenas uma vez, independentemente do número de vezes que forceé chamada (R5RS sec. 6.4 ). [4]

O SRFI 41 permite a expressão de sequências finitas e infinitas com extraordinária economia. Por exemplo, esta é uma definição da sequência de fibonacci usando as funções definidas no SRFI 41: [25]

;; Defina a sequência de Fibonacci: 
( define fibs 
  ( stream-cons  0 
    ( stream-cons  1 
      ( stream-map  + 
        fibs 
        ( stream-cdr  fibs ))))) 
;; Calcule o centésimo número na sequência: 
( stream-ref  fibs  99 ) 
===>   218922995834555169026

Ordem de avaliação dos argumentos do procedimento

A maioria dos Lisps especifica uma ordem de avaliação para argumentos de procedimento. Esquema não. A ordem de avaliação - incluindo a ordem na qual a expressão na posição do operador é avaliada - pode ser escolhida por uma implementação chamada por chamada, e a única restrição é que "o efeito de qualquer avaliação concorrente do operador e expressões operando são restritas para serem consistentes com alguma ordem sequencial de avaliação." (R5RS sec. 4.1.3) [4]

( let (( ev  ( lambda ( n )  ( display "Avaliando " ) 
                     ( display ( if ( procedimento? n )  "procedimento"  n )) 
                     ( newline )  n ))) 
  (( ev  + )  ( ev  1 )  ( ev  2 ))) 
===>  3

ev é um procedimento que descreve o argumento passado para ele e, em seguida, retorna o valor do argumento. Ao contrário de outros Lisps, a aparência de uma expressão na posição de operador (o primeiro item) de uma expressão Scheme é bastante legal, desde que o resultado da expressão na posição de operador seja um procedimento.

Ao chamar o procedimento "+" para somar 1 e 2, as expressões (ev +), (ev 1) e (ev 2) podem ser avaliadas em qualquer ordem, desde que o efeito não seja como se fossem avaliados em paralelo . Assim, as três linhas a seguir podem ser exibidas em qualquer ordem pelo Scheme padrão quando o código de exemplo acima é executado, embora o texto de uma linha não possa ser intercalado com outra porque isso violaria a restrição de avaliação sequencial.

Avaliando 1
Avaliando 2
Procedimento de avaliação

Macros higiênicos

No padrão R5RS e também em relatórios posteriores, a sintaxe do Scheme pode ser facilmente estendida através do sistema de macros. O padrão R5RS introduziu um poderoso sistema de macro higiênico que permite ao programador adicionar novas construções sintáticas à linguagem usando uma sublinguagem simples de correspondência de padrões (R5RS sec 4.3). [4] Antes disso, o macrossistema higiênico havia sido relegado a um apêndice do padrão R4RS, como um sistema de "alto nível" ao lado de um macrossistema de "baixo nível", ambos tratados como extensões do Esquema em vez de um parte essencial da língua. [26]

As implementações do sistema macro higiênico, também chamado syntax-rulesde , são necessárias para respeitar o escopo lexical do restante da linguagem. Isso é garantido por regras especiais de nomenclatura e escopo para expansão de macros e evita erros comuns de programação que podem ocorrer nos sistemas de macros de outras linguagens de programação. O R6RS especifica um sistema de transformação mais sofisticado, syntax-case, que está disponível como uma extensão de linguagem para o R5RS Scheme há algum tempo.

;; Defina uma macro para implementar uma variante de "if" com uma multi-expressão 
;; ramo verdadeiro e nenhum ramo falso. 
( define-sintaxe quando 
  ( regras de sintaxe () 
    (( quando  pred  exp  exps  ... ) 
      ( if pred  ( inicia exp  exps  ... )))))

Invocações de macros e procedimentos têm uma grande semelhança - ambas são expressões s - mas são tratadas de forma diferente. Quando o compilador encontra uma expressão s no programa, ele primeiro verifica se o símbolo está definido como uma palavra-chave sintática dentro do escopo lexical atual. Em caso afirmativo, ele tenta expandir a macro, tratando os itens na cauda da expressão-s como argumentos sem compilar código para avaliá-los, e esse processo é repetido recursivamente até que não reste nenhuma chamada de macro. Se não for uma palavra-chave sintática, o compilador compila o código para avaliar os argumentos no final da expressão-s e, em seguida, avaliar a variável representada pelo símbolo no início da expressão-s e chamá-lo como um procedimento com o expressões de cauda avaliadas passadas como argumentos reais para ele.

A maioria das implementações do Scheme também fornece sistemas de macro adicionais. Entre os populares estão fechamentos sintáticos , macros de renomeação explícita e define-macroum sistema de macros não higiênico semelhante ao defmacrosistema fornecido em Common Lisp .

A incapacidade de especificar se uma macro é ou não higiênica é uma das deficiências do sistema macro. Modelos alternativos para expansão, como conjuntos de escopos, fornecem uma solução potencial. [27]

Ambientes e avaliação

Antes do R5RS, Scheme não tinha equivalente padrão do evalprocedimento que é onipresente em outros Lisps, embora o primeiro Lambda Paper tenha descrito evaluatecomo "semelhante à função LISP EVAL" [19] e o primeiro Relatório Revisado em 1978 o substituiu por enclose, que levou dois argumentos. O segundo, terceiro e quarto relatórios revisados ​​omitiram qualquer equivalente de eval.

A razão para essa confusão é que em Scheme com seu escopo lexical o resultado da avaliação de uma expressão depende de onde ela é avaliada. Por exemplo, não está claro se o resultado da avaliação da seguinte expressão deve ser 5 ou 6: [28]

( let (( nome  '+ )) 
  ( let (( + * )) 
    ( avaliar  ( nome da lista 2 3 ))))  

Se for avaliado no ambiente externo, onde nameestá definido, o resultado é a soma dos operandos. Se for avaliado no ambiente interno, onde o símbolo "+" foi vinculado ao valor do procedimento "*", o resultado é o produto dos dois operandos.

O R5RS resolve essa confusão especificando três procedimentos que retornam ambientes e fornecendo um procedimento evalque recebe uma expressão s e um ambiente e avalia a expressão no ambiente fornecido. (R5RS sec. 6.5) [4] R6RS estende isso fornecendo um procedimento chamado environmentpelo qual o programador pode especificar exatamente quais objetos importar para o ambiente de avaliação.

Com esquema moderno (geralmente compatível com R5RS) para avaliar esta expressão, é preciso definir uma função evaluateque pode ficar assim:

( define ( avalia  expr ) 
   ( eval expr  ( interação-ambiente )))

interaction-environmenté o ambiente global do intérprete.

Tratamento de valores não booleanos em expressões booleanas

Na maioria dos dialetos de Lisp, incluindo Common Lisp, por convenção, o valor é NILavaliado como false em uma expressão booleana. Em Scheme, desde o padrão IEEE em 1991, [3] todos os valores exceto #f, incluindo NIL's equivalentes em Scheme que é escrito como '(), são avaliados como o valor true em uma expressão booleana. (R5RS sec. 6.3.1) [4]

Onde a constante que representa o valor booleano de true está Tna maioria dos Lisps, em Scheme é #t.

Disjunção de tipos de dados primitivos

Em Scheme os tipos de dados primitivos são disjuntos. Apenas um dos seguintes predicados pode ser verdadeiro para qualquer objeto Scheme: boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2) [4]

Dentro do tipo de dados numéricos, por outro lado, os valores numéricos se sobrepõem. Por exemplo, um valor inteiro satisfaz todos os predicados , , e integer?ao rational?mesmo real?tempo . (R5RS sec 6.2) [4]complex?number?

Predicados de equivalência

Scheme tem três tipos diferentes de equivalência entre objetos arbitrários denotados por três diferentes predicados de equivalência , operadores relacionais para testar a igualdade eq?, eqv?e equal?:

  • eq?avalia como a #fmenos que seus parâmetros representem o mesmo objeto de dados na memória;
  • eqv?é geralmente o mesmo que, eq?mas trata objetos primitivos (por exemplo, caracteres e números) especialmente para que os números que representam o mesmo valor sejam eqv?mesmo que não se refiram ao mesmo objeto;
  • equal?compara estruturas de dados como listas, vetores e strings para determinar se eles têm estrutura e eqv?conteúdo congruentes. (R5RS sec. 6.1) [4]

As operações de equivalência dependentes de tipo também existem em Scheme: string=?e string-ci=?compare duas strings (a última realiza uma comparação independente de maiúsculas e minúsculas); char=?e char-ci=?comparar personagens; =compara números. [4]

Comentários

Até o padrão R5RS, o comentário padrão em Scheme era um ponto e vírgula, o que torna o resto da linha invisível para Scheme. Numerosas implementações têm suportado convenções alternativas que permitem que comentários se estendam por mais de uma única linha, e o padrão R6RS permite duas delas: uma expressão s inteira pode ser transformada em um comentário (ou "comentado") precedendo-o com #;(introduzido em SRFI 62 [29] ) e um comentário de várias linhas ou "comentário de bloco" pode ser produzido circundando o texto com #|e |#.

Entrada/saída

A entrada e a saída do esquema são baseadas no tipo de dados da porta . (R5RS sec 6.6) [4] R5RS define duas portas padrão, acessíveis com os procedimentos current-input-porte current-output-port, que correspondem às noções Unix de entrada padrão e saída padrão . A maioria das implementações também fornece current-error-port. O redirecionamento de entrada e saída padrão é suportado no padrão, por procedimentos padrão como with-input-from-filee with-output-to-file. A maioria das implementações fornece portas de string com recursos de redirecionamento semelhantes, permitindo que muitas operações normais de entrada e saída sejam executadas em buffers de string em vez de arquivos, usando os procedimentos descritos no SRFI 6. [30]O padrão R6RS especifica procedimentos de porta muito mais sofisticados e capazes e muitos novos tipos de porta.

Os exemplos a seguir são escritos no esquema R5RS estrito.

Exemplo 1: Com saída padronizada para (porta de saída atual):

( let (( hello0  ( lambda ()  ( display "Hello world" )  ( newline )))) 
  ( hello0 ))

Exemplo 2: Como 1, mas usando o argumento de porta opcional para procedimentos de saída

( let (( hello1  ( lambda ( p )  ( display "Hello world"  p )  ( newline p )))) 
  ( hello1  ( current-output-port )))

Exemplo 3: Como 1, mas a saída é redirecionada para um arquivo recém-criado

;; NB: with-output-to-file é um procedimento opcional em R5RS 
( let (( hello0  ( lambda ()  ( display "Hello world" )  ( newline )))) 
  ( with-output-to-file "helloworldoutputfile"  hello0 ) )

Exemplo 4: Como 2, mas com arquivo explícito aberto e porta fechada para enviar saída para arquivo

( let (( hello1  ( lambda ( p )  ( display "Hello world"  p )  ( newline p ))) 
      ( output-port  ( open-output-file "helloworldoutputfile" ))) 
  ( hello1  output-port ) 
  ( close-output -porta porta de saída ))

Exemplo 5: Como 2, mas usando call-with-output-file para enviar a saída para um arquivo.

( let (( hello1  ( lambda ( p )  ( display "Hello world"  p )  ( newline p )))) 
  ( call-with-output-file "helloworldoutputfile"  hello1 ))

Procedimentos semelhantes são fornecidos para entrada. O esquema R5RS fornece os predicados input-port?e output-port?. Para entrada e saída de caracteres, write-char, read-chare peek-charsão char-ready?fornecidos. Para escrever e ler expressões Scheme, Scheme fornece reade write. Em uma operação de leitura, o resultado retornado é o objeto de fim de arquivo se a porta de entrada atingiu o fim do arquivo, e isso pode ser testado usando o predicado eof-object?.

Além do padrão, o SRFI 28 define um procedimento básico de formatação semelhante à formatfunção do Common Lisp, após o qual é nomeado. [31]

Redefinição de procedimentos padrão

Em Scheme, os procedimentos são vinculados a variáveis. No R5RS, o padrão da linguagem exigia formalmente que os programas pudessem alterar as ligações variáveis ​​de procedimentos internos, redefinindo-os efetivamente. (R5RS "Mudanças de idioma") [4] Por exemplo, pode-se estender +para aceitar strings, bem como números, redefinindo-o:

( set! + 
      ( let (( original +  + )) 
        ( lambda args 
          ( apply ( if ( ou ( null? args )  ( string? ( car args ))) 
                     string-append 
                     original+ ) 
                 args )))) 
( + 1  2  3 ) 
===>  6 
( + "1"  "2"  "3" ) 
===>  "123"

No R6RS cada ligação, incluindo as padrão, pertence a alguma biblioteca, e todas as ligações exportadas são imutáveis. (R6RS sec 7.1) [9] Por causa disso, a redefinição de procedimentos padrão por mutação é proibida. Em vez disso, é possível importar um procedimento diferente sob o nome de um padrão, que na verdade é semelhante à redefinição.

Nomenclatura e convenções de nomenclatura

No esquema padrão, os procedimentos que convertem de um tipo de dados para outro contêm a cadeia de caracteres "->" em seu nome, os predicados terminam com um "?" e os procedimentos que alteram o valor dos dados já alocados terminam com um "!". Essas convenções são frequentemente seguidas por programadores de esquemas.

Em contextos formais, como padrões de esquema, a palavra "procedimento" é usada de preferência a "função" para se referir a uma expressão lambda ou procedimento primitivo. No uso normal, as palavras "procedimento" e "função" são usadas de forma intercambiável. A aplicação do procedimento é por vezes referida formalmente como combinação .

Como em outros Lisps, o termo " thunk " é usado em Scheme para se referir a um procedimento sem argumentos. O termo "recursão de cauda adequada" refere-se à propriedade de todas as implementações de Scheme, que realizam otimização de chamada de cauda de modo a suportar um número indefinido de chamadas de cauda ativas .

A forma dos títulos dos documentos padrões desde R3RS, "Revised n Report on the Algorithmic Language Scheme", é uma referência ao título do documento padrão ALGOL 60 , "Revised Report on the Algorithmic Language Algol 60," The Summary page do R3RS é modelado de perto na página Resumo do Relatório ALGOL 60. [32] [33]

Revisão de formulários e procedimentos padrão

A linguagem é formalmente definida nas normas R5RS (1998) e R6RS (2007). Eles descrevem "formas" padrão: palavras-chave e sintaxe de acompanhamento, que fornecem a estrutura de controle da linguagem e procedimentos padrão que executam tarefas comuns.

Formulários padrão

Esta tabela descreve os formulários padrão em Scheme. Alguns formulários aparecem em mais de uma linha porque não podem ser facilmente classificados em uma única função na linguagem.

Os formulários marcados com "L" nesta tabela são classificados como formulários de "biblioteca" derivados no padrão e geralmente são implementados como macros usando formulários mais fundamentais na prática, tornando a tarefa de implementação muito mais fácil do que em outras linguagens.

Formulários padrão na linguagem R5RS Scheme
Objetivo Formulários
Definição definir
Construções de vinculação lambda, do (L), let (L), let* (L), letrec (L)
Avaliação condicional se, cond (L), caso (L) e (L), ou (L)
Avaliação sequencial começar (*)
Iteração lambda, do (L), chamado let (L)
Extensão sintática define-sintaxe, let-syntax, letrec-syntax, sintaxe-regras (R5RS), sintaxe-case (R6RS)
Citação quote('), unquote(,), quasiquote(`), unquote-splicing(,@)
Tarefa definir!
Avaliação atrasada atraso (L)

Observe que beginé definido como uma sintaxe de biblioteca no R5RS, mas o expansor precisa saber sobre isso para obter a funcionalidade de emenda. Em R6RS não é mais uma sintaxe de biblioteca.

Procedimentos padrão

As duas tabelas a seguir descrevem os procedimentos padrão no esquema R5RS. O R6RS é muito mais extenso e um resumo desse tipo não seria prático.

Alguns procedimentos aparecem em mais de uma linha porque não podem ser facilmente classificados em uma única função na linguagem.

Procedimentos padrão na linguagem R5RS Scheme
Objetivo Procedimentos
Construção vetor, make-vetor, make-string, lista
Predicados de equivalência eq?, eqv?, equal?, string=?, string-ci=?, char=?, char-ci=?
Conversão de tipo vetor->lista, lista->vetor, número->string, string->número, símbolo->string, string->symbol, char->integer, integer->char, string->list, list->string
Números Ver tabela separada
Cordas string?, make-string, string, string-length, string-ref, string-set!, string=?, string-ci=?, string<? string-ci<?, string<=? string-ci<=?, string>? string-ci>?, string>=? string-ci>=?, substring, string-append, string->list, list->string, string-copy, string-fill!
Personagens char?, char=?, char-ci=?, char<? char-ci<?, char<=? char-ci<=?, char>? char-ci>?, char>=? char-ci>=?, char-alphabetic?, char-numeric?, char-whitespace?, char-upper-case?, char-lower-case?, char->integer, integer->char, char-upcase, char-downcase
Vetores make-vector, vector, vector?, vector-length, vector-ref, vector-set!, vector->list, list->vector, vector-fill!
Símbolos símbolo->string, string->símbolo, símbolo?
Pares e listas par?, cons, carro, cdr, set-car!, set-cdr!, null?, list?, list, length, append, reverse, list-tail, list-ref, memq. memv. membro, assq, assv, assoc, lista->vetor, vetor->lista, lista->string, string->lista
Predicados de identidade boolean?, par?, símbolo?, número?, caractere?, string?, vetor?, porta?, procedimento?
Continuações call-with-current-continuation (call/cc), valores, call-with-values, dynamic-wind
Ambientes eval, schema-report-environment, null-environment, interação-ambiente (opcional)
Entrada/saída display, newline, read, write, read-char, write-char, peek-char, char-ready?, eof-object? arquivo de entrada aberto, arquivo de saída aberto, porta de entrada fechada, porta de saída fechada, porta de entrada?, porta de saída?, porta de entrada atual, porta de saída atual, chamada com- arquivo de entrada, chamada com arquivo de saída, com entrada de arquivo (opcional), com saída para arquivo (opcional)
Interface do sistema load (opcional), transcript-on (opcional), transcript-off (opcional)
Avaliação atrasada força
Programação funcional procedimento?, aplicar, mapear, para cada
Booleanos boleano? não

Os procedimentos de string e caractere que contêm "-ci" em seus nomes realizam comparações independentes de maiúsculas e minúsculas entre seus argumentos: as versões maiúsculas e minúsculas do mesmo caractere são consideradas iguais.

Procedimentos numéricos padrão na linguagem R5RS Scheme
Objetivo Procedimentos
Operadores aritméticos básicos +, -, *, /, abs, quociente, resto, módulo, gcd, lcm, expt, sqrt
Números racionais numerador, denominador, racional?, racionalizar
Aproximação chão, teto, truncar, redondo
Exatidão inexato->exato, exato->inexato, exato?, inexato?
Desigualdades <, <= , >, >=, =
Predicados diversos zero?, negativo?, positivo? chance? até?
Máximo e mínimo máximo, mínimo
Trigonometria pecado, cos, tan, asin, acos, atan
Exponenciais exp, log
Números complexos make-retangular, make-polar, real-part, imag-part, magnitude, ângulo, complexo?
Entrada-saída número->string, string->número
Predicados de tipo inteiro?, racional?, real?, complexo?, número?

Implementações de - e / que levam mais de dois argumentos são definidas, mas deixadas opcionais em R5RS.

Solicitações de Esquema para Implementação

Por causa do minimalismo do Scheme, muitos procedimentos comuns e formas sintáticas não são definidos pelo padrão. Para manter a linguagem principal pequena, mas facilitar a padronização de extensões, a comunidade Scheme tem um processo de "Scheme Request for Implementation" (SRFI) pelo qual as bibliotecas de extensão são definidas por meio de uma discussão cuidadosa de propostas de extensão. Isso promove a portabilidade do código. Muitos dos SRFIs são suportados por todas ou pela maioria das implementações do Scheme.

SRFIs com suporte bastante amplo em diferentes implementações incluem: [34]

  • 0: construção de expansão condicional baseada em recursos
  • 1: lista de biblioteca
  • 4: tipos de dados vetoriais numéricos homogêneos
  • 6: portas de string básicas
  • 8: receber, vinculando a vários valores
  • 9: definição de tipos de registro
  • 13: biblioteca de strings
  • 14: biblioteca de conjuntos de caracteres
  • 16: sintaxe para procedimentos de aridade variável
  • 17: conjunto generalizado!
  • 18: Suporte multithread
  • 19: tipos de dados de tempo e procedimentos
  • 25: primitivos de matriz multidimensional
  • 26: notação para parâmetros especializados sem curry
  • 27: fontes de bits aleatórios
  • 28: strings de formato básico
  • 29: localização
  • 30: comentários de várias linhas aninhados
  • 31: um formulário especial para avaliação recursiva
  • 37: args-fold: um processador de argumentos de programa
  • 39: objetos de parâmetro
  • 41: fluxos
  • 42: compreensões ansiosas
  • 43: biblioteca de vetores
  • 45: primitivos para expressar algoritmos lentos iterativos
  • 60: inteiros como bits
  • 61: uma cláusula cond mais geral
  • 66: vetores de octeto
  • 67: comparar procedimentos

Implementações

O design elegante e minimalista fez do Scheme um alvo popular para designers de linguagem, amadores e educadores, e devido ao seu tamanho pequeno, o de um intérprete típico , também é uma escolha popular para sistemas embarcados e scripts . Isso resultou em dezenas de implementações, [35] a maioria das quais difere tanto umas das outras que portar programas de uma implementação para outra é bastante difícil, e o pequeno tamanho da linguagem padrão significa que escrever um programa útil de qualquer grande complexidade no esquema padrão, portátil é quase impossível. [7] O padrão R6RS especifica uma linguagem muito mais ampla, na tentativa de ampliar seu apelo aos programadores.

Quase todas as implementações fornecem um loop tradicional de leitura-eval-impressão no estilo Lisp para desenvolvimento e depuração. Muitos também compilam programas Scheme para binários executáveis. O suporte para a incorporação de código Scheme em programas escritos em outras linguagens também é comum, pois a relativa simplicidade das implementações Scheme o torna uma escolha popular para adicionar recursos de script a sistemas maiores desenvolvidos em linguagens como C . Os intérpretes de esquema Gambit , Chicken e Bigloo compilam Scheme para C, o que torna a incorporação particularmente fácil. Além disso, o compilador do Bigloo pode ser configurado para gerar bytecode JVM , e também apresenta um gerador de bytecode experimental para .NET .

Algumas implementações suportam recursos adicionais. Por exemplo, Kawa e JScheme fornecem integração com classes Java, e os compiladores Scheme to C geralmente facilitam o uso de bibliotecas externas escritas em C, até permitir a incorporação de código C real na fonte Scheme. Outro exemplo é o Pvts , que oferece um conjunto de ferramentas visuais de apoio ao aprendizado do Scheme.

Uso

O esquema é amplamente utilizado por um número [36] de escolas; em particular, vários cursos introdutórios de Ciência da Computação usam o Scheme em conjunto com o livro Structure and Interpretation of Computer Programs (SICP). [37] Nos últimos 12 anos, a PLT executou o projeto ProgramByDesign (anteriormente TeachScheme!), que expôs cerca de 600 professores do ensino médio e milhares de alunos do ensino médio à programação rudimentar do Scheme. A antiga aula introdutória de programação 6.001 do MIT foi ministrada no Scheme, [38] Embora o 6.001 tenha sido substituído por cursos mais modernos, o SICP continua a ser ministrado no MIT. [39]Da mesma forma, a aula introdutória na UC Berkeley , CS 61A, foi até 2011 ministrada inteiramente em Scheme, exceto pequenas distrações no Logo para demonstrar o escopo dinâmico. Hoje, como o MIT, Berkeley substituiu o syllabus por uma versão mais moderna que é ensinada principalmente em Python 3 , mas o syllabus atual ainda é baseado no antigo currículo e partes da aula ainda são ministradas em Scheme. [40]

O livro How to Design Programs , de Matthias Felleisen, atualmente na Northeastern University, é usado por algumas instituições de ensino superior para seus cursos introdutórios de ciência da computação. Tanto a Northeastern University quanto o Worcester Polytechnic Institute usam o Scheme exclusivamente para seus cursos introdutórios Fundamentos de Ciência da Computação (CS2500) e Introdução ao Projeto de Programa (CS1101), respectivamente. [41] [42] Rose-Hulman usa Scheme em seu curso mais avançado de Conceitos de Linguagem de Programação. [43] O curso principal da Brandeis University , Structure and Interpretations of Computer Programs (COSI121b), também é ministrado exclusivamente em Scheme pelo cientista da computação teóricoHarry Mairson . [44] A classe introdutória da Universidade de Indiana, C211, é ministrada inteiramente em Scheme. Uma versão individualizada do curso, CS 61AS, continua a usar o Scheme. [45] Os cursos introdutórios de ciência da computação em Yale e Grinnell College também são ministrados em Scheme. [46] Programming Design Paradigms, [47] um curso obrigatório para os alunos de graduação em ciência da computação na Northeastern University, também usa amplamente Scheme. O antigo curso introdutório de Ciência da Computação da Universidade de Minnesota - Twin Cities, CSCI 1901, também usava Scheme como linguagem primária, seguido por um curso que introduzia os alunos à linguagem de programação Java; [48] ​​no entanto, seguindo o exemplo do MIT, o departamento substituiu 1901 pelo CSCI 1133 baseado em Python, [49] enquanto a programação funcional é abordada em detalhes no curso de terceiro semestre CSCI 2041. [50] Na indústria de software, A Tata Consultancy Services , a maior empresa de consultoria de software da Ásia, usa o Scheme em seu programa de treinamento de um mês para recém-formados. [ citação necessária ]

O esquema também é/foi usado para o seguinte:

Veja também

Referências

  1. ^ "A linguagem de programação do esquema" . MIT .
  2. ^ LISP comum: A língua, ò Ed., imprensa digital do Jr. de Guy L. Steele; 1981. ISBN 978-1-55558-041-4 . "Common Lisp é um novo dialeto de Lisp, um sucessor de MacLisp, fortemente influenciado por ZetaLisp e até certo ponto por Scheme e InterLisp." 
  3. ^ a b 1178-1990 (Reaff 2008) Padrão IEEE para a linguagem de programação do esquema. Número de peça IEEE STDPD14209, reafirmado por unanimidade em uma reunião do Comitê de Revisão de Padrões do IEEE-SA Standards Board (RevCom), 26 de março de 2008 (item 6.3 sobre ata), ata de reafirmação acessada em outubro de 2009. NOTA: este documento está disponível apenas para compra do IEEE e não está disponível online no momento da escrita (2009).
  4. ^ a b c d e f g h i j k l m n o p q Richard Kelsey; William Clinger; Jonathan Reis; et ai. (agosto de 1998). "Revisado 5 Relatório sobre o Esquema de Linguagem Algorítmica" . Computação Simbólica e de Ordem Superior . 11 (1): 7–105. doi : 10.1023/A:1010051815785 . S2CID 14069423 . Recuperado 2012-08-09 . 
  5. ^ Shinn, Alex; Cowan, John; Gleckler, Arthur (julho de 2013). "Revisado 7 Relatório sobre o Esquema de Linguagem Algorítmica (R7RS)" . Recuperado 2020-11-08 .
  6. ^ a b "R7RS final disponível" (PDF) . 2013-07-06.
  7. ^ a b c Will Clinger, Marc Feeley, Chris Hanson, Jonathan Rees e Olin Shivers (2009-08-20). "Declaração de Posição (rascunho) " . Comitê Diretivo do Esquema . Recuperado 2012-08-09 .{{cite web}}: CS1 maint: vários nomes: lista de autores ( link )
  8. ^ a b c d Sussman, Gerald Jay; Steele, Guy L. (1 de dezembro de 1998). "O primeiro relatório sobre o esquema revisitado". Computação Simbólica e de Ordem Superior . 11 (4): 399–404. doi : 10.1023/A:1010079421970 . S2CID 7704398 . 
  9. ^ a b c d Sperber, Michael; Dybvig, R. Kent; Flatt, Matthew; Van Straaten, Anton; et ai. (agosto de 2007). "Revisado 6 Relatório sobre o Esquema de Linguagem Algorítmica (R6RS)" . Comitê Diretivo do Esquema . Recuperado 2011-09-13 .
  10. ^ "Implementações R6RS" . r6rs.org . Recuperado em 24/11/2017 .
  11. ^ Abdulaziz Ghuloum (2007-10-27). "Bibliotecas R6RS e sistema de caso de sintaxe (psyntax)" . Esquema Ícaro . Recuperado 2009-10-20 .
  12. ^ Mantenha, Andrew W.; Dybvig, R. Kent (novembro de 2014). "Uma representação em tempo de execução de tipos de registro de esquema". Jornal de Programação Funcional . 24 (6): 675–716. doi : 10.1017/S0956796814000203 . S2CID 40001845 . 
  13. ^ "Revisado^6 Relatório sobre o Esquema de Linguagem Algorítmica, Apêndice E: mudanças de idioma" . Comitê Gestor do Esquema. 26-09-2007 . Recuperado 2009-10-20 .
  14. ^ "Eleitorado R6RS" . Comitê Gestor do Esquema. 2007 . Recuperado 2012-08-09 .
  15. ^ Marc Feeley (compilação) (2007-10-26). "Intenções dos implementadores em relação ao R6RS" . Scheme Steering Committee, lista de discussão r6rs-discuss . Recuperado 2012-08-09 .
  16. ^ "R7RS 9º rascunho disponível" (PDF) . 15-04-2013.
  17. ^ Will Clinger (2013-05-10). "extensão do período de votação" . Scheme Language Steering Committee, lista de discussão de relatórios de esquema. Arquivado a partir do original em 21/07/2013 . Recuperado 2013-07-07 .
  18. A implementação do Scheme 48 é assim chamada porque o interpretador foi escrito por Richard Kelsey e Jonathan Rees em 48 horas (6 a 7 de agosto de 1986. Veja Richard Kelsey; Jonathan Rees; Mike Sperber (2008-01-10). "The Esquema incompleto 48 Manual de referência para versão 1.8" . Jonathan Rees, s48.org . Recuperado em 2012-08-09 .
  19. ^ a b Gerald Jay Sussman & Guy Lewis Steele Jr. (dezembro de 1975). "Esquema: um intérprete para cálculo lambda estendido" (PDF) . Memorandos de IA . Laboratório de IA do MIT . AIM-349. hdl : 1721.1/5794 . Recuperado em 23 de dezembro de 2021 .
  20. ^ Joel Moses (junho de 1970), The Function of FUNCTION in LISP, or Why the FUNARG Problem Should Be Call the Environment Problem , hdl : 1721.1/5854 , AI Memo 199,Uma metáfora útil para a diferença entre FUNCTION e QUOTE em LISP é pensar em QUOTE como uma cobertura porosa ou aberta da função, uma vez que variáveis ​​livres escapam para o ambiente atual. FUNCTION atua como uma cobertura fechada ou não porosa (daí o termo "fechamento" utilizado pela Landin). Assim, falamos de expressões Lambda "abertas" (funções em LISP são geralmente expressões Lambda) e expressões Lambda "fechadas". [...] Meu interesse pelo problema do meio ambiente começou quando Landin, que tinha um profundo conhecimento do problema, visitou o MIT durante 1966-67. Percebi então a correspondência entre as listas da FUNARG que são os resultados da avaliação das expressões Lambda "fechadas" em LISP e Lambda Closures do ISWIM .
  21. ^ van Tonder, André (1 de janeiro de 2004). "Um cálculo lambda para computação quântica". SIAM Journal on Computing . 33 (5): 1109-1135. arXiv : quant-ph/0307150 . doi : 10.1137/S0097539703432165 . S2CID 613571 . 
  22. ^ Niehren, J.; Schwinghammer, J.; Smolka, G. (novembro de 2006). "Um cálculo lambda concorrente com futuros" (PDF) . Informática Teórica . 364 (3): 338–356. doi : 10.1016/j.tcs.2006.08.016 .
  23. ^ Gerald Jay Sussman & Guy Lewis Steele Jr. (março de 1976). "Lambda: The Ultimate Imperative" . Memorandos de IA . Laboratório de IA do MIT . AIM-353. Arquivado a partir do original (postscript ou PDF) em 2016-05-10 . Recuperado 2012-08-09 .
  24. ^ Gabriel, Richard P .; Pitman, Kent (1988). "Questões Técnicas de Separação em Células de Função e Células de Valor" . Lisp e Computação Simbólica . Vol. 1, não. 1 (publicado em junho de 1988). págs. 81-101. doi : 10.1007/BF01806178 . Recuperado 2012-08-09 .
  25. ^ a b Philip L. Bewig (2008-01-24). "SRFI 41: Fluxos" . Os Editores SRFI, schemers.org . Recuperado 2012-08-09 .
  26. ^ William Clinger e Jonathan Rees, ed. (1991). "Revisado 4 Relatório sobre o Esquema de Linguagem Algorítmica" . Ponteiros ACM Lisp . 4 (3): 1–55 . Recuperado 2012-08-09 .
  27. ^ Flatt, Matthew (2016). "Ligação como conjuntos de escopos". Anais do 43º Simpósio Anual ACM SIGPLAN-SIGACT sobre Princípios de Linguagens de Programação . pp. 705-717. doi : 10.1145/2837614.2837620 . ISBN 978-1-4503-3549-2. S2CID  15401805 .
  28. ^ Jonathan Rees, The Scheme of Things The June 1992 Meeting Archived 2011-07-16 at the Wayback Machine (postscript), em Lisp Pointers, V(4), outubro-dezembro de 1992. Recuperado em 2012-08-09
  29. ^ Taylor Campbell (2005-07-21). "SRFI 62: comentários da expressão S" . Os Editores SRFI, schemers.org . Recuperado 2012-08-09 .
  30. ^ William D Clinger (1999-07-01). "SRFI 6: Portas de string básicas" . Os Editores SRFI, schemers.org . Recuperado 2012-08-09 .
  31. ^ Scott G. Miller (2002-06-25). "SRFI 28: Strings de formato básico" . Os Editores SRFI, schemers.org . Recuperado 2012-08-09 .
  32. ^ JW Backus; FL Bauer; J. Verde; C. Katz; J. McCarthy P. Naur; et ai. (janeiro-abril de 1960). "Relatório revisado sobre a linguagem algorítmica Algol 60" . Numerische Mathematik, Comunicações da ACM e Journal of the British Computer Society . Recuperado 2012-08-09 .
  33. ^ Jonathan Reis; William Clinger, eds. (dezembro de 1986). "Revisado(3) Relatório sobre o Esquema de Linguagem Algorítmica (Dedicado à Memória do ALGOL 60)" . Avisos ACM SIGPLAN . 21 (12): 37–79. CiteSeerX 10.1.1.29.3015 . doi : 10.1145/15042.15043 . hdl : 1721.1/6424 . S2CID 43884422 . Recuperado 2012-08-09 .  
  34. ^ "Sistemas de esquema que apoiam SRFIs" . Os Editores SRFI, schemers.org. 30-08-2009 . Recuperado 2012-08-09 .
  35. ^ 75 implementações conhecidas do Scheme estão listadas por "scheme-faq-standards" . Wiki do Esquema da Comunidade. 2009-06-25 . Recuperado 2009-10-20 .
  36. ^ Ed Martin (2009-07-20). "Lista de escolas que utilizam o Esquema" . Schemers Inc. Recuperado 2009-10-20 .
  37. ^ "Lista de escolas que usam SICP" . Imprensa do MIT. 1999-01-26 . Recuperado 2009-10-20 .
  38. ^ Eric Grimson (primavera de 2005). "6.001 Estrutura e Interpretação de Programas de Computador" . MIT Open Courseware . Recuperado 2009-10-20 .
  39. ^ Alex Vandiver; Nelson Elhage; et ai. (janeiro de 2009). "6.184 - Zumbis bebem cafeína 6.001" . MIT CSAIL . Recuperado 2009-10-20 .
  40. ^ John DeNero (outono de 2019). "Ciência da Computação 61A, Berkeley" . Departamento de Engenharia Elétrica e Ciências da Computação, Berkeley . Recuperado 2019-12-17 .
  41. ^ CS 2500: Fundamentos de Ciência da Computação I , Northeastern University
  42. ^ CS 1101: Introdução ao Projeto de Programa (A05): software do curso , Worcester Polytechnic Institute
  43. ^ "CSSE 304: Conceitos de linguagem de programação" . Instituto de Tecnologia Rose-Hulman .
  44. ^ "Primavera 2021 CS121b Syllabus" (PDF) . Universidade Brandeis .
  45. ^ https://berkeley-cs61as.github.io
  46. ^ Dana Angluin (outono de 2009). "Introdução à Ciência da Computação (CPSC 201)" . O Zoológico, Departamento de Ciência da Computação da Universidade de Yale . Recuperado 2009-10-20 .
  47. ^ "Leituras do curso CSG107 dos paradigmas de projeto de programação" . Faculdade de Ciência da Computação e Informação da Northeastern University. Outono de 2009 . Recuperado 2012-08-09 .
  48. ^ Structure of Computer Programming I arquivado em 19/06/2010 na Wayback Machine , Departamento de Ciência da Computação, Universidade de Minnesota, primavera de 2010 (acessado em 30/01/2010).
  49. ^ Descrições do curso de classe obrigatória CSci e outras informações arquivadas em 25/10/2019 na Wayback Machine , Departamento de Ciência da Computação, Universidade de Minnesota (acessado em 25/10/2019)
  50. ^ CSCI 2041—Novo Curso CSE Curriculum Committee, University of Minnesota (acessado em 2019-10-25)
  51. Robin Cover (2002-02-25). "DSSSL - Document Style Semantics and Specification Language. ISO/IEC 10179:1996" . Folhas de rosto . Recuperado 2012-08-09 .
  52. ^ " A principal linguagem de script para o GIMP que foi anexada a ele hoje é Scheme. " De Dov Grobgeld (2002). "O Tutorial do Esquema Básico do GIMP" . A equipe do GIMP . Recuperado 2012-08-09 .
  53. ^ Todd Graham Lewis; David Zoll; Julian Missig (2002). "GNOME FAQ do Internet Archive" . A Equipe Gnome, gnome.org. Arquivado a partir do original em 2000-05-22 . Recuperado 2012-08-09 .
  54. ^ "guile-gnomo" . Fundação de Software Livre . Recuperado 2012-08-09 .
  55. ^ Laurence Brevard (2006-11-09). "Atualização do programa Synopsys MAP-in SM : Fórum de desenvolvedores de interoperabilidade EDA" (PDF) . Sinopse Inc. Recuperado 2012-08-09 .
  56. ^ Kawai, Shiro (outubro de 2002). "Colagem das Coisas - Esquema na Produção de Conteúdo em CG em Tempo Real" . Proceedings of the First International Lisp Conference, San Francisco : 342–348 . Recuperado 2012-08-09 .
  57. ^ Bill Magnuson; Hal Abelson & Mark Friedman (2009-08-11). "Sob o capô do App Inventor para Android" . Google Inc, blog oficial de pesquisa do Google . Recuperado 2012-08-09 .

Leitura adicional

Links externos