mondiale define
Tout d'abord, les programmes de haut niveau sont gérés par une autre partie de la mise en œuvre que dans une fonction et la définition d'une variable déjà définie n'est pas autorisé.
(define a 10)
(define a 20) ; ERROR: duplicate definition for identifier
Il peut arriver que cela fonctionne dans un REPL car il est fréquent de redéfinir des choses, mais lors de l'exécution des programmes ce qui est absolument interdit. Dans R5RS et avant que ce qui s'est passé est sous-spécifié et ne s'est pas inquiété puisque être la spécification en violant il n'est plus un programme de Scheme et les exécutants sont libres de faire ce qu'ils veulent. Le résultat est bien sûr que beaucoup de choses sous-spécifiées obtiennent un comportement spécifique à l'implémentation qui n'est pas portable ou stable.
Solution:
set!
liaisons de mute:
(define a 10)
(set! a 20)
define
dans un lambda (fonction, laissez, ...)
A define
dans un lambda est quelque chose de complètement différent, géré par des parties complètement différentes de la mise en œuvre. Il est géré par la macro/forme spéciale lambda
afin qu'il soit réécrite à un letrec*
A letrec*
ou letrec
est utilisé pour la fabrication des fonctions récursives de manière à les noms doivent être disponibles au moment où les expressions sont évaluées. À cause de cela quand vous define
n
il a déjà ombré le n
que vous avez passé en argument. De plus, les implémenteurs de R6RS sont tenus de signaler une erreur lorsqu'une liaison qui n'est pas encore initialisée est évaluée et c'est probablement ce qui se passe.Avant R6RS étaient libres implémenteurs de faire ce qu'ils voulaient:
(define (func n)
(define n (+ n 1)) ; illegal since n hasn't got a value yet!
n)
Cela devient en fait:
(define func
(lambda (n)
(let ((n 'undefined-blow-up-if-evaluated))
(let ((tmpn (+ n 1)))
(set! n tmpn))
n)))
Maintenant, un compilateur peut voir qu'il viole les spécifications au moment de la compilation, mais de nombreuses implémentations ne sait pas avant qu'il ne s'exécute.
(func 5) ; ==> 42
Parfaitement fin résultat dans R5RS si les exécutants ont un bon goût dans les livres. La différence dans la version vous avez dit des œuvres est que cela ne viole pas la règle d'évaluation n
avant que le corps:
(define (func n)
(define n 5)
n)
devient:
(define func
(lambda (n)
(let ((n 'undefined-blow-up-if-evaluated))
(let ((tmpn 5)) ; n is never evaluated here!
(set! n tmpn))
n)))
Solutions
Utilisez un non nom en conflit
(define (func n)
(define new-n (+ n 1))
new-n)
Utilisez let
. Il n'a pas sa propre liaison lorsque l'expression est évaluée:
(define (func n)
(let ((n (+ n 1)))
n))