Skip to content

Latest commit

 

History

History
85 lines (50 loc) · 6.45 KB

README_RU.md

File metadata and controls

85 lines (50 loc) · 6.45 KB

Оператор Объединения

Множественные источники данных

In general, the winner of this pushup competition can't be determined until both participants are finished.

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

В ро для таких ситуаций предусмотрен оператор объединения. Чтобы совершить объединение, просто используйте символ ;.

for (p1Pushups <- @"player1"; p2Pushups <- @"player2") {
  @"stdout"!("The winner is...")
}

Запуск ракеты

Для компании, которая занимается исследованием космоса, важно, чтобы запуск ракеты происходил только тогда, когда два инженера Алиса и Боб оба передадут команду на запуск. Например, Боб отдает такую команду, отправляя строку "ключ на старт" командой BobLaunch!("ключ на старт").

Упражнение

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

Ошибочный вариант

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

launchBad.rho

Проблема возникает тогда, когда Алиса дала согласие на запуска, а Боб ещё нет. У Алисы должна остаться возможность передумать, а сейчас её нет. Представьте, что она внезапно находит какой-нибудь дефект, или резко меняется погода, и ей нужно отложить запуск.

No use in grabbing just one set of mail. Might as well wait until the second set

Если использовать объединение, то у Алисы всё ещё будет возможность передумать, так как for не поглотит её сообщение на запуск, пока также не появится сообщение от Боба.

Правильный вариант

launch.rho

Какой код нужно добавить Алисе, чтобы отозвать команду на запуск?

  • @"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!("Надеюсь, я выиграл")

Игра на терперие -- Решение В этом случае нам не надо использовать объединение, потому что нам важно знать, какой игрок походил первым. Надеюсь, вы избежали ловушки ;)

patienceSolution.rho

Как написано в комментарии, нам нужно отправить по сообщению на каждый канал, чтобы точно знать, кто выиграл. Самый простой способ сделать это сейчас -- использовать REPL как описано в нулевом уроке. Другой вариант: когда один игрок сигналит другому, когда можно ходить, как показано в примере ниже. В следующем уроке мы разберем подобные случаи подробней.

P1First.rho

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

  • Потому что оба игрока могут отправить сообщения в то же время
  • Игроки отправляют сообщения на неверные каналы
  • Первый блок получает P2, а другой - P1, и игра никогда не заканчивается