2010-01-14 6 views
5

Desde que empecé a programar adecuadamente con el bueno de VB6 y hasta el día de hoy, a menudo todavía se queman (y simplemente) por esto en la programación:"o" operador sin repetir el problema en la mano izquierda de nuevo

if x == something or x == somethingelse 

a menudo terminan por escrito:

if x == something or somethingelse 

Sólo por puro interés, tiene que ver todo langauge/idiomas por ahí apoyar esto?

Respuesta

11

Python hace, tipo de:

if x in [something, somethingelse]: 
    ... 

in simplemente comprueba si un elemento se presenta en una lista dada. Del mismo modo, en Haskell:

if x `elem` [something, somethingelse] then ... 

supongo que esto se puede hacer en la mayoría de lenguajes que permiten la expresión de tipo de lista.

+0

Eso es una especie de trampa;) También podrías hacer eso con IList + LINQ en .NET. –

+0

Eso no es hacer trampa, así es como lo haces. ¡Las cosas del lado izquierdo las obtienes gratis! – Thomas

+0

Aceptado, aunque como se mencionó, es un poco engañoso y requiere una lista en lugar de implementarse directamente en el lenguaje si se construye. – Finglas

3

En muchos lenguajes de programación que puede hacer algo como esto:

myArray[something, somethingElse].Contains(x) 

... pero mi conjetura es que realizaría un poco peor.

+0

Mis pruebas rápidas muestran que en Python el rendimiento es casi exactamente el mismo entre "si x == 3 o x == 5" y "si x en [3,5]". Sin embargo, no tengo dudas de que la prueba podría ser más completa y concluyente. – Cdsboy

6

SQL tiene un operador in: x in (something, somethingelse), y hay muchos idiomas donde puede implementar algo similar.

en C#, por ejemplo, yo uso un método de extensión personalizada: if (x.In("something", "somethingelse"))...

edición aquí está la fuente de mi c Método # extensión:

public static bool In<T>(this T item, params T[] test_values) { 
    foreach (T test_value in test_values) 
    { 
    if (test_value.Equals(item)) 
    { 
     return true; 
    } 
    } 

    return false; 
} 
1

En idiomas con un operador de "interruptor", que puede hacer:

switch (x) 
{ 
    case 1: 
    case 2: 
    { 
     // do whatever 
     break; 
    } 

    default: 
    { 
     // else case 
     break;  
    } 
} 

es un poco prolijo, pero en C que podía esconderlo en una macro o en C++ tal vez una plantilla.

+0

Suponiendo que 'x' es de un tipo que puede 'cambiarse'. En C, y en la mayoría de los lenguajes tipo C, esto solo funciona en enteros. – Thomas

+0

Si 'x' no es algo que pueda 'cambiarse', entonces no es probable que haya optimización. Para obtener una lista de cadenas, deberá llamar a 'strcmp()' o equivalente en cada una, o usar un bucle 'for'. –

0

Perl: $foo ~~ ['string',$number,qr/regex/]

1

MATLAB tiene un par de maneras de manejar la segunda forma que la lista anterior:

if any(x == [something somethingelse]) ... 
%# OR 
if ismember(x,[something somethingelse]) ... 
0

Si

A in [x, y, z] 

se considera una solución válida, entonces la función

in(A, x, y, z) 

debe considerarse una solución válida también, especialmente para un lenguaje que permite la sobrecarga de operadores para que cmp (a, x, y, z) podría ser mapeada a

A in x y z 

discusiones hasta ahora han insistido en

if (A == x or y or z). 

¿Qué pasa con el caso de

if (A == x and y and z). 

por lo tanto, usaríamos varargs, una característica que se encuentra en C, C++, C# y java5.

Vamos a usar Java para ilustrar.

