Проблема с наличными или кредитом - PullRequest
2 голосов
/ 12 мая 2010

Если вы идете в магазин и спрашиваете «Наличные или кредит?» они могут просто сказать «да». Это ничего не говорит вам, так как вы поставили OR заявление. if(cash || credit)

С людьми возможно, что они ответят «Оба» на этот вопрос или «Только {наличные | кредит}». Есть ли способ (или оператор) заставить оператор возвращать TRUE части оператора? Например:

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
}

Я хотел бы отметить, что это не проблема, которую я пытаюсь решить. Это то, о чем я думал и думал , возможно ли это . Я не могу придумать практического приложения, которое бы у меня было для него.

Ответы [ 9 ]

10 голосов
/ 12 мая 2010

В C # вы можете сделать что-то очень похожее с перечислением с установленным атрибутом Flags.

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

Пример использования:

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;
    }
}
5 голосов
/ 12 мая 2010

В Scala вы можете написать следующее, используя оператор совпадения

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

Я люблю выражения совпадений.

3 голосов
/ 12 мая 2010

Я предполагаю, что этот несколько искусственный сценарий не совсем то, что вы пытаетесь ответить, поэтому я собираюсь сделать предположение, что в каком-то другом случае есть какая-то ценность.

На языках с функциональными конструкциями вы можете "выбирать" элементы из коллекции, которые соответствуют условию.

В рубине:

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

доходность [: наличные,: кредит]

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

В большинстве языков, о которых я могу думать, вы не можете делать то, что вам нужно, прямо из привязок переменных, не добавляя переменные в коллекцию или словарь. Возможно, есть какое-то исключение, но я не могу вспомнить ни одного из них.

Более близким приближением может быть сопоставление с образцом в таких языках, как Haskell, F # и OCaml, но я до сих пор не могу найти способ заставить его выглядеть так, как вы намекаете.

В Boo вы можете изменить конвейер компилятора, чтобы заменить семантику оператора if чем-то, что дало бы вам то, что вы хотите. Я бы, вероятно, использовал альтернативное ключевое слово, но вы могли бы в основном извлечь все подвыражения и добавить имена переменных в область видимости блока, или добавить значения «да» в одну коллекцию и «nos» в другую, и добавить именованная переменная по соглашению. Чтобы реализовать его с пользой, вам, возможно, придется нарушить соглашение об оценке короткого замыкания, которое раздражало бы большинство людей, привыкших к современной конструкции языка программирования.

3 голосов
/ 12 мая 2010

Это цель использования битовых масок. Вот хороший обзор (пример кода использует разрешения базы данных в качестве примера)

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

2 голосов
/ 12 мая 2010

Вы можете использовать понимание списка, если ваш язык поддерживает его (пример на Python):

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

В качестве альтернативы битовые маски часто используются для таких задач, как эта (а также, как правило, дешевы и существуют в большинстве языков):

CASH = 1
CREDIT = 2
ELSE = 4

myOption = CASH & ELSE

Все зависит от того, что именно вы пытаетесь сделать.

2 голосов
/ 12 мая 2010

Я думаю, что вы стремитесь (и поправьте меня, если я ошибаюсь, потому что я не уверен на 100%), что-то вроде этого:

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

Я не знаю ни одного языка, который может это сделать (по крайней мере, не так, как я иллюстрировал здесь). Как уже упоминалось многими, битовые маски и перечисления часто используются для решения этой проблемы. Некоторые другие люди опубликовали примеры на Ruby, Python и C #, которые могут быть близкими к тому, что вы хотите.

1 голос
/ 12 мая 2010

Судя по комментариям, вы спрашиваете: будет ли какой-либо язык автоматически создавать эту коллекцию для любого оператора if, который оценивается?

Ответ - нет. По крайней мере, не любой современный язык (C, C #, Java, Haskell, почти все). Причина в коротком замыкании. Вообразите это, если утверждение:

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

То есть вы вызываете функцию для получения каждого значения истинности. Если a() оценивается как true, то любой современный язык не будет оценивать какие-либо другие функции, так как они не изменят значение истинности всего утверждения. В настоящее время код опирается на это короткое замыкание, поэтому изменение языка для оценки всех его операндов может привести к поломке большого количества кода.

Что касается особого случая, когда у вас есть набор значений ors и только переменных в тестовом примере ... это действительно особый случай, и лучше использовать некоторые другие решения, предложенные здесь, если вы хотите, чтобы набор истинно, а не просто одно из них истинно.

1 голос
/ 12 мая 2010

Человеческий язык иногда использует слово «или» для обозначения «исключительный или», которое во многих языках (включая c, c ++ и java) обозначается как ^.

То есть cash ^ credit оценивается как true, если и только если один из cash и credit имеет значение true.

0 голосов
/ 12 мая 2010

Это часто делается с флагами и двоичной логикой:

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

...