Considera lo siguiente:
if(a == b or c)
En la mayoría de los idiomas, esto debería escribirse como:
if(a == b or a == c)
que es un poco engorroso y repite información.
Sé que mi sintaxis de muestra anterior es un poco torpe, pero estoy seguro de que hay mejores maneras de transmitir la idea.
¿Por qué no lo ofrecen más idiomas? ¿Hay problemas de rendimiento o sintaxis?
a == b or c
, y ni siquiera se ve bien en mi humilde opinión.Respuestas:
El problema de la sintaxis es que requiere sintaxis.
Cualquiera sea la sintaxis que tenga su idioma, las personas que lo usan tienen que aprenderlo. De lo contrario, corren el riesgo de ver el código y no saber lo que hace. Por lo tanto, generalmente se considera algo bueno si un lenguaje tiene una sintaxis simple que maneja limpiamente muchos casos.
En su ejemplo específico, está tratando de tomar un operador infijo (una función que toma dos argumentos pero está escrita
Argument1 Operator Argument2
) y está tratando de extenderlo a múltiples argumentos. Eso no funciona de manera muy limpia porque el objetivo de los operadores de infijo, en la medida en que haya uno, es colocar el operador justo entre los 2 argumentos. Extender a(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
no parece agregar mucha claridadEquals(Arg1,Arg2,...)
. Infix también se usa típicamente para emular convenciones matemáticas con las que las personas están familiarizadas, lo que no sería cierto para una sintaxis alternativa.No habría problemas de rendimiento particulares asociados con su idea, aparte de que el analizador tendría que lidiar con una gramática con otra o dos reglas de producción, lo que podría tener un ligero efecto en la velocidad del análisis. Esto podría hacer alguna diferencia para un lenguaje interpretado o compilado JIT, pero probablemente no sea una gran diferencia.
El mayor problema con la idea es que hacer muchos casos especiales en un idioma tiende a ser una mala idea .
fuente
.
. Entonces se escribirían comoarg1 op (arg2, arg3)
. No es exactamente hermoso, pero es necesario en algunos lugares en el contexto de ese idioma.if my_var in (a, b)
entonces? ¿No se trata más de utilizar la herramienta adecuada para el trabajo?a == b or c
mientras que otros quierena == b or c but not d
. OMI es donde las funciones de utilidad / bibliotecas vienen al rescate.f().Equals(a,b,c)
; podría evaluarse ya(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
que esa sintaxis sería perfecta, pero si se evalúa asíint[] arr = {a,b,c}; f().Equals(arr);
no sería tan buena, especialmente si se tuviera que crear una nueva matriz para cada llamada.Debido a que no es un problema, y resolverlo conlleva básicamente un beneficio cero, pero implementarlo conlleva un costo distinto de cero.
Las funciones basadas en rangos existentes y tal que prácticamente todos los idiomas ofrecen pueden funcionar perfectamente bien en esta situación si se escala a un tamaño en el
a == b || a == c
que no se corta.fuente
in_array($a, [$b, $c, $d, $e, $f])
. : PAlgunos idiomas tienen tales características. Por ejemplo, en Perl6 podemos utilizar uniones , que son “superposiciones” de dos valores:
Las uniones nos permiten expresar operaciones en un conjunto de datos de manera bastante sucinta, de forma similar a la forma en que las operaciones escalares se distribuyen sobre colecciones en algunos idiomas. Por ejemplo, usando Python con numpy, la comparación se puede distribuir entre todos los valores:
Sin embargo, esto solo funciona para tipos primitivos seleccionados.
¿Por qué las uniones son problemáticas? Debido a que las operaciones en una unión se distribuyen sobre los valores contenidos, el objeto de unión en sí se comporta como un proxy para las llamadas a métodos, algo que pocos sistemas de tipos, aparte de la escritura de pato, pueden manejar.
Los problemas del sistema de tipos se pueden evitar si tales uniones solo se permiten como sintaxis especial alrededor de los operadores de comparación. Pero en este caso, están tan limitados que no agregan suficiente valor para agregarse a cualquier lenguaje sensato. El mismo comportamiento podría expresarse utilizando operaciones de conjunto o deletreando todas las comparaciones manualmente, y la mayoría de los idiomas no creen en agregar sintaxis redundante si ya existe una solución perfectamente buena.
fuente
2 in [1, 2, 3]
. Por otro lado, si numpy tiene un.all()
o algo, la pitón simple equivalente no es tan concisa.==
operador, también podemos usarlo<
, ¿dónde estáin
ahora? Las uniones son más generales que las pruebas de membresía establecidas, porque las operaciones en la unión se distribuyen entre todos los miembros,(x|y).foo
es decirx.foo|y.foo
, hasta que la unión finalmente se colapsa en un solo valor. El código NumPy proporcionado muestra una traducción exactamente equivalente pero más detallada de las uniones Perl6, suponiendo tipos primitivos.En idiomas con macros, es fácil agregar algo así si aún no está allí. Considera la raqueta
En otros idiomas sin metaprogramación, tal vez pueda reformular eso como comprobación de membresía set / list tal vez:
fuente
En algunos idiomas (populares) el
==
operador no es transitivo. Por ejemplo, en JavaScript0
es igual a ambos''
y'0'
, pero luego''
y'0'
no son iguales entre sí. Más de tales peculiaridades en PHP.Significa que
a == b == c
agregaría otra ambigüedad, porque podría producir un resultado diferente dependiendo de si se interpreta como(a == b) & (a == c)
o(a == b) & (a == c) & (b == c)
.fuente
En la mayoría de los idiomas, esto debería lograrse de manera trivial escribiendo una
In
función, entonces, ¿por qué hacerla parte del lenguaje real?Linq, por ejemplo, tiene
Contains()
.Muy bien, para todos ustedes pedantes, aquí está mi implementación en C #:
fuente
a == b || a == c
varias veces, tal vez sea hora deequals_any(a, {b, c})
if (a > (b or c))
yif (a mod (b or c) == 2)
.i
variable. Y, en general, parece estar escrito después de haber tenido un largo día :) Porque poner ambosreturn true
yreturn false
dentro del bucle aquí significa que no hay forma de que vaya más allá de la primera iteración. Solo estás comparando con el primerovalue
. Por cierto, ¿por qué no usarloAny
como sugirió @Bob y simplificarloreturn values.Any(value => Object.Equals(obj, value));
"if (a == b o c)" funciona en la mayoría de los idiomas: si a == b o si c no es negativo, nulo o cero.
Quejarse de que es detallado pierde el punto: no deberías apilar una docena de cosas en un condicional. Si necesita comparar un valor con un número arbitrario de otros valores, cree una subrutina.
fuente
c
evalúa como booleano, entonces casi cualquier idioma puede manejara == b || c
:)if(a == b or c)
. Necesito tomar un descanso, creo ...: Pif (a == b or c)
es un pseudocódigo para verificar sia
es igualb
oa
es igual ac
. No está destinado a verificar quec
no sea cero.Por lo general, desea mantener su sintaxis al mínimo y, en su lugar, permitir que dichas construcciones se definan en el lenguaje mismo.
Por ejemplo, en Haskell, puede convertir cualquier función con dos o más argumentos en un operador infijo mediante backticks. Esto te permite escribir:
donde
elem
es solo una función normal que toma dos argumentos, un valor y una lista de valores, y comprueba si el primero es un elemento del segundo.¿Qué pasa si quieres usar en
and
lugar deor
? En Haskell, puede usar lo siguiente en lugar de esperar a que el proveedor del compilador implemente una nueva característica:fuente
Algunos idiomas ofrecen esto, hasta cierto punto.
Tal vez no como su ejemplo específico , pero tome por ejemplo una línea de Python:
Por lo tanto, algunos idiomas están bien con comparaciones múltiples, siempre que lo exprese correctamente.
Desafortunadamente, no funciona como esperarías para las comparaciones.
"¿Qué quieres decir con que devuelve True o 4?" - el alquiler después de ti
Una solución en este caso, al menos con Python, es usarlo de manera ligeramente diferente:
EDITAR: Lo siguiente también haría algo similar, nuevamente en Python ...
Por lo tanto, sea cual sea el idioma que esté utilizando, puede que no sea que no pueda hacerlo, solo que primero debe echar un vistazo más de cerca a cómo funciona realmente la lógica. Por lo general, es solo una cuestión de saber qué es lo que realmente está 'pidiendo' que le diga el idioma.
fuente
El método indexOf, utilizado en una matriz, que tienen todos los lenguajes, permite comparar un valor con varios otros, por lo que supongo que un operador especial no tiene mucho sentido.
En javascript eso escribiría:
fuente
Usted pregunta por qué no podemos hacer esto:
if(a == b or c)
Python hace esto de manera muy eficiente, de hecho, más eficientemente con
set
:Para la prueba de membresía, 'set' verifica que los valores hash del elemento sean los mismos y solo entonces se compara para la igualdad, por lo que los elementos, byc, deben ser utilizables, de lo contrario, una lista compara directamente la igualdad:
fuente
Los lenguajes de estilo APL le permiten comparar un escalar con cada elemento en un vector en una sola operación. Esto produce un vector booleano. Por ejemplo, me gustaría promocionar descaradamente mi calculadora apl mínimamente presentada, inca ( intérprete en línea ).
Para reducir esto a un solo valor, podemos hacer una inclusión o sumando y verificando que no sea cero.
Entonces, como dicen las otras respuestas, el problema es la sintaxis. Hasta cierto punto, se han encontrado soluciones de sintaxis , a un costo quizás elevado de aprender el paradigma de la matriz.
fuente