Es un poco subjetivo, pero espero obtener una comprensión más clara de los factores que hacen que un operador sea claro de usar vs obtuso y difícil. He estado considerando los diseños de idiomas recientemente, y un tema que siempre vuelvo a plantear es cuándo hacer que una operación clave en el idioma sea un operador, y cuándo usar una palabra clave o función.
Haskell es algo notorio por esto, ya que los operadores personalizados son fáciles de crear y, a menudo, un nuevo tipo de datos vendrá empaquetado con varios operadores para su uso. La biblioteca Parsec, por ejemplo, viene con un montón de operadores para combinar analizadores, con gemas como >.
y .>
ni siquiera puedo recordar lo que significan en este momento, pero sí recuerdo que es muy fácil trabajar con ellos una vez que memoricé qué en realidad quieren decir. ¿Sería mejor una llamada a una función como leftCompose(parser1, parser2)
? Ciertamente más detallado, pero más claro en algunos aspectos.
Las sobrecargas de operadores en lenguajes tipo C son un problema similar, pero se combinan con el problema adicional de sobrecargar el significado de operadores familiares como +
con nuevos significados inusuales.
En cualquier idioma nuevo, esto parecería un problema bastante difícil. En F #, por ejemplo, la conversión utiliza un operador de conversión de tipo derivado matemáticamente, en lugar de la sintaxis de conversión de estilo C # o el estilo detallado de VB. C #: (int32) x
VB: CType(x, int32)
F #:x :> int32
En teoría, un nuevo lenguaje podría tener operadores para la mayoría de las funciones integradas. En lugar de def
o dec
o var
de declaración de variables, por qué no ! name
o @ name
o algo similar. Ciertamente acorta la declaración seguida de un enlace: en @x := 5
lugar de declare x = 5
o let x = 5
La mayoría del código requerirá muchas definiciones de variables, entonces ¿por qué no?
¿Cuándo es un operador claro y útil, y cuándo se está oscureciendo?
+
para concatenación de cadenas o <<
para secuencias). Con Haskell, por otro lado, un operador es o bien simplemente una función con un nombre personalizado (es decir, no sobrecargado) o parte de una clase de tipo que significa que si bien es polimórfico, que hace lo mismo lógica cosa para cada tipo y incluso tiene el mismo tipo de firma. Así >>
es >>
para cada tipo y nunca va a ser un poco turno.