1
votes

Les «combinaisons dont les opérateurs sont eux-mêmes des expressions composées» sont-elles synonymes de fonctions variables?

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 ?


0 commentaires

3 Réponses :


3
votes

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:

  1. établissez qu'il est une application de fonction (ainsi, par exemple, (if ...) ne l'est pas, ni un formulaire qui est une macro);
  2. si c'est le cas, évaluez la fonction et ses arguments;
  3. appeler la fonction en lui transmettant le résultat de l'évaluation de ses arguments.

(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.

  • Un lisp-1 évalue la position de la fonction (la première position) sous une telle forme exactement de la même manière que toutes les autres positions. Ainsi, la position de la fonction peut contenir une expression complètement arbitraire. Donc ((if add + -) 1 2) est parfaitement bien, tout comme (let ((op ...)) (op ...)) par exemple .
  • Un lisp-2 utilise une règle spéciale pour la position de la fonction, et en particulier pour un lisp-2 la «valeur de fonction» d'un symbole vit dans un espace de noms différent de la valeur ordinaire. Cela signifie que ce qui y est autorisé n'est pas une expression générale, mais ce que les règles permettent. Ainsi, par exemple, dans un lisp-2, quelque chose comme ça ne fonctionne pas: (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.

  • JavaScript est un lisp-1, donc la position de fonction des éléments qui ressemblent à des applications de fonction est juste évaluée parfaitement normalement.
  • Python est un lisp-1.
  • Je ne sais pas ce qu'est PHP.

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 ?


3 commentaires

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 ...



2
votes

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 +


0 commentaires

2
votes

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.


0 commentaires