Часто бывает, что вычисление можно сделать только после получения данных из двух или более источников. Например, нельзя понять, выиграли ли вы в лотерею прежде, чем вы купили билет и стали известны выигрышные номера. Нельзя результат закупки, пока не станет ясно количество и цена приобретенного товара. Нельзя объявить победителя в конкурсе отжиманий, пока все участники не закончат отжиматься.
В ро для таких ситуаций предусмотрен оператор объединения. Чтобы совершить объединение, просто используйте символ ;
.
for (p1Pushups <- @"player1"; p2Pushups <- @"player2") {
@"stdout"!("The winner is...")
}
Для компании, которая занимается исследованием космоса, важно, чтобы запуск ракеты происходил только тогда, когда два инженера Алиса и Боб оба передадут команду на запуск. Например, Боб отдает такую команду, отправляя строку "ключ на старт" командой BobLaunch!("ключ на старт")
.
Придумайте, как можно написать такой код для запуска, используя оператор объединения, о котором мы только что узнали.
Можно попытать решить проблему запуска так: вначале получить одну команду на запуск, а затем - другую.
Проблема возникает тогда, когда Алиса дала согласие на запуска, а Боб ещё нет. У Алисы должна остаться возможность передумать, а сейчас её нет. Представьте, что она внезапно находит какой-нибудь дефект, или резко меняется погода, и ей нужно отложить запуск.
Если использовать объединение, то у Алисы всё ещё будет возможность передумать, так как for
не поглотит её сообщение на запуск, пока также не появится сообщение от Боба.
Какой код нужно добавить Алисе, чтобы отозвать команду на запуск?
-
@"AliceCancel"!("cancel")
-
@"AliceLaunch"!("cancel")
-
for (x <- @"AliceLaunch"){Nil}
Концепция объединения переосмыслена как проблема философов за обедом, которая детально изучена в кратком туториале по ро.
В выражении for (x <- y; a <- b){ Nil }
на какой канал нужно отправлять сообщения в первую очередь?
- y
- b
- неважно
- сообщения должны быть отправлены одновременно
В выражении for (x <- y; a <- b){ Nil }
какое сообщение будет поглощено первым?
- x
- a
- неважно
- сообщения будут поглощены одновременно
Представим себе игру, в которой два игрока отправляют сообщение на разные каналы. Тот, кто отсылает сообщение первым, проигрывает. А тот, у кого терпения больше и кто отсылает сообщение вторым, выигрывает. Ваша задача написать код для такой игры, который определяет, кто же выиграл. Чтобы сыграть, игроки отправляют сообщения примерно такого плана:
P1!("Рано отправил")
P2!("Надеюсь, я выиграл")
Игра на терперие -- Решение В этом случае нам не надо использовать объединение, потому что нам важно знать, какой игрок походил первым. Надеюсь, вы избежали ловушки ;)
Как написано в комментарии, нам нужно отправить по сообщению на каждый канал, чтобы точно знать, кто выиграл. Самый простой способ сделать это сейчас -- использовать REPL как описано в нулевом уроке. Другой вариант: когда один игрок сигналит другому, когда можно ходить, как показано в примере ниже. В следующем уроке мы разберем подобные случаи подробней.
Почему игра на терпение, в том виде, в котором она написана сейчас, может остаться без победителя?
- Потому что оба игрока могут отправить сообщения в то же время
- Игроки отправляют сообщения на неверные каналы
- Первый блок получает P2, а другой - P1, и игра никогда не заканчивается