views:

312

answers:

9

If you go to a store and ask "Cash or Credit?" they might simply say "Yes." This doesn't tell you anything as you posed an OR statement. if(cash || credit)

With humans it's possible that they might respond "Both" to that question, or "Only {cash | credit}." Is there a way (or operator) to force the a statement to return the TRUE portions of a statement? For example:

boolean cash = true;
boolean credit = true;
boolean check = false;

if(cash || credit || check)
{
    // In here you would have an array with cash and credit in it because both of those are true
}

I would like to note that this is not a problem I'm trying to solve. It's something I was thinking about and wondered if it was possible. I can't think of a practical application I would have for it.

+2  A: 

I think what you're aiming for (and correct me if I'm wrong because I'm not 100% sure here) is something like this:

if (operandA || operandB || operandC || (operandD && operandE))
{
    //in here we have access to an environment-created array $TRUE_OPERANDS which stores the operands
    //that were TRUE in the most recently evaluated if-statement.
    //Maybe it contains the names of operands. suppose that A, C and E were TRUE
    //then $TRUE_OPERANDS = {'operandA', 'operandC', 'operandE'}
    //...but E was AND'd with D and D was false, so should E still be returned?
    //Are E and D considered separate operands or are the considered as a single "E && D" operand?
    //...and how would we implement nested if-statements?
    //Would there be only one global $TRUE_OPERANDS or would there be one
    //for the scope of every if-statement?
}

I am not aware of any language that can do that (at least not like how I illustrated here). As many others have mentioned, bitmasks and enums are often used to work around this problem. Some other people have posted examples in Ruby, Python, and C# that might be close to what you want.

FrustratedWithFormsDesigner
+1  A: 

Human language sometimes use the word "or" to mean "exclusive or", which, in many languages (including c, c++ and java) is denoted by ^.

That is, cash ^ credit evaluates to true, if and only if one of cash and credit is true.

aioobe
In fact you can usually determine whether the speaker meant XOR or OR by their intonation. Asking it like a question, with a rising tone - they mean OR. Asking it point-blank with flat tone - they mean XOR.Contrast "Would you like an apple or a banana?" with rising tone and flat tone. :)
David
Yeah.. sure. Usually it is evident from the context as well :-)
aioobe
A: 

This is often done with Flags and binary logic:

http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx http://msdn.microsoft.com/en-us/library/cc138362.aspx

NotDan
+10  A: 

In C# you can do something very similar to this with an enum with the Flags attribute set.

[Flags]
enum MethodOfPayment
{
    None = 0,
    Cash = 1,
    Credit = 2,
    Check = 4
}

Example usage:

void Run()
{
    MethodOfPayment m = MethodOfPayment.Cash | MethodOfPayment.Credit;
    if (m != MethodOfPayment.None)
    {
        // You can now test m to see which values are selected.

        // If you really want the values in an array, you can do this:
        MethodOfPayment[] selected = getSelectedValues(m).ToArray();
        // selected now contains { Cash, Credit }
    }
}

// Helper method to get the selected values from the enum.
IEnumerable<MethodOfPayment> getSelectedValues(MethodOfPayment m)
{
    foreach (MethodOfPayment x in Enum.GetValues(typeof(MethodOfPayment)))
    {
        if ((m & x) != MethodOfPayment.None)
            yield return x;
    }
}
Mark Byers
can you give an example usage?
Claudiu
+2  A: 

You can use a list comprehension if your language supports it (example in Python):

list = [True, False, True, True]
print [x for x in list if x] # print only the True values

Alternatively, bitmasks are often used for tasks such as this (as well as being generally cheap and exist in most languages):

CASH = 1
CREDIT = 2
ELSE = 4

myOption = CASH & ELSE

It all depends on what exactly you are trying to do.

Yuval A
+5  A: 

In Scala you could write the following using a match statement

def OneOrTheOther( _1:Boolean, _2:Boolean ) = {
    (_1, _2) match{
        case True, False => //do stuff
        case False, True => //do stuff
        case True, True =>  //do stuff
        case False, False =>//do stuff
     }
}

I love match expressions.

wheaties
+1 match is great
Claudiu
+3  A: 

This is the purpose of using bitmasks. Here is a good overview (the sample code uses database permissions as an example)

http://www.vipan.com/htdocs/bitwisehelp.html

Ben Hoffstein
+3  A: 

I presume this somewhat artificial scenario isn't really what you're trying to answer, so I'm going to make the presumption that there's some value in some other case.

In languages with functional constructs, you can "select" items from a collection that match a condition.

In Ruby:

payment={cash=>true, credit=>true, check=>false}
methods_used=payment.select{ |key,value| value==true}.map { |key,value| key}

yields [:cash, :credit]

In C# 3:

var payment = new Dictionary<string, bool> 
   {{"cash", true}, {"credit",true}, {"check", false}};
var items=payment.Where(x => x.Value == true).Select(x => x.Key);
Console.WriteLine(String.Join(",",items.ToArray()));

In most languages that I can think of, you can't do what you're after straight from variable bindings without adding the variables to a collection or dictionary. There might be some sort of exception, but I can't think of one off the top of my head.

A closer approximation might be pattern matching in languages like Haskell, F# and OCaml, but I still can't quite find a way to make it look the way you're hinting.

In Boo, you could alter the compiler pipeline to replace the semantics of the if statement with something that would give you what you want. I would probably use an alternate keyword, but you could basically extract all the subexpressions, and add the variable names to the scope of the block, or add the "yes" values to one collection and the "nos" to another, and add a named variable by convention. In order to implement it usefully, you might have to break the convention of short-circuit evaluation, which would annoy most people used to contemporary programming language design.

JasonTrue
I *think* he wants to know if any languages will automatically create that collection for any if-statement that gets evaluated.
FrustratedWithFormsDesigner
@Frustrated: Yes!
Josh K
@Josh K: Is my code sample (further below) a more generic description of the problem?
FrustratedWithFormsDesigner
@Frustrated: Yes it is, +1. Edited question.
Josh K
+1  A: 

From the comments, you seem to be asking: will any language automatically create that collection for any if-statement that gets evaluated?

The answer is no. At least, not any modern language (C, C#, Java, Haskell, pretty much anything). The reason is short-circuiting. Imagine this if statement:

if (a() || b() || c() || d()) {
}

That is, you call a function to get each truth value. If a() evaluates to true, then any modern language will not evaluate any of the other functions, since they wouldn't change the truth value of the entire statement. Code nowadays relies on this short-circuiting, so changing a language to evaluate all its or operands would likely break a lot of code.

As for the special case where you have a set of ors and only variables in the test case... that's a really special case, and it's best to use some of the other solutions proposed here if you want a set of what is true instead of just whether any one of them is true.

Claudiu
You can use `if(a() | b() | c() | d())` in Java (and possibly also Cx) to not-lazy evaluate the if-statement.
Pindatjuh
@Pindatjuh yes, but I think the point was that *already existing* code might break if this feature was introduced to *already existing* languages that use short-circuit evaluation, if this new addition would prohibit short-circuit eval. Perhaps a, b, c, or d have side-effects.
Wallacoloo