Schéma (langage de programmation)
Scheme est un dialecte minimaliste de la famille Lisp des langages de programmation . Le schéma se compose d’un petit noyau standard avec plusieurs outils d’extension de langage. [1]
Paradigmes | Multi-paradigme : fonctionnel , impératif , méta |
---|---|
Famille | Zézayer |
Conçu par | Guy L. Steele Gerald Jay Sussman |
Première apparition | 1975 ; il y a 47 ans ( 1975 ) |
Version stable | R7RS/2013 ; il y a 9 ans (2013) |
Discipline de frappe | Dynamique , latent , fort |
Portée | Lexical |
Extensions de nom de fichier | .scm, .ss |
Site Internet | www .scheme-reports .org |
Principales implémentations | |
Beaucoup (voir Implémentations de schéma ) |
|
Influencé par | |
ALGOL , Lisp , MDL | |
Influencé | |
Clojure , Common Lisp , Dylan , EuLisp , Haskell , Hop , JavaScript , Julia , Lua , MultiLisp , R , Racket , Ruby , Rust , S , Scala , T | |
|
Scheme a été créé dans les années 1970 au MIT AI Lab et publié par ses développeurs, Guy L. Steele et Gerald Jay Sussman , via une série de notes désormais connues sous le nom de Lambda Papers . C’était le premier dialecte de Lisp à choisir la portée lexicale et le premier à exiger des implémentations pour effectuer une optimisation des appels de queue , offrant un support plus solide pour la programmation fonctionnelle et les techniques associées telles que les algorithmes récursifs. C’était également l’un des premiers langages de programmation à prendre en charge les continuations de première classe . Il a eu une influence significative sur les efforts qui ont conduit au développement de Common Lisp . [2]
Le langage Scheme est normalisé dans la norme officielle IEEE [ 3] et dans une norme de facto appelée Revised n Report on the Algorithmic Language Scheme (R n RS). La norme la plus largement mise en œuvre est R5RS (1998). [4] La norme la plus récente, R7RS, [5] fournit des versions “petites” et “grandes” du langage Scheme ; la “petite” norme linguistique a été ratifiée en 2013. [6]Scheme a une base d’utilisateurs diversifiée en raison de sa compacité et de son élégance, mais sa philosophie minimaliste a également provoqué une grande divergence entre les implémentations pratiques, à tel point que le comité directeur de Scheme l’appelle “le langage de programmation le plus portable au monde” et “une famille de dialectes” plutôt qu’une seule langue. [7]
Histoire
Origines
Scheme a commencé dans les années 1970 comme une tentative de comprendre le modèle d’acteur de Carl Hewitt , pour lequel Steele et Sussman ont écrit un “petit interpréteur Lisp” en utilisant Maclisp , puis “ont ajouté des mécanismes pour créer des acteurs et envoyer des messages”. [8] Scheme s’appelait à l’origine “Schemer”, dans la tradition d’autres langages dérivés de Lisp tels que Planner ou Conniver . Le nom actuel résulte de l’utilisation par les auteurs du système d’exploitation ITS , qui limitait les noms de fichiers à deux composants d’au plus six caractères chacun. Actuellement, “Schemer” est couramment utilisé pour désigner un programmeur Scheme.
R6RS
Un nouveau processus de normalisation de la langue a commencé lors de l’atelier Scheme de 2003, dans le but de produire une norme R6RS en 2006. Ce processus a rompu avec l’approche antérieure de l’unanimité R n RS.
R6RS [9] dispose d’un système de module standard, permettant une séparation entre le langage de base et les bibliothèques. Un certain nombre d’ébauches de la spécification R6RS ont été publiées, la version finale étant R5.97RS. Un vote réussi a abouti à la ratification de la nouvelle norme, annoncée le 28 août 2007. [9]
Actuellement, les dernières versions de diverses implémentations de Scheme [10] prennent en charge la norme R6RS. Il existe une implémentation de référence portable des bibliothèques implicitement phasées proposées pour R6RS, appelée psyntax, qui se charge et s’amorce correctement sur diverses implémentations Scheme plus anciennes. [11]
Une caractéristique de R6RS est le descripteur de type d’enregistrement (RTD). Lorsqu’un RTD est créé et utilisé, la représentation du type d’enregistrement peut afficher la disposition de la mémoire. Il a également calculé le masque de bits de champ d’objet et les masques de bits de champ d’objet de schéma mutable, et a aidé le ramasse-miettes à savoir quoi faire avec les champs sans parcourir toute la liste des champs qui sont enregistrés dans le RTD. RTD permet aux utilisateurs d’étendre le RTD de base pour créer un nouveau système d’enregistrement. [12]
R6RS introduit de nombreux changements significatifs dans le langage. [13] Le code source est désormais spécifié en Unicode et un grand sous-ensemble de caractères Unicode peut désormais apparaître dans les symboles et identifiants de schéma, et il y a d’autres changements mineurs aux règles lexicales. Les données de caractères sont également désormais spécifiées en Unicode. De nombreuses procédures standard ont été déplacées vers les nouvelles bibliothèques standard, qui forment elles-mêmes une grande expansion de la norme, contenant des procédures et des formes syntaxiques qui ne faisaient auparavant pas partie de la norme. Un nouveau système de modules a été introduit et les systèmes de gestion des exceptions sont maintenant normalisés. Les règles de syntaxe ont été remplacées par une fonction d’abstraction syntaxique plus expressive (cas de syntaxe) qui permet l’utilisation de l’ensemble de Scheme au moment de l’expansion de la macro. Des implémentations conformes sont désormais nécessaires pour prendre en charge la tour numérique complète de Scheme , et la sémantique des nombres a été étendue, principalement dans le sens de la prise en charge de l’ IEEE 754 .standard pour la représentation numérique en virgule flottante.
R7RS
La norme R6RS a suscité la controverse car elle est considérée comme s’écartant de la philosophie minimaliste. [14] [15] En août 2009, le Scheme Steering Committee, qui supervise le processus de normalisation, a annoncé son intention de recommander de diviser Scheme en deux langages : un grand langage de programmation moderne pour les programmeurs ; et une petite version, un sous-ensemble de la grande version conservant le minimalisme loué par les éducateurs et les implémenteurs occasionnels. [7] Deux groupes de travail ont été créés pour travailler sur ces deux nouvelles versions de Scheme. Le site Scheme Reports Process contient des liens vers les chartes des groupes de travail, les discussions publiques et le système de suivi des problèmes.
Le neuvième projet de R7RS (petit langage) a été rendu disponible le 15 avril 2013. [16] Un vote ratifiant ce projet s’est clôturé le 20 mai 2013, [17] et le rapport final est disponible depuis le 6 août 2013, décrivant “le” petit “langage de cet effort: il ne peut donc pas être considéré isolément comme le successeur de R6RS”. [6]
1955 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
LISP 1, 1.5, LISP 2 (abandonné) | |||||||||||||
Maclisp | |||||||||||||
Interlisp | |||||||||||||
LMD | |||||||||||||
Lisp Machine Lisp | |||||||||||||
Schème | R5RS | R6RS | R7RS petit | ||||||||||
NÉANT | |||||||||||||
ZIL (Langage d’implémentation de Zork) | |||||||||||||
Franz Lisp | |||||||||||||
Lisp commun | |||||||||||||
Le Lisp | |||||||||||||
Programme MIT | |||||||||||||
J | |||||||||||||
Chez Scheme | |||||||||||||
Emacs LispComment | |||||||||||||
AutoLISP | |||||||||||||
PicoLisp | |||||||||||||
EuLisp | |||||||||||||
ILISISP | |||||||||||||
OpenLisp | |||||||||||||
Régime PLT | Raquette | ||||||||||||
Ruse GNU | |||||||||||||
LISP visuel | |||||||||||||
Clojure | |||||||||||||
Arc | |||||||||||||
LFE | |||||||||||||
Hy |
Caractéristiques distinctives
Scheme est avant tout un langage de programmation fonctionnel . Il partage de nombreuses caractéristiques avec d’autres membres de la famille des langages de programmation Lisp. La syntaxe très simple de Scheme est basée sur des s-expressions , des listes entre parenthèses dans lesquelles un opérateur de préfixe est suivi de ses arguments. Les programmes Scheme sont donc constitués de séquences de listes imbriquées. Les listes sont également la principale structure de données dans Scheme, ce qui conduit à une étroite équivalence entre le code source et les formats de données ( homoiconicité ). Les programmes Scheme peuvent facilement créer et évaluer dynamiquement des morceaux de code Scheme.
Le recours aux listes en tant que structures de données est partagé par tous les dialectes Lisp. Scheme hérite d’un riche ensemble de primitives de traitement de listecons telles que , caretcdr de ses ancêtres Lisp. Scheme utilise des variables typées strictement mais dynamiquement et prend en charge les procédures de première classe . Ainsi, les procédures peuvent être affectées en tant que valeurs à des variables ou transmises en tant qu’arguments à des procédures.
Cette section se concentre principalement sur les fonctionnalités innovantes du langage, y compris les fonctionnalités qui distinguent Scheme des autres Lisps. Sauf indication contraire, les descriptions des fonctionnalités se rapportent à la norme R5RS. Dans les exemples fournis dans cette section, la notation “===> résultat” est utilisée pour indiquer le résultat de l’évaluation de l’expression sur la ligne immédiatement précédente. Il s’agit de la même convention utilisée dans R5RS.
Minimalisme
Scheme est un langage très simple, beaucoup plus facile à mettre en œuvre que de nombreux autres langages de puissance expressive comparable . [18] Cette facilité est attribuable à l’utilisation du calcul lambda pour dériver une grande partie de la syntaxe du langage à partir de formes plus primitives. Par exemple, sur les 23 constructions syntaxiques basées sur l’expression s définies dans la norme R5RS Scheme, 14 sont classées comme formes dérivées ou de bibliothèque, qui peuvent être écrites sous forme de macros impliquant des formes plus fondamentales, principalement lambda. Comme le dit R5RS (§3.1): “La plus fondamentale des constructions de liaison de variables est l’expression lambda, car toutes les autres constructions de liaison de variables peuvent être expliquées en termes d’expressions lambda.” [4]
Formes fondamentales : define, lambda, quote, if, define-syntax, let-syntax, letrec-syntax, syntax-rules, set! Formes dérivées : do, let, let*, letrec, cond, case, and, or, begin, nommé let, delay, unquote, unquote-splicing, quasiquote
Exemple : une macro à implémenter leten tant qu’expression utilisant lambdapour effectuer les liaisons de variables.
( définition-syntaxe let ( règles-syntaxe () (( let (( var expr ) … ) corps … ) (( lambda ( var … ) corps … ) expr … ))))
Ainsi, utiliser letcomme défini ci-dessus une implémentation Scheme réécrirait ” (let ((a 1)(b 2)) (+ b a))” comme ” ((lambda (a b) (+ b a)) 1 2)”, ce qui réduit la tâche de l’implémentation à celle de coder les instanciations de procédure.
En 1998, Sussman et Steele ont fait remarquer que le minimalisme de Scheme n’était pas un objectif de conception conscient, mais plutôt le résultat involontaire du processus de conception. “Nous essayions en fait de construire quelque chose de compliqué et avons découvert, par hasard, que nous avions accidentellement conçu quelque chose qui remplissait tous nos objectifs mais était beaucoup plus simple que prévu… nous avons réalisé que le calcul lambda – un petit formalisme simple – pourrait servir de noyau à un langage de programmation puissant et expressif.” [8]
Portée lexicale
Comme la plupart des langages de programmation modernes et contrairement aux Lisps antérieurs tels que Maclisp , Scheme a une portée lexicale : toutes les liaisons de variables possibles dans une unité de programme peuvent être analysées en lisant le texte de l’unité de programme sans tenir compte des contextes dans lesquels elle peut être appelée. Cela contraste avec la portée dynamique qui était caractéristique des premiers dialectes Lisp, en raison des coûts de traitement associés aux méthodes de substitution textuelle primitives utilisées pour implémenter les algorithmes de portée lexicale dans les compilateurs et les interprètes de l’époque. Dans ces Lisps, il était parfaitement possible qu’une référence à une Variable libre à l’ intérieur d’une procédure renvoie à des liaisons bien distinctes externes à la procédure, selon le contexte de l’appel.
L’impulsion pour incorporer la portée lexicale, qui était un modèle de portée inhabituel au début des années 1970, dans leur nouvelle version de Lisp, est venue des études de Sussman sur ALGOL . Il a suggéré que les mécanismes de portée lexicale de type ALGOL aideraient à réaliser leur objectif initial d’implémentation du modèle d’acteur de Hewitt dans Lisp. [8]
Les idées clés sur la façon d’introduire la portée lexicale dans un dialecte Lisp ont été popularisées dans l’article Lambda de Sussman et Steele de 1975, “Scheme: An Interpreter for Extended Lambda Calculus”, [19] où ils ont adopté le concept de la fermeture lexicale (à la page 21 ), qui avait été décrit dans un AI Memo en 1970 par Joel Moses , qui attribuait l’idée à Peter J. Landin . [20]
Calcul lambda
La notation mathématique d’ Alonzo Church , le calcul lambda , a inspiré l’utilisation par Lisp de «lambda» comme mot-clé pour introduire une procédure, ainsi que pour influencer le développement de techniques de programmation fonctionnelle impliquant l’utilisation de fonctions d’ordre supérieur dans Lisp. Mais les premiers Lisps n’étaient pas des expressions appropriées du calcul lambda en raison de leur traitement des variables libres . [8]
Un système lambda formel a des axiomes et une règle de calcul complète. Il est utile pour l’analyse à l’aide de la logique et des outils mathématiques. Dans ce système, le calcul peut être vu comme une déduction directionnelle. La syntaxe du lambda calcul suit les expressions récursives à partir de x, y, z, …, des parenthèses, des espaces, du point et du symbole λ. [21] La fonction du calcul lambda comprend : Premièrement, servir de point de départ à une puissante logique mathématique. Deuxièmement, cela peut réduire la nécessité pour les programmeurs de prendre en compte les détails de mise en œuvre, car il peut être utilisé pour imiter l’évaluation de la machine. Enfin, le calcul lambda a créé une méta-théorie substantielle. [22]
L’introduction de la portée lexicale a résolu le problème en faisant une équivalence entre certaines formes de notation lambda et leur expression pratique dans un langage de programmation fonctionnel. Sussman et Steele ont montré que le nouveau langage pouvait être utilisé pour dériver élégamment toute la sémantique impérative et déclarative d’autres langages de programmation, y compris ALGOL et Fortran , et la portée dynamique d’autres Lisps, en utilisant des expressions lambda non pas comme de simples instanciations de procédure mais comme “contrôle structures et modificateurs d’environnement ». [23] Ils ont introduit le style de passage de continuationavec leur première description de Scheme dans le premier des papiers Lambda, et dans les papiers suivants, ils ont continué à démontrer la puissance brute de cette utilisation pratique du calcul lambda.
Structure de bloc
Scheme hérite de sa structure en blocs des langages structurés en blocs antérieurs, en particulier ALGOL . Dans Scheme, les blocs sont implémentés par trois constructions de liaison : let, let*et letrec. Par exemple, la construction suivante crée un bloc dans lequel un symbole appelé varest lié au nombre 10 :
( définir var “goose” ) ;; Toute référence à var ici sera liée à “goose” ( let (( var 10 )) ;; les instructions vont ici. Toute référence à var ici sera liée à 10. ) ;; Toute référence à var ici sera liée à “goose”
Les blocs peuvent être imbriqués pour créer des structures de blocs arbitrairement complexes en fonction des besoins du programmeur. L’utilisation de la structuration en blocs pour créer des liaisons locales atténue le risque de collision d’espaces de noms qui pourrait autrement se produire.
Une variante de let, let*, permet aux liaisons de faire référence à des variables définies précédemment dans la même construction, ainsi :
( let* (( var1 10 ) ( var2 ( + var1 12 ))) ;; Mais la définition de var1 ne pouvait pas faire référence à var2 )
L’autre variante, letrec, est conçue pour permettre aux procédures mutuellement récursives d’être liées les unes aux autres.
;; Calcul des séquences masculines et féminines de Hofstadter sous forme de liste de paires ( définir ( hofstadter-mâle-femelle n ) ( letrec (( femelle ( lambda ( n ) ( si ( = n 0 ) 1 ( – n ( mâle ( femelle ( – n 1 ))))))) ( mâle ( lambda ( n ) ( si ( = n 0 ) 0 ( – n ( femme ( mâle ( – n 1 )))))))) ( let loop (( i 0 )) ( if ( > i n ) ‘ () ( cons ( cons ( femelle i ) ( male i )) ( loop ( + je 1 )))))))) ( hofstadter-male-femelle 8 ) ===> (( 1 . 0 ) ( 1 . 0 ) ( 2 . 1 ) ( 2 . 2 ) ( 3 . 2 ) ( 3 . 3 ) ( 4 . 4 ) ( 5 . 4 ) ( 5 . 5 ) )
(Voir les séquences masculines et féminines de Hofstadter pour les définitions utilisées dans cet exemple.)
Toutes les procédures liées dans un single letrecpeuvent faire référence les unes aux autres par leur nom, ainsi qu’aux valeurs des variables définies précédemment dans le même letrec, mais elles ne peuvent pas faire référence à des valeurs définies ultérieurement dans le même letrec.
Une variante de let, la forme “named let”, a un identifiant après le mot- letclé. Cela lie les variables let à l’argument d’une procédure dont le nom est l’identifiant donné et dont le corps est le corps de la forme let. Le corps peut être répété à volonté en appelant la procédure. Le let nommé est largement utilisé pour implémenter l’itération.
Exemple : un compteur simple
( let loop (( n 1 )) ( if ( > n 10 ) ‘ () ( cons n ( loop ( + n 1 ))))) ===> ( 1 2 3 4 5 6 7 8 9 10 )
Comme toute procédure dans Scheme, la procédure créée dans le let nommé est un Objet de première classe.
Récursion de queue appropriée
Scheme a une construction d’itération, do, mais il est plus idiomatique dans Scheme d’utiliser la récursivité terminale pour exprimer l’ itération . Des implémentations Scheme conformes aux normes sont nécessaires pour optimiser les appels de queue afin de prendre en charge un nombre illimité d’appels de queue actifs (R5RS sec. 3.5) [4] – une propriété que le rapport Scheme décrit comme une récursivité de queue appropriée – ce qui permet aux programmeurs Scheme de écrire des algorithmes itératifs en utilisant des structures récursives, parfois plus intuitives. Les procédures récursives de queue et la forme nomméelet prennent en charge l’itération à l’aide de la récursivité de queue.
;; Construire une liste de cases de 0 à 9 : ;; Remarque : loop est simplement un symbole arbitraire utilisé comme étiquette. N’importe quel symbole fera l’affaire. ( définir ( liste-de-carrés n ) ( let loop (( i n ) ( res ‘ ())) ( if ( < i 0 ) res ( loop ( – i 1 ) ( cons ( * i i ) res )) ))) ( liste-de-carres 9 ) ===> ( 0 1 4 9 16 25 36 49 64 81 )
Suite de première classe
Les continuations dans Scheme sont des objets de première classe . Scheme fournit la procédure call-with-current-continuation(également connue sous le nom de call/cc) pour capturer la continuation actuelle en la regroupant sous la forme d’une procédure d’échappement liée à un argument formel dans une procédure fournie par le programmeur. (R5RS sec. 6.4) [4] Les continuations de première classe permettent au programmeur de créer des constructions de contrôle non locales telles que des itérateurs , des coroutines et des backtracking .
Les continuations peuvent être utilisées pour émuler le comportement des instructions de retour dans les langages de programmation impératifs. La fonction suivante , étant donné find-firstfunction funcet list lst, renvoie le premier élément tel que renvoie true.xlst(func x)
( define ( find-first func lst ) ( call-with-current-continuation ( lambda ( return-immediately ) ( for-each ( lambda ( x ) ( if ( func x ) ( return-immediately x ))) lst ) # f ))) ( trouver le premier entier? ‘ ( 1 /2 3 /4 5.6 7 8 /9 10 11 )) ===> 7 ( trouver le premier zéro? ‘ ( 1 2 3 4 )) ===> #f
L’exemple suivant, un puzzle de programmeur traditionnel, montre que Scheme peut gérer les continuations comme des objets de première classe, en les liant à des variables et en les passant comme arguments aux procédures.
( let* (( yin (( lambda ( cc ) ( display “@” ) cc ) ( call-with-current-continuation ( lambda ( c ) c )))) ( yang (( lambda ( cc ) ( display “* ” ) cc ) ( appel-avec-continuation-du-courant ( lambda ( c ) c ))))) ( yin yang ))
Lorsqu’il est exécuté, ce code affiche une séquence de comptage :@*@**@***@****@*****@******@*******@********…
Espace de noms partagé pour les procédures et les variables
Contrairement à Common Lisp, toutes les données et procédures de Scheme partagent un espace de noms commun, alors que dans Common Lisp , les fonctions et les données ont des espaces de noms séparés permettant à une fonction et à une variable d’avoir le même nom, et nécessitant une notation spéciale pour faire référence à un fonctionner comme une valeur. Ceci est parfois connu sous le nom de distinction ” Lisp-1 vs Lisp-2 “, faisant référence à l’espace de noms unifié de Scheme et aux espaces de noms séparés de Common Lisp. [24]
Dans Scheme, les mêmes primitives utilisées pour manipuler et lier des données peuvent être utilisées pour lier des procédures. Il n’y a pas d’équivalent de Common Lisp defunet de #’primitives.
;; Variable liée à un nombre : ( définir f 10 ) f ===> 10 ;; Mutation (modification de la valeur liée) ( set! f ( + f f 6 )) f ===> 26 ;; Affectation d’une procédure à la même variable : ( set! f ( lambda ( n ) ( + n 12 ))) ( f 6 ) ===> 18 ;; Affectation du résultat d’une expression à la même variable : ( set! f ( f 1 )) f ===> 13 ;; programmation fonctionnelle : ( apply + ‘ ( 1 2 3 4 5 6 )) ===> 21 ( set! f ( lambda ( n ) ( + n 100 ))) ( map f ‘ ( 1 2 3 )) === > ( 101 102 103 )
Normes de mise en œuvre
Cette sous-section documente les décisions de conception qui ont été prises au fil des ans et qui ont donné à Scheme un caractère particulier, mais qui ne sont pas les résultats directs de la conception originale.
Tour numérique
Scheme spécifie un ensemble relativement complet de types de données numériques, y compris des types complexes et rationnels , qui est connu dans Scheme sous le nom de tour numérique (R5RS sec. 6.2 [4] ). La norme les traite comme des abstractions et n’engage pas l’implémenteur dans des représentations internes particulières.
Les nombres peuvent avoir la qualité de l’exactitude. Un nombre exact ne peut être produit que par une suite d’opérations exactes impliquant d’autres nombres exacts – l’inexactitude est donc contagieuse. La norme spécifie que deux implémentations quelconques doivent produire des résultats équivalents pour toutes les opérations aboutissant à des nombres exacts.
La norme R5RS spécifie les procédures exact->inexactet inexact->exactqui peuvent être utilisées pour modifier l’exactitude d’un nombre. inexact->exactproduit “le nombre exact qui est numériquement le plus proche de l’argument”. exact->inexactproduit “le nombre inexact qui est numériquement le plus proche de l’argument”. La norme R6RS omet ces procédures du rapport principal, mais les spécifie comme procédures de compatibilité R5RS dans la bibliothèque standard (rnrs r5rs (6)).
Dans la norme R5RS, les implémentations Scheme ne sont pas tenues d’implémenter l’ensemble de la tour numérique, mais elles doivent implémenter “un sous-ensemble cohérent conforme à la fois aux objectifs de l’implémentation et à l’esprit du langage Scheme” (R5RS sec. 6.2.3). [4] La nouvelle norme R6RS nécessite l’implémentation de toute la tour, et “des objets entiers exacts et des objets de nombres rationnels exacts de taille et de précision pratiquement illimitées, et d’implémenter certaines procédures… afin qu’ils renvoient toujours des résultats exacts lorsqu’on leur donne des arguments exacts ” (R6RS art. 3.4, art. 11.7.1). [9]
Exemple 1 : arithmétique exacte dans une implémentation qui prend en charge les nombres complexes rationnels exacts.
;; Somme de trois nombres réels rationnels et de deux nombres complexes rationnels ( définir x ( + 1 /3 1 /4 -1 /5 -1 /3i 405 /50+2/3i )) x ===> 509 /60+1/ 3i ;; Vérifier l’exactitude. ( exact ? x ) ===> #t
Exemple 2 : même arithmétique dans une implémentation qui ne prend en charge ni les nombres rationnels exacts ni les nombres complexes, mais accepte les nombres réels en notation rationnelle.
;; Somme de quatre nombres réels rationnels ( définir xr ( + 1 /3 1 /4 -1 /5 405 /50 )) ;; Somme de deux nombres réels rationnels ( définir xi ( + -1 /3 2 /3 )) xr ===> 8,48333333333333 xi ===> 0,333333333333333 ;; Vérifier l’exactitude. ( exact ? xr ) ===> #f ( exact ? xi ) ===> #f
Les deux implémentations sont conformes à la norme R5RS mais la seconde n’est pas conforme à R6RS car elle n’implémente pas la tour numérique complète.
Évaluation différée
Le programme prend en charge l’évaluation différée par le biais du delayformulaire et de la procédure force.
( définir a 10 ) ( définir eval-aplus2 ( délai ( + a 2 ))) ( set! a 20 ) ( force eval-aplus2 ) ===> 22 ( définir eval-aplus50 ( délai ( + a 50 ))) ( let (( a 8 )) ( force eval-aplus50 )) ===> 70 ( set! a 100 ) ( force eval-aplus2 ) ===> 22
Le contexte lexical de la définition originale de la promesse est conservé, et sa valeur est également conservée après la première utilisation de force. La promesse n’est évaluée qu’une seule fois.
Ces primitives, qui produisent ou gèrent des valeurs appelées promises , peuvent être utilisées pour implémenter des constructions d’ évaluation paresseuses avancées telles que streams . [25]
Dans la norme R6RS, ce ne sont plus des primitives, mais à la place, elles sont fournies dans le cadre de la bibliothèque de compatibilité R5RS (rnrs r5rs (6)).
Dans R5RS, une implémentation suggérée de delayet forceest donnée, implémentant la promesse comme une procédure sans arguments (un thunk ) et utilisant la mémorisation pour s’assurer qu’elle n’est jamais évaluée qu’une seule fois, quel que soit le nombre de fois qu’elle forceest appelée (R5RS sec. 6.4 ). [4]
SRFI 41 permet l’expression de séquences finies et infinies avec une économie extraordinaire. Par exemple, voici une définition de la suite de Fibonacci utilisant les fonctions définies dans SRFI 41 : [25]
;; Définissez la séquence de Fibonacci : ( définir fibs ( stream-cons 0 ( stream-cons 1 ( stream-map + fibs ( stream-cdr fibs ))))) ;; Calculez le centième nombre dans la séquence : ( stream-ref fibs 99 ) ===> 218922995834555169026
Ordre d’évaluation des arguments de la procédure
La plupart des Lisps spécifient un ordre d’évaluation pour les arguments de la procédure. Le schéma ne fonctionne pas. L’ordre d’évaluation – y compris l’ordre dans lequel l’expression dans la position de l’opérateur est évaluée – peut être choisi par une implémentation appel par appel, et la seule contrainte est que “l’effet de toute évaluation simultanée de l’opérateur et les expressions d’opérande sont contraintes d’être cohérentes avec un ordre séquentiel d’évaluation.” (R5RS art. 4.1.3) [4]
( let (( ev ( lambda ( n ) ( display “Evaluating ” ) ( display ( if ( procedure? n ) “procedure” n )) ( newline ) n ))) (( ev + ) ( ev 1 ) ( ev 2 ))) ===> 3
ev est une procédure qui décrit l’argument qui lui est passé, puis renvoie la valeur de l’argument. Contrairement aux autres Lisps, l’apparition d’une expression dans la position de l’opérateur (le premier élément) d’une expression Scheme est tout à fait légale, tant que le résultat de l’expression dans la position de l’opérateur est une procédure.
En appelant la procédure “+” pour ajouter 1 et 2, les expressions (ev +), (ev 1) et (ev 2) peuvent être évaluées dans n’importe quel ordre, tant que l’effet n’est pas comme si elles étaient évaluées en parallèle . Ainsi, les trois lignes suivantes peuvent être affichées dans n’importe quel ordre par Scheme standard lorsque l’exemple de code ci-dessus est exécuté, bien que le texte d’une ligne ne puisse pas être entrelacé avec un autre car cela violerait la contrainte d’évaluation séquentielle.
Évaluation 1 Évaluation 2 Procédure d’évaluation
Macros hygiéniques
Dans la norme R5RS et également dans les rapports ultérieurs, la syntaxe de Scheme peut facilement être étendue via le système de macros. La norme R5RS a introduit un puissant système de macros hygiéniques qui permet au programmeur d’ajouter de nouvelles constructions syntaxiques au langage à l’aide d’un simple sous-langage de correspondance de motifs (R5RS sec 4.3). [4] Auparavant, le macro-système hygiénique avait été relégué à une annexe de la norme R4RS, en tant que système “de haut niveau” aux côtés d’un système de macro “de bas niveau”, qui étaient tous deux traités comme des extensions du schéma plutôt que comme un système. partie essentielle de la langue. [26]
Les implémentations du système macro hygiénique, également appelé syntax-rules, doivent respecter la portée lexicale du reste du langage. Ceci est assuré par des règles de dénomination et de portée spéciales pour l’expansion des macros et évite les erreurs de programmation courantes qui peuvent se produire dans les systèmes de macros d’autres langages de programmation. R6RS spécifie un système de transformation plus sophistiqué, syntax-case, qui est disponible comme extension de langage pour R5RS Scheme depuis un certain temps.
;; Définissez une macro pour implémenter une variante de “if” avec une multi-expression ;; vraie branche et pas de fausse branche. ( définir la syntaxe quand ( règles de syntaxe () (( quand pred exp exps … ) ( if pred ( begin exp exps … )))))
Les invocations de macros et de procédures ressemblent beaucoup (les deux sont des s-expressions), mais elles sont traitées différemment. Lorsque le compilateur rencontre une expression s dans le programme, il vérifie d’abord si le symbole est défini comme un mot-clé syntaxique dans la portée lexicale actuelle. Si tel est le cas, il tente alors d’étendre la macro, en traitant les éléments de la queue de l’expression s comme des arguments sans compiler le code pour les évaluer, et ce processus est répété de manière récursive jusqu’à ce qu’il ne reste plus d’invocations de macro. S’il ne s’agit pas d’un mot clé syntaxique, le compilateur compile le code pour évaluer les arguments dans la queue de l’expression s, puis pour évaluer la variable représentée par le symbole en tête de l’expression s et l’appeler en tant que procédure avec le les expressions de queue évaluées qui lui sont passées en tant qu’arguments réels.
La plupart des implémentations de Scheme fournissent également des systèmes de macros supplémentaires. Parmi les plus populaires figurent les fermetures syntaxiques , les macros de renommage explicites et define-macro, un système de macros non hygiénique similaire au defmacrosystème fourni dans Common Lisp .
L’incapacité de spécifier si une macro est hygiénique ou non est l’une des lacunes du système macro. Les modèles alternatifs d’expansion tels que les ensembles de portées offrent une solution potentielle. [27]
Environnements et évaluation
Avant R5RS, Scheme n’avait pas d’équivalent standard de la evalprocédure qui est omniprésente dans d’autres Lisps, bien que le premier document Lambda l’ait décrit evaluatecomme “similaire à la fonction LISP EVAL” [19] et le premier rapport révisé en 1978 l’a remplacé par enclose, qui pris deux arguments. Les deuxième, troisième et quatrième rapports révisés ont omis tout équivalent de eval.
La raison de cette confusion est que dans Scheme avec sa portée lexicale, le résultat de l’évaluation d’une expression dépend de l’endroit où elle est évaluée. Par exemple, il n’est pas clair si le résultat de l’évaluation de l’expression suivante doit être 5 ou 6 : [28]
( laissez (( nom ‘+ )) ( laissez (( + * )) ( évaluez ( nom de la liste 2 3 ))))
S’il est évalué dans l’environnement extérieur, où nameest défini, le résultat est la somme des opérandes. S’il est évalué dans l’environnement interne, où le symbole “+” a été lié à la valeur de la procédure “*”, le résultat est le produit des deux opérandes.
R5RS résout cette confusion en spécifiant trois procédures qui renvoient des environnements et en fournissant une procédure evalqui prend une expression s et un environnement et évalue l’expression dans l’environnement fourni. (R5RS sec. 6.5) [4] R6RS étend cela en fournissant une procédure appelée environmentpar laquelle le programmeur peut spécifier exactement quels objets importer dans l’environnement d’évaluation.
Avec le schéma moderne (généralement compatible avec R5RS) pour évaluer cette expression, il faut définir une fonction evaluatequi peut ressembler à ceci :
( définir ( évaluer expr ) ( eval expr ( interaction-environnement )))
interaction-environmentest l’environnement global de l’interprète.
Traitement des valeurs non booléennes dans les expressions booléennes
Dans la plupart des dialectes de Lisp, y compris Common Lisp, par convention, la valeur est NILévaluée à la valeur false dans une expression booléenne. Dans Scheme, depuis la norme IEEE en 1991, [3] toutes les valeurs sauf #f, y compris NILl’équivalent de Scheme qui s’écrit ‘(), prennent la valeur true dans une expression booléenne. (R5RS art. 6.3.1) [4]
Là où la constante représentant la valeur booléenne de true est Tdans la plupart des Lisps, dans Scheme c’est #t.
Disjonction des types de données primitifs
Dans Scheme, les types de données primitifs sont disjoints. Un seul des prédicats suivants peut être vrai pour un objet Scheme : boolean?, pair?, symbol?, number?, char?, string?, vector?, port?, procedure?. (R5RS sec 3.2) [4]
Dans le type de données numérique, en revanche, les valeurs numériques se chevauchent. Par exemple, une valeur entière satisfait tous les prédicats integer?, rational?, et real?en même temps. (R5RS sec 6.2) [4]complex?number?
Prédicats d’équivalence
Scheme a trois types différents d’équivalence entre des objets arbitraires désignés par trois prédicats d’équivalence différents , des opérateurs relationnels pour tester l’égalité, eq?, eqv?et equal?:
- eq?vaut à #fmoins que ses paramètres ne représentent le même objet de données en mémoire ;
- eqv?est généralement le même que eq?mais traite les objets primitifs (par exemple, les caractères et les nombres) spécialement pour que les nombres qui représentent la même valeur soient eqv?pairs s’ils ne font pas référence au même objet ;
- equal?compare des structures de données telles que des listes, des vecteurs et des chaînes pour déterminer si elles ont une structure et un eqv?contenu congruents. (R5RS sec. 6.1) [4]
Les opérations d’équivalence dépendantes du type existent également dans Scheme : string=?et string-ci=?comparent deux chaînes (ce dernier effectue une comparaison indépendante de la casse) ; char=?et char-ci=?comparer les caractères ; =compare les nombres. [4]
commentaires
Jusqu’à la norme R5RS, le commentaire standard dans Scheme était un point-virgule, ce qui rend le reste de la ligne invisible pour Scheme. De nombreuses implémentations ont pris en charge des conventions alternatives permettant aux commentaires de s’étendre sur plus d’une seule ligne, et la norme R6RS en autorise deux : une expression s entière peut être transformée en commentaire (ou “commentée”) en la faisant précéder de #;(introduced dans SRFI 62 [29] ) et un commentaire multiligne ou “commentaire en bloc” peut être produit en entourant le texte avec #|et |#.
Entrée sortie
L’entrée et la sortie du schéma sont basées sur le type de données du port . (R5RS sec 6.6) [4] R5RS définit deux ports par défaut, accessibles avec les procédures current-input-portet current-output-port, qui correspondent aux notions Unix d’ entrée standard et de sortie standard . La plupart des implémentations fournissent également current-error-port. La redirection de l’entrée et de la sortie standard est prise en charge dans la norme, par des procédures standard telles que with-input-from-fileet with-output-to-file. La plupart des implémentations fournissent des ports de chaîne avec des capacités de redirection similaires, permettant d’effectuer de nombreuses opérations d’entrée-sortie normales sur des tampons de chaîne au lieu de fichiers, en utilisant les procédures décrites dans SRFI 6. [30]La norme R6RS spécifie des procédures de port beaucoup plus sophistiquées et performantes et de nombreux nouveaux types de port.
Les exemples suivants sont écrits dans le schéma R5RS strict.
Exemple 1 : avec la sortie par défaut sur (current-output-port) :
( let (( hello0 ( lambda () ( display “Hello world” ) ( newline )))) ( hello0 ))
Exemple 2 : comme 1, mais en utilisant l’argument de port facultatif pour les procédures de sortie
( let (( hello1 ( lambda ( p ) ( display “Hello world” p ) ( newline p )))) ( hello1 ( current-output-port )))
Exemple 3 : comme 1, mais la sortie est redirigée vers un fichier nouvellement créé
;; NB : with-output-to-file est une procédure optionnelle dans R5RS ( let (( hello0 ( lambda () ( display “Hello world” ) ( newline )))) ( with-output-to-file “helloworldoutputfile” hello0 ) )
Exemple 4 : comme 2, mais avec un fichier explicite ouvert et un port fermé pour envoyer la sortie au fichier
( let (( hello1 ( lambda ( p ) ( display “Hello world” p ) ( newline p ))) ( output-port ( open-output-file “helloworldoutputfile” ))) ( hello1 output-port ) ( close-output -port port de sortie ))
Exemple 5 : Comme 2, mais en utilisant call-with-output-file pour envoyer la sortie vers un fichier.
( let (( hello1 ( lambda ( p ) ( display “Hello world” p ) ( newline p )))) ( call-with-output-file “helloworldoutputfile” hello1 ))
Des procédures similaires sont fournies pour la saisie. R5RS Scheme fournit les prédicats input-port?et output-port?. Pour l’entrée et la sortie de caractères, write-char, read-charet peek-charsont char-ready?fournis. Pour écrire et lire des expressions Scheme, Scheme fournit readet write. Lors d’une opération de lecture, le résultat renvoyé est l’objet de fin de fichier si le port d’entrée a atteint la fin du fichier, et cela peut être testé à l’aide du prédicat eof-object?.
En plus de la norme, SRFI 28 définit une procédure de formatage de base ressemblant à la formatfonction de Common Lisp, d’après laquelle elle porte le nom. [31]
Redéfinition des procédures standards
Dans Scheme, les procédures sont liées à des variables. Chez R5RS, la norme de langage exigeait formellement que les programmes puissent modifier les liaisons de variables des procédures intégrées, les redéfinissant ainsi. (R5RS “Language changes”) [4] Par exemple, on peut étendre +pour accepter des chaînes aussi bien que des nombres en le redéfinissant :
( set! + ( let (( original+ + )) ( lambda args ( apply ( if ( or ( null? args ) ( string? ( car args ))) string-append original+ ) args )))) ( + 1 2 3 ) ===> 6 ( + “1” “2” “3” ) ===> “123”
Dans R6RS, chaque liaison, y compris les liaisons standard, appartient à une bibliothèque et toutes les liaisons exportées sont immuables. (R6RS sec 7.1) [9] De ce fait, la redéfinition des procédures standards par mutation est interdite. Au lieu de cela, il est possible d’importer une procédure différente sous le nom d’une procédure standard, ce qui s’apparente en fait à une redéfinition.
Nomenclature et conventions de dénomination
Dans le schéma standard, les procédures qui convertissent d’un type de données à un autre contiennent la chaîne de caractères “->” dans leur nom, les prédicats se terminent par un “?”, et les procédures qui modifient la valeur des données déjà allouées se terminent par un “!”. Ces conventions sont souvent suivies par les programmeurs Scheme.
Dans des contextes formels tels que les normes Scheme, le mot “procédure” est utilisé de préférence à “fonction” pour désigner une expression lambda ou une procédure primitive. Dans l’usage normal, les mots “procédure” et “fonction” sont utilisés de manière interchangeable. L’application de la procédure est parfois appelée officiellement combinaison .
Comme dans d’autres Lisps, le terme « thunk » est utilisé dans Scheme pour désigner une procédure sans arguments. Le terme “récursivité de queue appropriée” fait référence à la propriété de toutes les implémentations de Scheme, qu’elles effectuent une optimisation des appels de queue de manière à prendre en charge un nombre indéfini d’ appels de queue actifs .
La forme des titres des documents standards depuis R3RS, “Revised n Report on the Algorithmic Language Scheme”, est une référence au titre du document standard ALGOL 60 , “Revised Report on the Algorithmic Language Algol 60,” La page Résumé du R3RS est étroitement calqué sur la page Résumé du rapport ALGOL 60. [32] [33]
Examen des formulaires et procédures standard
Apprendre encore plus Cette section ne cite aucune source . ( mai 2013 ) Please help improve this section by adding citations to reliable sources. Unsourced material may be challenged and removed. (Learn how and when to remove this template message) |
Le langage est formellement défini dans les normes R5RS (1998) et R6RS (2007). Ils décrivent des « formulaires » standard : des mots-clés et la syntaxe qui les accompagne, qui fournissent la structure de contrôle du langage, et des procédures standard qui exécutent des tâches courantes.
Formulaires standards
Ce tableau décrit les formulaires standard dans Scheme. Certaines formes apparaissent sur plusieurs lignes car elles ne peuvent pas être facilement classées en une seule fonction dans la langue.
Les formulaires marqués “L” dans ce tableau sont classés comme des formulaires de “bibliothèque” dérivés dans la norme et sont souvent implémentés sous forme de macros utilisant des formes plus fondamentales dans la pratique, ce qui rend la tâche de mise en œuvre beaucoup plus facile que dans d’autres langages.
But | Formes |
---|---|
Définition | définir |
Constructions de liaison | lambda, do (L), let (L), let* (L), letrec (L) |
Évaluation conditionnelle | si, cond (L), cas (L), et (L), ou (L) |
Évaluation séquentielle | commencer (*) |
Itération | lambda, do (L), nommé let (L) |
Extension syntaxique | définir-syntaxe, let-syntaxe, letrec-syntaxe, syntaxe-règles (R5RS), syntaxe-cas (R6RS) |
Citation | quote(‘), unquote(,), quasiquote(`), unquote-splicing(,@) |
Mission | Positionner! |
Évaluation différée | retard (L) |
Notez que cela beginest défini comme une syntaxe de bibliothèque dans R5RS, mais que l’expandeur doit la connaître pour obtenir la fonctionnalité d’épissage. Dans R6RS, ce n’est plus une syntaxe de bibliothèque.
Procédures standards
Les deux tableaux suivants décrivent les procédures standard du schéma R5RS. R6RS est beaucoup plus complet et un résumé de ce type ne serait pas pratique.
Certaines procédures apparaissent sur plusieurs lignes car elles ne peuvent pas être facilement classées en une seule fonction dans le langage.
But | Procédures |
---|---|
Construction | vecteur, make-vector, make-string, liste |
Prédicats d’équivalence | eq?, eqv?, égal?, string=?, string-ci=?, char=?, char-ci=? |
Conversion de types | vecteur->liste, liste->vecteur, nombre->chaîne, chaîne->nombre, symbole->chaîne, chaîne->symbole, caractère->entier, entier->caractère, chaîne->liste, liste->chaîne |
Nombres | Voir tableau séparé |
Cordes | string?, make-string, string, string-length, string-ref, string-set!, string=?, string-ci=?, string<? chaîne-ci<?, chaîne<=? chaîne-ci<=?, chaîne>? chaîne-ci>?, chaîne>=? string-ci>=?, substring, string-append, string->list, list->string, string-copy, string-fill ! |
Personnages | char?, char=?, char-ci=?, char<? car-ci<?, car<=? car-ci<=?, car>? car-ci>?, car>=? char-ci>=?, char-alphabétique?, char-numérique?, char-espace blanc?, char-majuscule?, char-minuscule?, char->entier, entier->car, char-majuscule, char-downcase |
Vecteurs | make-vector, vector, vector ?, vector-length, vector-ref, vector-set !, vector->list, list->vector, vector-fill ! |
Symboles | symbole->chaîne, chaîne->symbole, symbole ? |
Paires et listes | pair?, cons, car, cdr, set-car!, set-cdr!, null?, list?, list, length, append, reverse, list-tail, list-ref, memq. memv. membre, assq, assv, assoc, liste->vecteur, vecteur->liste, liste->chaîne, chaîne->liste |
Prédicats d’identité | booléen ?, paire ?, symbole ?, nombre ?, caractère ?, chaîne ?, vecteur ?, port ?, procédure ? |
Suite | call-with-current-continuation (call/cc), valeurs, call-with-values, dynamic-wind |
Environnements | eval, schema-report-environment, null-environment, interaction-environment (optionnel) |
Entrée sortie | display, newline, read, write, read-char, write-char, peek-char, char-ready?, eof-object? open-input-file, open-output-file, close-input-port, close-output-port, input-port?, output-port?, current-input-port, current-output-port, call-with- input-file, call-with-output-file, with-input-from-file(facultatif), with-output-to-file(facultatif) |
Interface système | chargement (facultatif), transcript-on (facultatif), transcript-off (facultatif) |
Évaluation différée | Obliger |
Programmation fonctionnelle | procédure ?, appliquer, mapper, pour chaque |
Booléens | booléen ? ne pas |
Les procédures de chaîne et de caractère qui contiennent “-ci” dans leurs noms effectuent des comparaisons indépendantes de la casse entre leurs arguments : les versions majuscules et minuscules du même caractère sont considérées comme étant égales.
But | Procédures |
---|---|
Opérateurs arithmétiques de base | +, -, *, /, abs, quotient, reste, modulo, pgcd, lcm, expt, sqrt |
Nombres rationnels | numérateur, dénominateur, rationnel ?, rationaliser |
Approximation | sol, plafond, tronqué, rond |
Exactitude | inexact->exact, exact->inexact, exact ?, inexact ? |
Inégalités | <, <= , >, >=, = |
Prédicats divers | zéro ?, négatif ?, positif ? étrange? même? |
Maximum et minimum | maximum minimum |
Trigonométrie | péché, cos, bronzer, asin, acos, atan |
Exponentiels | exp, journal |
Nombres complexes | faire-rectangulaire, faire-polaire, partie réelle, partie imag, magnitude, angle, complexe ? |
Entrée sortie | nombre->chaîne, chaîne->nombre |
Prédicats de type | entier ?, rationnel ?, réel ?, complexe ?, nombre ? |
Les implémentations de – et / qui prennent plus de deux arguments sont définies mais laissées facultatives dans R5RS.
Demandes de schéma pour la mise en œuvre
En raison du minimalisme de Scheme, de nombreuses procédures et formes syntaxiques courantes ne sont pas définies par la norme. Afin de garder le langage de base petit mais de faciliter la standardisation des extensions, la communauté Scheme a un processus de “Scheme Request for Implementation” (SRFI) par lequel les bibliothèques d’extensions sont définies grâce à une discussion approfondie des propositions d’extension. Cela favorise la portabilité du code. De nombreuses SRFI sont prises en charge par toutes ou la plupart des implémentations de Scheme.
Les SRFI avec un soutien assez large dans différentes implémentations incluent : [34]
- 0 : construction d’expansion conditionnelle basée sur les fonctionnalités
- 1 : bibliothèque de listes
- 4 : types de données vectorielles numériques homogènes
- 6 : ports de chaîne de base
- 8 : réception, liaison à plusieurs valeurs
- 9 : définir les types d’enregistrement
- 13 : bibliothèque de chaînes
- 14 : bibliothèque de jeux de caractères
- 16 : syntaxe pour les procédures d’ arité variable
- 17 : ensemble généralisé !
- 18 : Prise en charge du multithreading
- 19 : types de données temporelles et procédures
- 25 : primitives de tableau multidimensionnel
- 26 : notation pour spécialiser les paramètres sans curry
- 27 : sources de bits aléatoires
- 28 : chaînes de format de base
- 29 : localisation
- 30 : commentaires multilignes imbriqués
- 31 : un formulaire spécial pour l’évaluation récursive
- 37 : args-fold : un processeur d’arguments de programme
- 39 : objets paramètres
- 41 : flux
- 42 : compréhensions avides
- 43 : bibliothèque de vecteurs
- 45 : primitives pour exprimer des algorithmes paresseux itératifs
- 60 : entiers sous forme de bits
- 61 : une clause cond plus générale
- 66 : vecteurs d’octets
- 67 : comparer les procédures
Implémentations
Le design élégant et minimaliste a fait de Scheme une cible populaire pour les concepteurs de langages, les amateurs et les éducateurs, et en raison de sa petite taille, celle d’un interprète typique , c’est également un choix populaire pour les systèmes embarqués et les scripts . Cela a abouti à des dizaines d’implémentations, [35] dont la plupart diffèrent les unes des autres à tel point que le portage de programmes d’une implémentation à une autre est assez difficile, et la petite taille du langage standard signifie que l’écriture d’un programme utile d’une grande complexité en standard, le schéma portable est presque impossible. [7] La norme R6RS spécifie un langage beaucoup plus large, dans une tentative d’élargir son attrait pour les programmeurs.
Presque toutes les implémentations fournissent une boucle de lecture-évaluation-impression de style Lisp traditionnel pour le développement et le débogage. Beaucoup compilent également les programmes Scheme en binaire exécutable. La prise en charge de l’intégration du code Scheme dans des programmes écrits dans d’autres langages est également courante, car la simplicité relative des implémentations Scheme en fait un choix populaire pour ajouter des capacités de script à des systèmes plus grands développés dans des langages tels que C . Les interpréteurs Gambit , Chicken et Bigloo Scheme compilent Scheme en C, ce qui rend l’intégration particulièrement facile. De plus, le compilateur de Bigloo peut être configuré pour générer du bytecode JVM , et il dispose également d’un générateur de bytecode expérimental pour .NET .
Certaines implémentations prennent en charge des fonctionnalités supplémentaires. Par exemple, Kawa et JScheme fournissent une intégration avec les classes Java, et les compilateurs Scheme vers C facilitent souvent l’utilisation de bibliothèques externes écrites en C, jusqu’à permettre l’intégration du code C réel dans la source Scheme. Un autre exemple est Pvts , qui propose un ensemble d’outils visuels pour soutenir l’apprentissage de Scheme.
Usage
Scheme est largement utilisé par un certain nombre [36] d’écoles; en particulier, un certain nombre de cours d’introduction à L’informatique utilisent Scheme en conjonction avec le manuel Structure et interprétation des programmes informatiques (SICP). [37] Au cours des 12 dernières années, PLT a dirigé le projet ProgramByDesign (anciennement TeachScheme!), Qui a exposé près de 600 enseignants du secondaire et des milliers d’élèves du secondaire à la programmation Scheme rudimentaire. L’ancienne classe de programmation d’introduction 6.001 du MIT était enseignée dans Scheme, [ 38] Bien que 6.001 ait été remplacé par des cours plus modernes, le SICP continue d’être enseigné au MIT. [39]De même, la classe d’introduction à l’UC Berkeley , CS 61A, était jusqu’en 2011 entièrement enseignée en Scheme, à l’exception de détournements mineurs vers Logo pour démontrer une portée dynamique. Aujourd’hui, comme le MIT, Berkeley a remplacé le programme par une version plus moderne qui est principalement enseignée en Python 3 , mais le programme actuel est toujours basé sur l’ancien programme et certaines parties de la classe sont toujours enseignées en Scheme. [40]
Le manuel How to Design Programs de Matthias Felleisen, actuellement à la Northeastern University, est utilisé par certains instituts d’enseignement supérieur pour leurs cours d’introduction à L’informatique. La Northeastern University et le Worcester Polytechnic Institute utilisent Scheme exclusivement pour leurs cours d’introduction Fundamentals of Computer Science (CS2500) et Introduction to Program Design (CS1101), respectivement. [41] [42] Rose-Hulman utilise Scheme dans son cours plus avancé sur les concepts de langage de programmation. [43] Le cours de base de l’Université Brandeis , Structure et interprétations des programmes informatiques (COSI121b), est également enseigné exclusivement dans Scheme par un informaticien théoriqueHarry Merson . [44] La classe d’introduction de l’Université d’Indiana , C211, est enseignée entièrement dans Scheme. Une version à votre rythme du cours, CS 61AS, continue d’utiliser Scheme. [45] Les cours d’introduction à L’informatique à Yale et Grinnell College sont également enseignés dans Scheme. [46] Paradigmes de conception de programmation, [47] un cours obligatoire pour les étudiants diplômés en informatique de la Northeastern University, utilise également largement Scheme. L’ancien cours d’introduction à L’informatique de l’Université du Minnesota – Twin Cities, CSCI 1901, utilisait également Scheme comme langage principal, suivi d’un cours qui initiait les étudiants au langage de programmation Java ; [48] cependant, à l’instar du MIT, le département a remplacé 1901 par le CSCI 1133 basé sur Python, [49] tandis que la programmation fonctionnelle est couverte en détail dans le cours du troisième semestre CSCI 2041. [50] Dans l’industrie du logiciel, Tata Consultancy Services , la plus grande société de conseil en logiciels d’Asie, utilise Scheme dans son programme de formation d’un mois pour les nouveaux diplômés universitaires. [ citation nécessaire ]
Le schéma est/était également utilisé pour les éléments suivants :
- Le document DSSSL ( Document Style Semantics and Specification Language ), qui fournit une méthode de spécification des feuilles de style SGML , utilise un sous-ensemble Scheme. [51]
- Le célèbre éditeur graphique raster open source GIMP utilise TinyScheme comme langage de script . [52]
- Guile a été adopté par le projet GNU comme langage de script officiel, et cette implémentation de Scheme est intégrée dans des applications telles que GNU LilyPond et GnuCash en tant que langage de script pour les extensions. De même, Guile était le langage de script pour l’ environnement de bureau GNOME , [53] et GNOME a toujours un projet qui fournit des liaisons Guile à sa pile de bibliothèques. [54] Il existe un projet d’incorporation de Guile dans GNU Emacs , le programme phare de GNU, remplaçant l’ interpréteur Emacs Lisp actuel. [ citation nécessaire ]
- Elk Scheme est utilisé par Synopsys comme langage de script pour ses outils technologiques de CAO (TCAD) . [55]
- Shiro Kawai, programmeur senior sur le film Final Fantasy : The Spirits Within , a utilisé Scheme comme langage de script pour gérer le moteur de rendu en temps réel. [56]
- Google App Inventor pour Android utilise Scheme, où Kawa est utilisé pour compiler le code Scheme en byte-codes pour la Machine virtuelle Java exécutée sur les appareils Android. [57]
Voir également
- Portail de programmation informatique
- Essentials of Programming Languages , manuel utilisant Scheme comme base
Références
- ^ “Le langage de programmation de schéma” . MIT .
- ^ Common LISP: The Language, 2e éd., Guy L. Steele Jr. Digital Press; 1981. ISBN 978-1-55558-041-4 . “Common Lisp est un nouveau dialecte de Lisp, un successeur de MacLisp, fortement influencé par ZetaLisp et dans une certaine mesure par Scheme et InterLisp.”
- ^ un b 1178-1990 (Reaff 2008) la Norme IEEE pour le Langage de Programmation de Schéma. Numéro de pièce IEEE STDPD14209, réaffirmé à l’unanimité lors d’une réunion du comité d’examen des normes du conseil des normes IEEE-SA (RevCom), 26 mars 2008 (point 6.3 sur le procès-verbal), procès-verbal de réaffirmation consulté en octobre 2009. REMARQUE : ce document est uniquement disponible à l’achat de l’IEEE et n’est pas disponible en ligne au moment de la rédaction (2009).
- ^ un bcd e f g h i j k l m n o p q Richard Kelsey ; Guillaume Clinger; Jonathan Rees; et coll. (Août 1998). “Rapport révisé 5 sur le schéma de langage algorithmique” . Calcul d’ordre supérieur et symbolique . 11 (1): 7–105. doi : 10.1023/A:1010051815785 . S2CID 14069423 . Récupéré le 09/08/2012 .
- ^ Shinn, Alex; Cowan, John; Gleckler, Arthur (juillet 2013). “Rapport révisé 7 sur le schéma de langage algorithmique (R7RS)” . Récupéré le 08/11/2020 .
- ^ un b “R7RS final disponible” (PDF) . 2013-07-06.
- ^ un bc Will Clinger , Marc Feeley, Chris Hanson, Jonathan Rees et Olin Shivers (2009-08-20). “Énoncé de position (ébauche) ” . Comité de pilotage du régime . Récupéré le 09/08/2012 . {{cite web}}: CS1 maint: multiple names: authors list (link)
- ^ un bcd Sussman , Gerald Jay; Steele, Guy L. (1er décembre 1998). “Le premier rapport sur le schéma revisité”. Calcul d’ordre supérieur et symbolique . 11 (4): 399–404. doi : 10.1023/A:1010079421970 . S2CID 7704398 .
- ^ un bcd Sperber , Michael ; Dybvig, R. Kent; Flatt, Matthieu ; Van Straaten, Anton; et coll. (Août 2007). “Rapport révisé 6 sur le schéma de langage algorithmique (R6RS)” . Comité de pilotage du régime . Récupéré le 13/09/2011 .
- ^ “Implémentations R6RS” . r6rs.org . Récupéré le 24/11/2017 .
- ^ Abdulaziz Ghuloum (2007-10-27). “Bibliothèques R6RS et système de cas de syntaxe (psyntax)” . Schéma d’Ikarus . Récupéré le 20/10/2009 .
- ^ Gardez, Andrew W.; Dybvig, R. Kent (novembre 2014). “Une représentation d’exécution des types d’enregistrement de schéma”. Journal de programmation fonctionnelle . 24 (6): 675–716. doi : 10.1017/S0956796814000203 . S2CID 40001845 .
- ^ “Rapport révisé ^ 6 sur le schéma de langage algorithmique, annexe E: changements de langage” . Comité de pilotage du régime. 2007-09-26 . Récupéré le 20/10/2009 .
- ^ “Électorat R6RS” . Comité de pilotage du régime. 2007 . Récupéré le 09/08/2012 .
- ^ Marc Feeley (compilation) (2007-10-26). “Intentions des implémenteurs concernant R6RS” . Scheme Steering Committee, liste de diffusion r6rs-discuss . Récupéré le 09/08/2012 .
- ^ “R7RS 9e brouillon disponible” (PDF) . 2013-04-15.
- ^ Will Clinger (2013-05-10). “prolongation de la période de vote” . Scheme Language Steering Committee, liste de diffusion des rapports sur les schémas. Archivé de l’original le 2013-07-21 . Récupéré le 07/07/2013 .
- ^ L’ implémentation du schéma 48 est ainsi nommée parce que l’interprète a été écrit par Richard Kelsey et Jonathan Rees en 48 heures (du 6 au 7 août 1986. Voir Richard Kelsey ; Jonathan Rees ; Mike Sperber (2008-01-10) . Incomplete Scheme 48 Reference Manual for release 1.8″ . Jonathan Rees, s48.org . Récupéré le 09/08/2012 .
- ^ un b Gerald Jay Sussman et Guy Lewis Steele Jr. (décembre 1975). “Schéma: un interprète pour le calcul Lambda étendu” (PDF) . Mémos IA . Laboratoire d’IA du MIT . BUT-349. hdl : 1721.1/5794 . Récupéré le 23 décembre 2021 .
- ^ Joel Moses (juin 1970), La fonction de la fonction dans LISP, ou pourquoi le problème FUNARG devrait être appelé le problème de l’environnement , hdl : 1721.1/5854 , AI Memo 199, Une métaphore utile pour la différence entre FUNCTION et QUOTE en LISP est de considérer QUOTE comme une couverture poreuse ou ouverte de la fonction puisque les variables libres s’échappent dans l’environnement actuel. FUNCTION agit comme un revêtement fermé ou non poreux (d’où le terme “fermeture” utilisé par Landin). Ainsi, nous parlons d’expressions Lambda “ouvertes” (les fonctions dans LISP sont généralement des expressions Lambda) et d’expressions Lambda “fermées”. […] Mon intérêt pour le problème de l’environnement a commencé lorsque Landin, qui avait une profonde compréhension du problème, a visité le MIT en 1966-67. J’ai ensuite réalisé la correspondance entre les listes FUNARG qui sont les résultats de l’évaluation des expressions Lambda “fermées” en LISP et les Lambda Closures d’ ISWIM .
- ^ van Tonder, André (1er janvier 2004). “Un calcul Lambda pour le calcul quantique”. Journal SIAM sur L’informatique . 33 (5): 1109–1135. arXiv : quant-ph/0307150 . doi : 10.1137/S0097539703432165 . S2CID 613571 .
- ^ Niehren, J.; Schwinghammer, J.; Smolka, G. (novembre 2006). “Un calcul lambda simultané avec des contrats à terme” (PDF) . Informatique théorique . 364 (3): 338–356. doi : 10.1016/j.tcs.2006.08.016 .
- ^ Gerald Jay Sussman et Guy Lewis Steele Jr. (mars 1976). “Lambda : L’Impératif Ultime” . Mémos IA . Laboratoire d’IA du MIT . BUT-353. Archivé de l’original (postscript ou PDF) le 2016-05-10 . Récupéré le 09/08/2012 .
- ^ Gabriel, Richard P. ; Pitman, Kent (1988). “Problèmes techniques de séparation dans les cellules de fonction et les cellules de valeur” . Lisp et calcul symbolique . Vol. 1, non. 1 (publié en juin 1988). p. 81–101. doi : 10.1007/BF01806178 . Récupéré le 09/08/2012 .
- ^ un b Philip L. Bewig (2008-01-24). « SRFI 41 : Flux » . Les éditeurs SRFI, schemers.org . Récupéré le 09/08/2012 .
- ^ William Clinger et Jonathan Rees, éd. (1991). “Rapport révisé 4 sur le schéma de langage algorithmique” . Pointeurs Lisp ACM . 4 (3) : 1–55 . Récupéré le 09/08/2012 .
- ^ Flatt, Matthieu (2016). « Liaison en tant qu’ensembles de portées ». Actes du 43e symposium annuel ACM SIGPLAN-SIGACT sur les principes des langages de programmation . pages 705–717. doi : 10.1145/2837614.2837620 . ISBN 978-1-4503-3549-2. S2CID 15401805 .
- ^ Jonathan Rees, The Scheme of Things The June 1992 Meeting Archivé le 16/07/2011 à la Wayback Machine (postscript), dans Lisp Pointers, V(4), octobre-décembre 1992. Récupéré le 09/08/2012
- ^ Taylor Campbell (2005-07-21). « SRFI 62 : commentaires d’expression S » . Les éditeurs SRFI, schemers.org . Récupéré le 09/08/2012 .
- ^ William D Clinger (1999-07-01). “SRFI 6 : Ports de chaîne de base” . Les éditeurs SRFI, schemers.org . Récupéré le 09/08/2012 .
- ^ Scott G. Miller (2002-06-25). “SRFI 28 : Chaînes de format de base” . Les éditeurs SRFI, schemers.org . Récupéré le 09/08/2012 .
- ^ JW Backus; FL Bauer; J. Green ; C. Katz; J. McCarthy P. Naur; et coll. (janvier-avril 1960). “Rapport révisé sur le langage algorithmique Algol 60” . Numerische Mathematik, Communications of the ACM et Journal of the British Computer Society . Récupéré le 09/08/2012 .
- ^ Jonathan Rees; William Clinger, éd. (Décembre 1986). “Rapport révisé (3) sur le schéma de langage algorithmique (dédié à la mémoire d’ALGOL 60)” . Avis ACM SIGPLAN . 21 (12): 37–79. CiteSeerX 10.1.1.29.3015 . doi : 10.1145/15042.15043 . hdl : 1721.1/6424 . S2CID 43884422 . Récupéré le 09/08/2012 .
- ^ “Systèmes de schéma prenant en charge les SRFI” . Les éditeurs SRFI, schemers.org. 2009-08-30 . Récupéré le 09/08/2012 .
- ^ 75 implémentations connues de Scheme sont répertoriées par “scheme-faq-standards” . Wiki du programme communautaire. 2009-06-25 . Récupéré le 20/10/2009 .
- ^ Ed Martin (2009-07-20). “Liste des écoles utilisant le programme” . Schemers Inc . Récupéré le 20/10/2009 .
- ^ “Liste des écoles utilisant le SICP” . Presse du MIT. 1999-01-26 . Récupéré le 20/10/2009 .
- ^ Eric Grimson (printemps 2005). “6.001 Structure et interprétation des programmes informatiques” . Didacticiel ouvert du MIT . Récupéré le 20/10/2009 .
- ^ Alex Vandiver; Nelson Elhage; et coll. (janvier 2009). “6.184 – Les zombies boivent de la caféine 6.001” . MIT CSAIL . Récupéré le 20/10/2009 .
- ^ John DeNero (automne 2019). “Informatique 61A, Berkeley” . Département de génie électrique et d’informatique, Berkeley . Récupéré le 17/12/2019 .
- ^ CS 2500: Principes fondamentaux de L’informatique I , Northeastern University
- ^ CS 1101: Introduction à la conception de programmes (A05): logiciel de cours , Worcester Polytechnic Institute
- ^ “CSSE 304 : Concepts de langage de programmation” . Institut de technologie Rose-Hulman .
- ^ “Syllabus du printemps 2021 CS121b” (PDF) . Université Brandeis .
- ^ https://berkeley-cs61as.github.io
- ^ Dana Angluin (automne 2009). “Introduction à L’informatique (CPSC 201)” . Le zoo, département d’informatique de l’université de Yale . Récupéré le 20/10/2009 .
- ^ “Lectures de cours sur les paradigmes de conception de programmation CSG107” . Collège universitaire d’informatique et de sciences de l’information du nord-est. Automne 2009 . Récupéré le 09/08/2012 .
- ^ Structure de la programmation informatique I Archivé le 19/06/2010 à la Wayback Machine , Département d’informatique, Université du Minnesota, printemps 2010 (consulté le 30/01/2010).
- ^ Descriptions des cours de classe obligatoires CSci et autres informations archivées le 25/10/2019 à la Wayback Machine , département d’informatique, Université du Minnesota (consulté le 25/10/2019)
- ^ CSCI 2041—New Course CSE Curriculum Committee, University of Minnesota (consulté le 2019-10-25)
- ^ Robin Cover (2002-02-25). “DSSSL – Sémantique du style de document et langage de spécification. ISO/IEC 10179:1996” . Pages de garde . Récupéré le 09/08/2012 .
- ^ “ Le principal langage de script pour le GIMP qui lui a été attaché aujourd’hui est Scheme. ” D’après Dov Grobgeld (2002). “Tutoriel sur le schéma de base de GIMP” . L’équipe Gimp . Récupéré le 09/08/2012 .
- ^ Todd Graham Lewis; David Zoll; Julien Missig (2002). “FAQ GNOME à partir des archives Internet” . L’équipe Gnome, gnome.org. Archivé de l’original le 2000-05-22 . Récupéré le 09/08/2012 .
- ^ “ruse-gnome” . Fondation du logiciel libre . Récupéré le 09/08/2012 .
- ^ Laurence Brévard (2006-11-09). “Mise à jour du programme Synopsys MAP-in SM : Forum des développeurs d’interopérabilité EDA” (PDF) . Synopsis Inc . Récupéré le 09/08/2012 .
- ^ Kawai, Shiro (octobre 2002). “Coller les choses ensemble – Schéma dans la production de contenu CG en temps réel” . Actes de la première conférence internationale Lisp, San Francisco : 342–348 . Récupéré le 09/08/2012 .
- ^ Bill Magnuson; Hal Abelson et Mark Friedman (2009-08-11). “Sous le capot d’App Inventor pour Android” . Google Inc, blog officiel de Google Research . Récupéré le 09/08/2012 .
Lectures complémentaires
- Une introduction au schéma et à sa mise en œuvre en œuvre ( un miroir )
- Christopher T. Haynes (1999-06-22).”L’expérience de normalisation du langage de programmation Scheme” .
- Guy L. Steele Jr. , Richard P. Gabriel . “L’évolution de Lisp” (PDF) .
- Gerald Jay Sussman et Guy Lewis Steele Jr. (décembre 1975). Scheme : Un interpréteur pour le calcul lambda étendu . Vol. AI Memo 349. Laboratoire d’intelligence artificielle du MIT . CiteSeerX 10.1.1.128.80 – via Wikisource .
Liens externes
- Régime à Curlie
- Programmation de schémas sur Wikibooks
- Écrivez-vous un plan en 48 heures sur Wikibooks
- Médias liés à Scheme (langage de programmation) sur Wikimedia Commons
- Bookmarklet qui ajoute Interactive Scheme REPL à n’importe quel site Web