2010-01-14 1 views
5

Da quando ho iniziato la programmazione correttamente utilizzando il buon vecchio VB6 e fino ad oggi, ho spesso ancora ottenere bruciato (e solo) di questo nella programmazione:"o" operatore senza ripetere la condizione mano sinistra di nuovo

if x == something or x == somethingelse 

ho spesso finiscono per iscritto:

if x == something or somethingelse 

Solo per puro interesse, fa qualsiasi langauge/lingue là fuori sostenere questo?

risposta

11

Python fa, tipo di:

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

in controlla semplicemente se un elemento presente in una lista. Allo stesso modo, in Haskell:

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

Suppongo che questo può essere fatto nella maggior parte delle lingue che permettono a manifestare il proprio tipo di lista.

+0

È una specie di imbroglio;) Lo si può fare anche con IList + LINQ in .NET. –

+0

Non è barare, è così che lo fai. Le cose sul lato sinistro si ottiene gratis! – Thomas

+0

Accettato, sebbene come detto sia un po 'imbroglio e richiede una lista piuttosto che essere implementato direttamente nel linguaggio se costrutto. – Finglas

3

In molti linguaggi di programmazione si può fare qualcosa di simile:

myArray[something, somethingElse].Contains(x) 

... ma la mia ipotesi è che si comporta un po 'peggio.

+0

I miei test rapidi mostrano che in Python le prestazioni sono quasi esattamente le stesse tra "se x == 3 o x == 5" e "se x in [3,5]". Tuttavia, non ho dubbi che il test potrebbe essere più completo e conclusivo. – Cdsboy

6

SQL ha un operatore in: x in (something, somethingelse) e ci sono molte lingue in cui è possibile implementare qualcosa di simile.

in C#, per esempio, io uso un metodo di estensione personalizzata: if (x.In("something", "somethingelse"))...

modificare ecco la fonte del mio c Metodo # estensione:

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

In lingue con un operatore di "switch", si può fare:

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

    default: 
    { 
     // else case 
     break;  
    } 
} 

e 'un po' prolisso, ma in C si potrebbe nasconderlo in una macro o in C++, forse un modello.

+0

Supponendo che 'x' sia di un tipo che può essere 'commutato su'. In C e nella maggior parte dei linguaggi di tipo C, questo funziona solo sui numeri interi. – Thomas

+0

Se 'x' non è qualcosa su cui 'switch' può essere acceso, allora probabilmente non vi è ottimizzazione. Per un elenco di stringhe, dovrai chiamare 'strcmp()' o equivalente su ognuna, o usare un ciclo 'for'. –

0

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

1

MATLAB ha un paio di modi per gestire la seconda forma si elencano sopra:

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

Se

A in [x, y, z] 

è considerato una valida soluzione, allora la funzione

in(A, x, y, z) 
dovrebbe essere considerato una valida soluzione troppo

, soprattutto per un linguaggio che permette all'operatore sovraccarico modo che CMP (A, x, y, z) potrebbe essere mappati

A in x y z 

discussioni finora hanno soffermati su

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

e il caso di

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

Pertanto, useremmo varargs, una funzionalità presente in C, C++, C# e java5.

Usiamo java per illustrare.

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 consentono di definire una singola funzione che prende in un numero variabile di argomenti in modo che si può usare lo stesso metodo per confrontare

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

Tuttavia, quanto sopra è definita solo per confronti stringa , così dovremmo creare un paio di metodi per ogni tipo di arg. Ma poi in Java 5 ci sono i generici.

<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; 
} 

Così ora è possibile fare confronti per qualsiasi tipo che implementa un'interfaccia comparabile.

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

Peccato, Java non permette l'overloading degli operatori in modo che si possa fare

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

in C++, non ho mai tentato l'overloading degli operatori con varargs sapere anche se è possibile.

Revisit: Tuttavia, rivisita questo ore più tardi,

potremmo definire una classe

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; 
    } 
} 

Ora, non abbiamo bisogno di overloading degli operatori a tutti e possiamo fare

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); 

E potremmo espanderlo e potremmo fare tutto, in tutto, gtany, gtall, ltany, ltall, ecc espandendo il co mparison funzionalità.

2

Il Icon programming language supporta magnificamente questo linguaggio.Icon è stata progettata da Ralph Griswold, che aveva già progettato SNOBOL, e l'intero modello di valutazione è basato sul successo o l'insuccesso. Tutto si compone e in linea di principio ogni espressione può produrre più risultati. È possibile scrivere cose come

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

Ecco il modello di valutazione:

  1. In primo luogo si valuta l'espressione tra parentesi e ottenere something
  2. Poi si confronta something-x
  3. Se sono non uguale, l'espressione non riesce e il motore di valutazione torna automaticamente indietro.
  4. Durante il backtracking, la valutazione dell'espressione tra parentesi è riprende e ha esito positivo! Questa volta produce somethingelse.
  5. Supponiamo che questo confronto abbia esito positivo. Quindi viene valutato il corpo di if e il programma scrive sullo standard output.

Ecco un altro scenario interessante: ogni confronto ha esito positivo o negativo e, se riesce, restituisce l'argomento della mano destra. Così si può fare il controllo dei limiti con

lo <= x < limit 

Questa espressione parenthesizes così:

(lo <= x) < limit 

E così, se è più grande lox, l'espressione tra parentesi non riesce, e così il tutto non riesce. (Un'espressione ordinaria fallisce se una parte di esso non riesce.) Ma se lo è al massimo x, quindi lo <= xsupera e restituisce x. Successivamente, la macchina confronta x < limit e se ciò riesce, l'intera operazione ha esito positivo.

L'icona era un linguaggio magnificamente coerente, meravigliosamente facile da usare e sottovalutato. Ma non è mai stato ben integrato con il sistema operativo, e quando hanno avuto una versione che ha funzionato bene con Unix, Icon ha già perso le sue possibilità di ottenere mindshare. Ma tutti i progettisti linguistici potrebbero imparare molto studiandolo.

R.I.P.

+0

Interessante, non ne avevo mai sentito parlare. – Finglas