Je m'excuse par avance de manquer de vocabulaire ici. En passant par Structure et interprétation des programmes informatiques , il y a une référence précoce aux 'combinaisons dont les opérateurs sont eux-mêmes des expressions composées', par exemple:
(define (a-plus-abs-b a b) ((if (> b 0) + -) a b))
où la combinaison (si ( > b 0) + -)
est évalué comme un +
ou -
, qui est ensuite évalué comme par exemple (+ ab)
si b est supérieur à zéro.
Ma question est: est-ce différent d'une fonction variable (par exemple en PHP ), et comment? De plus, les fonctions variables et cette fonctionnalité diffèrent de l'utilisation de références d'objets de style Javascript ?
3 Réponses :
La notion importante ici, du point de vue Lisp, est de savoir si un langage est un «lisp-1» ou un «lisp-2». La différence entre ces deux est: dans une expression qui ressemble à une application de fonction, comment la chose qui représentera la fonction à appliquer est-elle évaluée?
Donc, en Lisps, quelque chose qui ressemble à une application de fonction ressemble à une liste:
(f a b ...)
En considérant une telle chose, le système doit faire trois choses:
(if ...)
ne l'est pas, ni un formulaire qui est une macro); (Note: j'ai supposé ce que l'on appelle ici l'évaluation de l ' ordre applicatif : un langage normal fait les choses différemment.)
Et la question est de savoir comment (2) se produit.
((if add + -) 1 2)
est parfaitement bien, tout comme (let ((op ...)) (op ...))
par exemple . (let ((op (lambda ...))) (op ...))
, mais quelque chose comme ça fonctionne : (let ((car ...)) (car car))
. De façon célèbre, Scheme est un lisp-1, Common Lisp est un lisp-2.
Alors la façon de répondre à votre question, je pense, est de réaliser que cette notion peut être parfaitement appliqué à d’autres langues.
Notez que dans ces langages, la façon dont vous savez que quelque chose est une application de fonction est complètement différente de ce qu'elle est en Lisp, mais la question importante est, une fois que vous le savez, comment évaluer la position de la fonction ?
n'aurions-nous pas besoin de funcall
que laissez
-defined voiture
?
@WillNess: Nous le ferions si nous voulions l'appeler, mais je veux appeler la fonction car
ordinaire. Évidemment, ce serait un code horrible en pratique: j'avoue des choses comme (destructuring-bind (first. Rest) ... ...)
mais j'essaierais alors d'éviter de dire ( first first)
dans le corps, car c'est simplement déroutant gratuitement.
ah, donc vous vouliez dire que la voiture
définie par let est une donnée, pas une fonction ...
Dans Scheme (qui est utilisé par SICP) on peut utiliser des variables en position de fonction.
Nous essayons d'abord d'utiliser le symbole +
comme fonction:
Essayer d'utiliser un symbole comme fonction
> (define foo +) > (foo 1 2) 3
Malheureusement, cela ne fonctionne pas: foo
correspond au symbole +
et ce n'est pas en soi une fonction
Utilisation d'un objet fonction
Mais cela fonctionne:
> (define foo '+) > foo + > (foo 1 2) Exception: attempt to apply non-procedure +
Toutes les fonctions de JavaScript sont des variables et autorisent les expressions en position d'opérateur:
function add($a, $b) { return $a+$b; } function sub($a, $b) { return $a-$b; } function plusAbs ($a, $b) { return call_user_func($b < 0 ? 'sub' : 'add', $a, $b); } plusAbs(3, -3); // => 6
Tout comme Scheme, il n'évalue pas à plus code> ou
moins
mais plutôt ce que plus
et moins
évaluent. Par exemple. le [fonction moins]
et pas la variable.
Les fonctions en PHP ne peuvent pas être effectuées de cette façon par leur nom, mais des variables liées à des fonctions:
function plusAbs ($a, $b) { $add = function($a, $b) { return $a+$b; }; $sub = function($a, $b) { return $a-$b; }; return ($b < 0 ? $sub : $add)($a, $b); } plusAbs(3, -3); // => 6
Le plus proche que vous obtenez avec les fonctions nommées:
function plus (a, b) { return a + b; } plus; // => [Function: plus] function minus (a, b) { return a - b } minus; // => [Function: minus] function plusAbs (a, b) { return (b > 0 ? plus : minus)(a, b); } plusAbs(3, -3); // => 6 plusAbs(3, 3); // => 6 var plus = 4; plus; // => 4 (no longer a function) plusAbs(3, 3); // ERROR! 4 is not a function
Notez que cela n'a plus d'expression en position d'opérateur.