Je le pense de cette façon:
<?php
$number1 = 5; // (Type 'Int')
$operator1 = +; // (Type non-existent 'Operator')
$number2 = 5; // (Type 'Int')
$operator2 = *; // (Type non-existent 'Operator')
$number3 = 8; // (Type 'Int')
$test = $number1 $operator1 $number2 $operator2 $number3; //5 + 5 * 8.
var_dump($test);
?>
Mais aussi de cette façon:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
Cela ne semble pas être le cas pour toutes les langues - existe-t-il une bonne raison pour que ce ne soit pas le cas?
programming-languages
variables
operators
kgongonowdoe
la source
la source
(+)
estNum a => a -> a -> a
IIRC. vous pouvez également définir des fonctions afin qu'elles puissent être écrites en caractères infixés (a + b
au lieu de(+) a b
)Réponses:
Les opérateurs ne sont que des fonctions sous des noms amusants, avec une syntaxe spéciale.
Dans de nombreuses langues, aussi variées que C ++ et Python, vous pouvez redéfinir les opérateurs en redéfinissant les méthodes spéciales de votre classe. Ensuite, les opérateurs standard (par exemple
+
) fonctionnent selon la logique que vous indiquez (par exemple, concaténer des chaînes ou ajouter des matrices, etc.).Comme ces fonctions définissant des opérateurs ne sont que des méthodes, vous pouvez les transmettre comme une fonction:
Autres langues vous permet de définir directement de nouveaux opérateurs en tant que fonctions et de les utiliser sous forme infixe.
Malheureusement, je ne suis pas sûr si PHP supporte quelque chose comme ça, et si le supporter serait une bonne chose. Utilisez une fonction simple, c'est plus lisible que
$foo $operator $bar
.la source
$
opérateur qui supprime les parenthèses (en particulier les multiples imbriqués) - mais cela ne peut fonctionner qu'avec -variadic fonctions, excluant ainsi par exemple Python et Java. La composition de fonction unaire OTOH peut très bien être faite .operator
module standard qui vous permet d’écrireaction = operator.add
et qu’il fonctionne pour tous les types qui définissent+
(pas seulementint
).+
, la classe de types Num vous permet de la mettre en œuvre+
pour tout nouveau type de données que vous créez, mais de la même manière que vous faites autre chose, par exemple fmap pour un foncteur. Il est tellement naturel que Haskell permette aux opérateurs surchargés de travailler dur pour ne pas le permettre!$operator1 = +
et utiliser ensuite une expression, vous n'avez pas du tout besoin de surcharger l'opérateur !Il y a beaucoup de langues qui permettent une sorte de métaprogrammation . En particulier, je suis surpris de ne voir aucune réponse parler de la famille de langues Lisp .
De wikipedia:
Plus tard dans le texte:
Langues Lisp
Suit une introduction rapide à Lisp.
Une façon de voir le code consiste à suivre une suite d'instructions: faites ceci, puis faites-le, puis procédez comme suit ... Ceci est une liste! Une liste de choses à faire pour le programme. Et bien sûr, vous pouvez avoir des listes dans des listes pour représenter des boucles, etc.
Si nous représentons une liste contenant les éléments a, b, c, d comme celui - ci: (ABCD) nous obtenons quelque chose qui ressemble à un appel de fonction Lisp, où
a
est la fonction, etb
,c
,d
sont les arguments. Si fait le typique "Hello World!" programme pourrait être écrit comme suit:(println "Hello World!")
Bien sûr
b
,c
oud
pourrait être des listes qui donnent aussi quelque chose. Ce qui suit:(println "I can add :" (+ 1 3) )
serait alors imprimer "" Je peux ajouter: 4 ".Ainsi, un programme est une série de listes imbriquées et le premier élément est une fonction. La bonne nouvelle est que nous pouvons manipuler des listes! Nous pouvons donc manipuler les langages de programmation.
L'avantage Lisp
Il est non seulement beaucoup plus facile avec Lisps de créer de nouveaux opérateurs, il est également presque impossible d'écrire certains opérateurs dans d'autres langues car les arguments sont évalués lorsqu'ils sont transmis à la fonction.
Par exemple, dans un langage de type C, supposons que vous souhaitiez écrire
if
vous-même un opérateur, par exemple:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
Dans ce cas, les deux arguments seront évalués et imprimés, dans un ordre dépendant de l'ordre d'évaluation des arguments.
En Lisps, écrire un opérateur (on appelle ça une macro) et écrire une fonction est à peu près la même chose et utilisé de la même manière. La principale différence est que les paramètres d'une macro ne sont pas évalués avant d'être passés en tant qu'arguments à la macro. Ceci est essentiel pour pouvoir écrire certains opérateurs, comme
if
ci - dessus.Langues du monde réel
Montrer comment est exactement un peu hors de portée ici, mais je vous encourage à essayer de programmer dans un Lisp pour en savoir plus. Par exemple, vous pouvez regarder:
Oh, au fait, Lisp veut dire LISt Processing.
Concernant vos exemples
Je vais donner des exemples en utilisant Clojure ci-dessous:
Si vous pouvez écrire une
add
fonction dans Clojure(defn add [a b] ...your-implementation-here... )
, vous pouvez le nommer+
ainsi(defn + [a b] ...your-implementation-here... )
. C’est en fait ce qui est fait dans l’ implémentation réelle (le corps de la fonction est un peu plus impliqué mais la définition est essentiellement la même que celle que j’ai écrite ci-dessus).Qu'en est-il de la notation infixe? Eh bien Clojure utilise une
prefix
notation (ou polonaise), nous pourrions donc créer uneinfix-to-prefix
macro qui transformerait le code préfixé en code Clojure. Ce qui est en fait étonnamment facile (c’est en fait l’un des exercices de macro dans les koans du clojure)! On peut également le voir à l'état sauvage, par exemple voir Macro Incanter$=
.Voici la version la plus simple des koans expliqués:
Pour pousser plus loin le propos, quelques citations de Lisp :
la source
if
, mais vous devez envelopper les argumentsthen
etelse
avec des lambdas. PHP et JavaScript ontfunction()
, C ++ a lambdas, et il existe une extension Apple à C avec lambdas.La plupart des implémentations de langages ont une étape où un analyseur analyse votre code et construit un arbre à partir de celui-ci. Ainsi, par exemple, l'expression
5 + 5 * 8
serait analysée commegrâce à la connaissance du compilateur sur les précédents. Si vous introduisiez des variables à la place des opérateurs, il ne saurait connaître le bon ordre des opérations avant d'exécuter le code. Pour la plupart des implémentations, ce serait un problème sérieux, donc la plupart des langues ne le permettent pas.
Vous pouvez bien sûr concevoir un langage dans lequel l'analyseur syntaxique analyse simplement ce qui précède comme une séquence d'expressions et d'opérateurs, à trier et à évaluer au moment de l'exécution. Vraisemblablement, il n'y a tout simplement pas beaucoup d'applications pour cela.
De nombreux langages de script permettent l'évaluation d'expressions arbitraires (ou au moins d'expressions arithmétiques arbitraires comme dans le cas de
expr
) lors de l'exécution. Là, vous pouvez combiner vos chiffres et vos opérateurs en une seule expression et laisser le langage l’évaluer. En PHP (et beaucoup d'autres), cette fonction est appeléeeval
.Il existe également des langages permettant la génération de code au moment de la compilation. L’ expression mixin de D me vient à l’esprit, où je crois que vous pourriez écrire quelque chose comme
Ici
operator1
etoperator2
devraient être des constantes de chaîne qui sont connues au moment de la compilation, par exemple des paramètres de modèle.number1
,number2
etnumber3
ont été laissés comme variables d’exécution normales.D'autres réponses ont déjà abordé les différentes manières dont un opérateur et une fonction sont plus ou moins la même chose, en fonction de la langue. Mais il existe généralement une différence syntaxique entre un symbole d'opérateur infix intégré, tel que,
+
et un appelable, tel que nomméoperator1
. Je vais laisser les détails à ces autres réponses.la source
eval()
construction de langage " ... Techniquement, il fournit exactement le résultat souhaité dans la question.eval
ne répond pas à cet aspect, careval
les opérateurs ne sont que des chaînes. Par conséquent, j'ai commencé par expliquer pourquoi les variables de type opérateur posaient problème, avant de commencer à discuter des alternatives.Algol 68 avait exactement cette caractéristique. Votre exemple dans Algol 68 ressemblerait à ceci:
Votre deuxième exemple ressemblerait à ceci:
Vous remarquerez que les symboles d'opérateur sont des corps de méthode définis et affectés contenant l'opération souhaitée. Les opérateurs et leurs opérandes sont tous dactylographiés et des priorités peuvent être attribuées aux opérateurs afin que l'évaluation se déroule dans le bon ordre. Vous remarquerez peut-être également qu'il existe une légère différence de police de caractères entre le symbole d'opérateur et un symbole de variable.
En fait, bien que la langue soit écrite en utilisant la police de caractères, les machines du jour ne pouvaient pas gérer les polices (bande de papier et cartes perforées), et le strophage était utilisé. Le programme serait probablement entré comme:
Vous pouvez également jouer à des jeux intéressants avec le langage lorsque vous pouvez définir vos propres symboles pour les opérateurs, que j'ai exploités une fois, il y a de nombreuses années ... [2].
Références:
[1] Introduction informelle à Algol 68 par CHLindsey et SG van der Meulen, Hollande du Nord, 1971 .
[2] Algol 68 Phrases, outil d'aide à l'écriture de compilateurs dans Algol 68 , BC Tompsett, Conférence internationale sur les applications d'Algol 68, Université de East Anglia, Norwich, Royaume-Uni, 1976 ..
la source