Реализация снимка в FRP
Я внедряю FRP-фреймворк в Scala и, похоже, столкнулся с проблемой. Руководствуясь некоторыми размышлениями, этот вопрос я решил ограничить общедоступным интерфейсом моей платформы, чтобы поведение можно было оценить только в "настоящем", то есть:
behaviour.at(now)
Это также согласуется с предположением Конала в статье Фрэн о том, что Поведение оценивается / отбирается только в возрастающее время. Это ограничивает преобразования в поведении, но в противном случае мы находимся в огромных проблемах с поведением, которые представляют некоторый вклад:
val slider = Stepper(0, sliderChangeEvent)
При таком поведении оценка будущих значений будет неправильной, а оценка прошлых значений потребует неограниченного объема памяти (все вхождения, используемые в событии "ползунок", должны быть сохранены).
У меня возникли проблемы со спецификацией для операции "моментальный снимок" в поведении с учетом этого ограничения. Моя проблема лучше всего объясняется на примере (с использованием ползунка, упомянутого выше):
val event = mouseB // an event that occurs when the mouse is pressed
val sampler = slider.snapshot(event)
val stepper = Stepper(0, sampler)
Моя проблема здесь заключается в том, что если при выполнении этого кода произошло событие "mouseB", то текущее значение "stepper" будет последним "образцом" "ползунка" (значение во время последнего вхождения). Если время последнего вхождения прошло, то мы в итоге будем оценивать "ползунок", используя прошедшее время, которое нарушает установленное выше правило (и ваше исходное предположение). Я вижу несколько способов решить эту проблему:
- Мы "записываем" прошлое (сохраняем все прошлые события в событии), позволяя оценивать поведение с прошедшими временами (используя неограниченный объем памяти)
- Мы модифицируем "снимок", чтобы принять аргумент времени ("образец после этого времени") и принудительно установить, что это время>= сейчас
- В более дурацком движении мы могли бы как-то ограничить создание объектов FRP первоначальной настройкой программы и начинать обрабатывать события / ввод только после завершения этой настройки.
Я также мог бы просто не реализовывать "sample" или удалять "stepper" / "switcher" (но я действительно не хочу делать ни одну из этих вещей). У кого-нибудь есть мысли по этому поводу? Я что-то здесь неправильно понял?
3 ответа
О, я понимаю, что ты имеешь в виду сейчас.
Я полагаю, что ваше ограничение "Вы можете выбирать только сейчас" недостаточно жесткое. Это должно быть немного сильнее, чтобы не заглядывать в прошлое. Поскольку вы используете экологическую концепцию now
Я бы определил функции построения поведения в терминах этого (до тех пор, пока now
не может продвинуться простым исполнением определений, которое, согласно моему последнему ответу, стало бы грязным). Например:
Stepper(i,e)
это поведение со значениемi
в промежутке[now,e1]
(гдеe1
время первого появленияe
послеnow
), а также значение самого последнего появленияe
после этого.
С этой семантикой ваш прогноз о значении stepper
то, что привело вас в эту головоломку, демонтировано, и степпер теперь будет иметь значение 0. Я не знаю, желательна ли вам эта семантика, но она кажется мне достаточно естественной.
Из того, что я могу сказать, вы беспокоитесь о состоянии гонки: что произойдет, если событие произойдет во время выполнения кода.
Чисто функциональный код не любит знать, что он исполняется. Функциональные приемы являются лучшими в чистом виде, так что не имеет значения, в каком коде заказа выполняется. Выход из этой дилеммы - сделать вид, что каждое изменение произошло в одном чувствительном (внутреннем, вероятно) фрагменте императивного кода; притвориться, что любые функциональные объявления в структуре FRP происходят за 0 раз, поэтому невозможно что-то изменить во время их объявления.
Никто не должен спать или делать что-то чувствительное ко времени в разделе кода, который объявляет поведение и вещи. По сути, код, который работает с объектами FRP, должен быть чистым, тогда у вас нет проблем.
Это не обязательно исключает запуск его в нескольких потоках, но для поддержки этого вам может понадобиться реорганизовать ваши внутренние представления. Добро пожаловать в мир внедрения библиотеки FRP - я подозреваю, что ваше внутреннее представительство будет колебаться много раз в течение этого процесса.:-)
Я запутался из-за твоего замешательства. Я вижу, что Stepper
будет "устанавливать" поведение на новое значение всякий раз, когда происходит событие. Итак, что происходит, это следующее:
Момент, в который произошло событие
mouseB
происходит, значениеslider
поведение будет прочитано (snapshot
). Это значение будет "установлено" в поведенииstepper
,
Таким образом, это правда, что Stepper
будет "запоминать" ценности из прошлого; Дело в том, что он запоминает только последнюю ценность из прошлого, а не все.
Семантически лучше всего моделировать Stepper
как функция, которую предлагает Луки.