2012-07-04 2 views
1

J'ai découvert que les formes spéciales ne peuvent être passés comme arguments ou dans des variables, aussi bien dans Clojure:Quelles seraient les conséquences d'autoriser le traitement de formulaires spéciaux en tant que valeurs normales?

user=> (defn my-func 
     [op] 
     (op 1 2 3)) 
#'user/my-func 
user=> (my-func +) 
6 
user=> (my-func if) 
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5) 
user=> (def my-if if) 
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9) 

et Racket/Système:

> (define (my-func op) 
    (op 1 2 3)) 
> (my-func +) 
6 
> (my-func if) 
    if: bad syntax in: if 
> (define my-if if) 
    *if: bad syntax in: if 

C'est cool, je suis bien avec Cela, je sais que je peux juste écrire une fonction pour envelopper un formulaire spécial, puis passer cette fonction. Mais je voudrais savoir pourquoi Lisps a cette restriction, et quelles conséquences négatives cela aurait permis. Sont-ils des dialectes majeurs qui permettent cela?

Répondre

4

Cela complique l'évaluation et la compilation.

Si vous avez une forme (a b c), alors vous devez résoudre à l'exécution de la valeur a et appliquer ensuite en quelque sorte aux formes b et c.

Le modèle plus simple d'un nombre limité de formulaires spéciaux et d'une évaluation par ailleurs stricte a disparu.

Voir aussi: FEXPR

+0

Merci pour le nom FEXPR! –

4

Les formes spéciales ne sont pas des fonctions: les fonctions prennent des valeurs comme arguments, tandis que les formes spéciales prennent des formes. Par exemple, regardez votre exemple de if:

(if 1 2 3) 

D'accord, c'est facile, puisque 2 et 3 sont déjà des valeurs. Mais qu'en est-il de ça?

(define (modadd a b n) 
    (if (zero? n) #f (modulo (+ a b) n))) 

Dans ce cas, l'if reçoit est en fait la #f et (modulo (+ a b) n) comme des formes, et non comme valeurs. Et c'est important! (modulo x n) échouera si n est 0: c'est pourquoi il est laissé non évalué jusqu'à ce que nous savons que n n'est pas 0.

Le problème d'être en mesure de transmettre des formulaires spéciaux comme des objets de première classe est que les fonctions d'ordre supérieur ne peuvent pas appeler les objets utilisant une sémantique prévisible: est-ce un objet de fonction, de sorte que vous passez des valeurs, ou est-ce une forme spéciale, de sorte que vous passez dans des formes? Cela devient un énorme désordre.

Oui, vous pouvez écrire une fonction wrapper, comme mon modadd, qui encapsule if. Cependant, il est impossible de simplement réimplémenter if en tant que fonction, tout en préservant le comportement d'évaluation unique des branches.

Questions connexes