Références : sur le langage Symmetric Lisp [GJL 87a] [GJL 87c].
De même que dans Scheme les fonctions sont des objets de première classe, en Symmetric Lisp les environnements sont des objets de première classe.
Note : les objets de première classe
La notion d'objet de première classe est une notion très informatique : elle caractérise les objets manipulés par un langage de programmation qui peuvent être : affectés, passés en paramètre d'une fonction, retournés par une fonction, ... Par exemple en Pascal, les entiers sont de première classe, mais non les pointeurs (ils ne peuvent pas être retournés par une fonction).
Au sens strict du terme, dans tous les langages Lisp une fonction est un objet de première classe – grâce entre autre à la fonction eval. Cependant Scheme offre en plus un modèle d'interprétation cohérent : un appel de fonction réalise toujours le même calcul quel que soit le point de programme d'où l'on appelle cette fonction. Pour ce faire, Scheme définit pour chaque fonction un unique contexte d'évaluation : ce contexte correspond très précisément au contexte lexical de définition de la fonction.
On n'a donc plus ici les deux types d'interprétation : Ienv (environnement) et Irep (représentation), puisqu'une valeur peut servir à modifier l'environnement d'évaluation. On ne distingue donc plus pour une valeur les champs env et rep, et on appelle dans la suite une valeur indifféremment env ou rep selon le sens intuitif qu'on lui attache.
1. Termes
2. Manipulation d'environnement
3. Application
Définitions
On a deux sortes de définitions :
définition de symbole : def
I[env-0 (def x rep)]
= ( x :→ I[env-0 rep] )
définition d'environnement : alpha
I[env-0 (alpha env)]
env* = I[env*:env-0 env]
= env*
Ici on a effectivement une évaluation parallèle de l'environnement (aux difficultés algorithmiques près).
Symbole
Un symbole retourne sa valeur :
I[env-0 x]
= env-0(x)
λ-expression
L'évaluation d'une λ-expression est retardée :
I[env-0 (lambda(u) env)]
= Iλ[env-0 λu.env]
qui est représentée formellement en Lisp identiquement à elle-même, mais a de fait une sémantique plus riche après son évaluation.
Utilisation contextuelle
La manipulation explicite des environnements permet de définir une utilisation contextuelle :
I[env-0 (with e x)]
I[env-0 e] = e
= if alpha(e) then I[e:env-0 x] else I[env-0 x]
où alpha(e) teste si la valeur e est un environnement (alpha).
Pour réaliser cette fonction, il faut donc légèrement modifier les évaluations des définitions, de manière à typer les valeurs. Le seul véritable changement se situe au niveau de l'évaluation d'un symbole :
I[env x]
qu'on ne peut plus considérer comme l'appel fonctionnel (au sens mathématique du terme) :
env(x)
et qu'on remplace donc par l'appel d'une fonction (Lisp par exempel) :
(recherche x env)
Par exemple :
(x:→x) est remplacée par : (list 'def x x)env = (x1:→x1)···(xn:→xn) est remplacé par : (list 'alpha x)env on remplace maintenant les définitions par leur équivalent en Lisp).
La fonction de recherche pourra être :
recherche (x env)
(cond
((nul env) ())
((eq (caar env) 'def)
(if (eq (cadar env) x)
(caddar env)
(recherche x (cdr env))))
((eq (caar env) 'alpha)
(or (any '(lambda (trm)
(recherche x trm))
(cdar env))
(recherche x (cdr env)))))