Может ли оператор switch иметь более одной переменной? - PullRequest
6 голосов
/ 25 марта 2011

Вопрос основан на всех языках, которые используют блок переключателей (C ++, C # PHP, Java, Python и т. Д.). Так возможно ли иметь что-то подобное?

switch (var1, var2)
case  var1 = a:
    something
    break;
case var2 = b:
    something
    break;
case var1 = 0 ,var2 = 1
     etc...

Ответы [ 11 ]

5 голосов
/ 25 марта 2011

Python не имеет оператора switch.Рекомендуемая альтернатива - использование цепочки цепочек if / else, что в любом случае следует использовать в вашем случае.

Другая распространенная идиома - использование карты.И в вашем случае вы можете использовать кортеж (var1, var2) для сопоставления с результатами.

switch = {
   (1,2): lambda: ..,
   (3,4): lambda: ...,
}
switch[(var1,var2)]

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

4 голосов
/ 25 марта 2011

Да / Нет.

Нет традиционного языка с оператором "switch".Он существует в так называемом «сопоставлении с образцом».

C #, Java, PHP и Python не поддерживают сопоставление с образцом (не совсем уверен в PHP, но я не верю в это. Поправьте меня, если яЯ ошибаюсь).

Вот пример в Haskell, где сопоставление с образцом действительно существует.Сопоставление с образцом происходит во многих языках функциональных стилей.

function 1 _ = "first parameter has a one"
function _ 1 = "second parameter is a one"
function _ _ = "I don't know what crazy number you passed in"

Когда эта функция вызывается, среда выполнения / компилятор / любой, кто ее проверяет, увидит, можно ли вызвать первую функцию.Если это возможно, он возвращает это значение.Затем он продолжает работать до тех пор, пока не найдет какое-либо совпадение, которое работает для заданных параметров.«_» - это просто способ сказать: «Здесь может быть что угодно, и мне действительно все равно, что это, поэтому не связывайте значение с именем».Если бы я заботился о значении, я мог бы сделать следующее:

function 1 a = "second parameter is " ++ (show a)

Теперь, поскольку оно обычно идет сверху вниз (в отличие от оператора switch), это больше похоже на оператор if / else, чем оператор switch, который простопрыгает в правильное место.Это просто очень красиво выглядит, если / еще.Кроме того, если бы я переупорядочил его так, чтобы самый общий случай был в верхней части файла, другие случаи были бы проигнорированы.

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

2 голосов
/ 25 марта 2011

Как уже говорилось, это сопоставление с образцом типично для функциональных языков. Но вы можете найти как минимум «гибридные» функциональные / ООП, которые его поддерживают.

Вот пример на F #

let fnc (var1, var2) =
    match (var1, var2) with
        | 2 , _ -> "something"
        | _ , 3 -> "something else"
        | 0, 1  -> "etc ... "
        | a, b -> "I got " + a.ToString() + " and " + b.ToString()

fnc(0, 1) |> printfn "%s" // prints "etc.."

и то же самое в скале

def fnc(var1: Int, var2: Int) : String = 
  (var1, var2) match { 
    case (2, _) => "something" 
    case ( _,3) => "something else"
    case (0, 1) => "etc..."
    case (a, b) => "I got " + a + " and " + b
  } 

println(fnc(0,1))
2 голосов
/ 25 марта 2011

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

def matchTest(var1: Any, var2: Any): Any = (var1, var2) match {
  case (a, _) => "var1 == a"
  case (_, b) => "var2 == b"
  case (0, 1) => "var1 == 0, var2 == 1"
}
2 голосов
/ 25 марта 2011

CHILL позволяет:

PROC (b board LOC,m move) EXCEPTIONS (illegal);
DCL starting square LOC:= b (m.lin_1)(m.col_1),
arriving square LOC:= b (m.lin_2)(m.col_2);
DO WITH m;
IF starting.status=free THEN CAUSE illegal; FI;
IF arriving.status/=free THEN
IF arriving.p.kind=king THEN CAUSE illegal; FI;
FI;
CASE starting.p.kind, starting.p.color OF
   (pawn),(white):
      IF col_1 = col_2 AND (arriving.status/=free
      OR NOT (lin_2=lin_1+1 OR lin_2=lin_1+2 AND lin_2=2))
      OR (col_2=PRED (col_1) OR col_2=SUCC (col_1))
      AND arriving.status=free THEN CAUSE illegal; FI;
      IF arriving.status/=free THEN
      IF arriving.p.color=white THEN CAUSE illegal; FI; FI;
   (pawn),(black):
      IF col_1=col_2 AND (arriving.status/=free
      OR NOT (lin_2=lin_11 OR lin_2=lin_12 AND lin_1=7))
      OR (col_2=PRED (col_1) OR col_2=SUCC (col_1))
      AND arriving.status=free THEN CAUSE illegal; FI;
      IF arriving.status/=free THEN
      IF arriving.p.color=black THEN CAUSE illegal; FI; FI;
   (rook),(*):
      IF NOT ok_rook (b,m)
      THEN CAUSE illegal;
      FI;
   (bishop),(*):
      IF NOT ok_bishop (b,m)
      THEN CAUSE illegal;
      FI;
   (queen),(*):
   IF NOT ok_rook (b,m) AND NOT ok_bishop (b,m)
     THEN CAUSE illegal;
2 голосов
/ 25 марта 2011

Я думаю, что вы можете выполнить произвольное сопоставление регистров в некоторых языках, таких как Haskell и ML.См. Соответствие шаблону Хаскелла .Рассматриваемый объект по-прежнему является единственным объектом, но этот объект может быть кортежем, который содержит произвольное количество объектов.

Пример, приведенный в ссылке:

describeList :: [a] -> String
describeList list = 
  case list of
   []     -> "The list was empty"
   (x:xs) -> "The list wasn't empty: the first element was " ++ show x ++
             ", and there were " ++ show (length xs) ++
             " more elements in the list."
0 голосов
/ 25 марта 2011

AFAIK, python не имеет переключателя.

0 голосов
/ 25 марта 2011

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

0 голосов
/ 25 марта 2011

Нет. Вам придется вкладывать регистр переключателя для одной переменной в каждый регистр другого.

0 голосов
/ 25 марта 2011

Конечно, не в C #.Вы бы использовали шаблон if / else if, чтобы пройти через такие условия.Я не могу говорить на любом другом языке с авторитетом, но я на 99% уверен, что Java тоже не позволяет этого.Кто знает, что допускают эти сумасшедшие парни из PHP и Python ...

...