Lo digo de esta manera:
<?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);
?>
Pero también de esta manera:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
No parece que ningún idioma tenga esto, ¿hay una buena razón por la que no lo tienen?
programming-languages
variables
operators
kgongonowdoe
fuente
fuente
(+)
esNum a => a -> a -> a
IIRC. también se puede definir funciones para que puedan ser escritas infija (a + b
en lugar de(+) a b
)Respuestas:
Los operadores son solo funciones con nombres divertidos, con alguna sintaxis especial.
En muchos lenguajes, tan variados como C ++ y Python, puede redefinir operadores anulando métodos especiales de su clase. Luego, los operadores estándar (p
+
. Ej. ) Funcionan de acuerdo con la lógica que proporciona (p. Ej., Concatenando cadenas o agregando matrices o lo que sea).Dado que tales funciones que definen el operador son solo métodos, puede pasarlas como lo haría con una función:
Otros lenguajes le permiten definir directamente nuevos operadores como funciones y usarlos en forma infija.
Desafortunadamente, no estoy seguro de si PHP admite algo así, y si lo admite sería algo bueno. Use una función simple, es más legible que
$foo $operator $bar
.fuente
$
operador que evita los paréntesis (especialmente los anidados múltiples), pero esto solo puede funcionar con -variables, excluyendo, por ejemplo, Python y Java. La composición de la función unitaria de OTOH se puede hacer muy bien .operator
módulo estándar que le permitirá escribiraction = operator.add
y que funcione para cualquier tipo que defina+
(no soloint
).+
trabaja en la clase de tipo Num para que pueda implementar+
cualquier tipo de datos nuevo que cree, pero de la misma manera que hace cualquier otra cosa, por ejemplo, fmap para un functor. ¡Haskell es una opción tan natural para permitir la sobrecarga del operador que tendrían que trabajar duro para no permitirlo!$operator1 = +
y luego usar una expresión, ¡no necesita usar la sobrecarga del operador en absoluto !Hay muchos idiomas que permiten algún tipo de metaprogramación . En particular, me sorprende no ver una respuesta sobre la familia de idiomas Lisp .
De wikipedia:
Más adelante en el texto:
Idiomas Lisp
Sigue una introducción rápida a Lisp.
Una forma de ver el código es como un conjunto de instrucciones: haz esto, luego haz eso, luego haz lo otro ... ¡Esta es una lista! Una lista de cosas que debe hacer el programa. Y, por supuesto, puede tener listas dentro de listas para representar bucles, etc.
Si representamos una lista que contiene los elementos a, b, c, d como esta: (ABCD) obtenemos algo que se parece a una llamada de función Lisp, donde
a
es la función, yb
,c
,d
son los argumentos. De hecho, el típico "¡Hola Mundo!" programa podría escribirse así:(println "Hello World!")
Por supuesto
b
,c
od
podrían ser listas que evalúen algo también. Lo siguiente:(println "I can add :" (+ 1 3) )
luego imprimiría "" Puedo agregar: 4 ".Entonces, un programa es una serie de listas anidadas, y el primer elemento es una función. ¡La buena noticia es que podemos manipular las listas! Entonces podemos manipular lenguajes de programación.
La ventaja de Lisp
Esto no solo es mucho más fácil en Lisps para crear nuevos operadores, sino que también es casi imposible escribir algunos operadores en otros idiomas porque los argumentos se evalúan cuando se pasan a la función.
Por ejemplo, en un lenguaje tipo C, supongamos que desea escribir un
if
operador usted mismo, algo así como:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
En este caso, ambos argumentos serán evaluados e impresos, en un orden dependiente del orden de la evaluación de los argumentos.
En Lisps, escribir un operador (lo llamamos macro) y escribir una función es casi lo mismo y se usa de la misma manera. La principal diferencia es que los parámetros de una macro no se evalúan antes de pasarlos como argumentos a la macro. Esto es esencial para poder escribir algunos operadores, como el
if
anterior.Idiomas del mundo real
Muestra cómo exactamente está un poco fuera de alcance aquí, pero le animo a que intente programar en un Lisp para obtener más información. Por ejemplo, podrías echar un vistazo a:
Ah, y por cierto, Lisp significa LISt Processing.
En cuanto a tus ejemplos
Voy a dar ejemplos usando Clojure a continuación:
Si puede escribir una
add
función en Clojure(defn add [a b] ...your-implementation-here... )
, puede nombrarla+
así(defn + [a b] ...your-implementation-here... )
. De hecho, esto es lo que se hace en la implementación real (el cuerpo de la función está un poco más involucrado pero la definición es esencialmente la misma que escribí anteriormente).¿Qué pasa con la notación infija? Bueno, Clojure usa una
prefix
notación (o polaca), por lo que podríamos hacer unainfix-to-prefix
macro que convertiría el código prefijado en código Clojure. ¡Lo que en realidad es sorprendentemente fácil (en realidad es uno de los ejercicios macro en los clojure koans)! También se puede ver en la naturaleza, por ejemplo, ver macro de Incanter$=
.Aquí está la versión más simple de los koans explicados:
Para llevar el punto aún más lejos, algunas citas de Lisp :
fuente
if
, pero necesitaría envolver los argumentosthen
yelse
con lambdas. PHP y JavaScript tienenfunction()
, C ++ tiene lambdas, y existe una extensión de Apple para C con lambdas.La mayoría de las implementaciones de idiomas tienen un paso en el que un analizador analiza su código y crea un árbol a partir de él. Entonces, por ejemplo, la expresión
5 + 5 * 8
se analizaría comogracias al conocimiento del compilador sobre precedencia. Si lo alimentó con variables en lugar de operadores, no conocería el orden correcto de las operaciones antes de ejecutar el código. Para la mayoría de las implementaciones, eso sería un problema grave, por lo que la mayoría de los idiomas no lo permiten.
Por supuesto, podría concebir un lenguaje en el que el analizador analice lo anterior como una secuencia de expresiones y operadores, para clasificar y evaluar en tiempo de ejecución. Presumiblemente no hay mucha aplicación para esto.
Muchos lenguajes de script permiten la evaluación de expresiones arbitrarias (o al menos expresiones aritméticas arbitrarias como en el caso de
expr
) en tiempo de ejecución. Allí podría combinar sus números y operadores en una sola expresión y dejar que el lenguaje lo evalúe. En PHP (y muchos otros) esa función se llamaeval
.También hay idiomas que permiten la generación de código en tiempo de compilación. La expresión mixin en D viene a la mente, donde creo que se podría escribir algo así como
Aquí
operator1
yoperator2
tendrían que ser constantes de cadena que se conocen en tiempo de compilación, por ejemplo, parámetros de plantilla.number1
,number2
ynumber3
se dejaron como variables de tiempo de ejecución normales.Otras respuestas ya discutieron las diversas formas en que un operador y una función son más o menos lo mismo, dependiendo del idioma. Pero, por lo general, existe una diferencia sintáctica entre un símbolo de operador infijo incorporado
+
y un nombre llamado invocableoperator1
. Dejaré los detalles a esas otras respuestas.fuente
eval()
construcción del lenguaje " ... Técnicamente proporciona exactamente el resultado deseado en la pregunta.eval
no responde a ese aspecto, ya que paraeval
los operadores son solo cadenas. Por lo tanto, comencé con una explicación de por qué las variables de tipo operador causarían problemas, antes de comenzar a discutir alternativas.Algol 68 tenía exactamente esa característica. Su ejemplo en Algol 68 se vería así:
Su segundo ejemplo se vería así:
Notará que los símbolos del operador están definidos y asignan cuerpos de métodos que contienen la operación deseada. Todos los operadores y sus operandos están tipificados y se les puede asignar prioridades a los operadores para que la evaluación se realice en el orden correcto. También puede notar que hay una ligera diferencia en la fuente entre el símbolo del operador y un símbolo variable.
En realidad, aunque el lenguaje se escribe usando fuentes, las máquinas de la época no podían manejar las fuentes (cinta de papel y tarjetas perforadas), y se utilizaba la eliminación . El programa probablemente se ingresará como:
También puedes jugar juegos interesantes con el lenguaje cuando puedes definir tus propios símbolos para operadores, que exploté una vez, hace muchos años ... [2].
Referencias
[1] Introducción informal a Algol 68 por CHLindsey y SG van der Meulen, Holanda del Norte, 1971 .
[2] Algol 68 Phrases, una herramienta para ayudar a la redacción del compilador en Algol 68 , BC Tompsett, Conferencia Internacional sobre las Aplicaciones de Algol 68, en la Universidad de East Anglia, Norwich, Reino Unido, 1976 ..
fuente