boolean or(String lhs, String... rhs){ 
    for(String z: rhs){ 
    if (lhs.equals(z) return true; 
    } 
    return false; 
} 

boolean and(String lhs, String... rhs){ 
    for(String z: rhs){ 
    if (!lhs.equals(z) return false; 
    } 
    return true; 
} 

Varargs le permiten definir una única función que toma en un número variable de argumentos para que usted podría utilizar el mismo método para comparar

or (A, x) 
or (A, x, y) 
or (A, x, y, z) 

Sin embargo, lo anterior se define sólo por las comparaciones de cadenas , de modo que tendríamos que crear un par de métodos para cada tipo de arg. Pero luego en Java 5 hay genéricos.

<T extends Comparable<T>>boolean or(T lhs, T... rhs){ 
    for(T z: rhs){ 
    if (lhs.compareTo(z)==0) return true; 
    } 
    return false; 
} 

<T extends Comparable<T>>boolean and(T lhs, T... rhs){ 
    for(T z: rhs){ 
    if (lhs.compareTo(z)!=0) return false; 
    } 
    return true; 
} 

Ahora puede hacer comparaciones para cualquier tipo que implemente una interfaz comparable.

and(stringA, stringx, stringy) 
or(dateA, datex) 

Lástima, Java no permite la sobrecarga de operadores para que pudiéramos hacer

stringA && stringx, stringy 
dateA || datex, datey, datez 

en C++, nunca he intentado la sobrecarga de operadores con varargs saber incluso si es posible.

Revisita: Sin embargo, volver a visitar esta hora más tarde,

podríamos definir una clase

public class <T extends Comparable<T>> Comparigator{ 
    public Comparigator(T lhs){ 
    this.lhs = lhs; 
    } 
    final private T lhs; 

    static public <T extends Comparable<T>> Comparigator is(T lhs){ 
    return (T)new Comparigator(lhs); 
    } 

    public boolean inAny(T... rhs){ 
    for(T z: rhs){ 
     if (this.lhs.compareTo(z)==0) return true; 
    } 
    return false; 
    } 

    public boolean inAll(T... rhs){ 
    for(T z: rhs){ 
     if (this.lhs.compareTo(z)!=0) return false; 
    } 
    return true; 
    } 

    public boolean gtAny(T... rhs){ 
    for(T z: rhs){ 
     if (this.lhs.compareTo(z)>0) return true; 
    } 
    return false; 
    } 

    public boolean gtAll(T... rhs){ 
    for(T z: rhs){ 
     if (this.lhs.compareTo(z)<=0) return false; 
    } 
    return true; 
    } 
} 

Ahora, no necesitamos la sobrecarga de operadores en todo y nos puede hacer

import Comparigator; 
..... 

is(A).inAny(x,y,z); // or 
is(A).inAll(w,x,y,z); // and 

is(B).gtAny(k,l,m); 
is(C).gtAll(j,k); 

Y podríamos expandirlo y podríamos hacerlo en cualquier, en todos, gtany, gtall, ltany, ltall, etc. mediante la expansión de la co funcionalidad de comparación.

2

El Icon programming language es compatible con este idioma maravillosamente.Icon fue diseñado por Ralph Griswold, quien ya había diseñado SNOBOL, y su modelo de evaluación completo está basado en el éxito o el fracaso. Todo se compone, y en principio cada expresión puede producir resultados múltiples. Se puede escribir cosas como

if x == (something | somethingelse) then write("Goodie!") 

Esto es el modelo de evaluación:

  1. Primero se evalúa la expresión entre paréntesis y obtener something
  2. A continuación, comparar something-x
  3. Si están no igual, la expresión falla, y el motor de evaluación retrocede automáticamente.
  4. Durante el retroceso, la evaluación de la expresión entre paréntesis es reanudada, y vuelve a tener éxito! Esta vez produce somethingelse.
  5. Supongamos que esta comparación tiene éxito. Luego, se evalúa el cuerpo del if y el programa escribe en la salida estándar.

Aquí hay otro escenario interesante: cada comparación tiene éxito o falla, y si tiene éxito, devuelve su argumento de la derecha. Lo que puede hacer la comprobación de límites con

lo <= x < limit 

Esta expresión parenthesizes así:

(lo <= x) < limit 

Y por lo que si es más grande que lox, la expresión entre paréntesis falla, y así toda la cosa falla. (Una expresión ordinaria falla si alguna parte de ella falla). Pero si lo es como máximo x, entonces lo <= xsucede y devuelve x. Luego, por supuesto, la máquina compara x < limit, y si eso tiene éxito, todo se lleva a cabo.

El ícono era un lenguaje hermosamente consistente, maravillosamente fácil de usar y poco apreciado. Pero nunca estuvo bien integrado con el sistema operativo, y para el momento en que tenían una versión que funcionaba bien con Unix, Icon ya había perdido la oportunidad de compartir su mente. Pero todos los diseñadores de idiomas podrían aprender mucho estudiándolo.

R.I.P.

+0

Interesante, nunca había oído hablar de eso. – Finglas

Cuestiones relacionadas