Я хотел бы определить предикат, который, принимая в качестве входных данных некоторые предикаты с соответствующими входными данными (они могут быть заданы как ленивая последовательность вызовов), запускает их параллельно и вычисляет логический или из результатов, таким образомчто в тот момент, когда вызов предиката завершается, возвращая true
, все вычисление также завершается (возвращая true
).
Помимо оптимизации времени, это также поможет в некоторых случаях избежать прерывания (некоторыевызовы предикатов не могут прерваться).На самом деле, интерпретируя отсутствие завершения как третье undefined
значение, этот предикат имитирует операцию или в логике Клини К3 (объединение в начальной центрированной алгебре Клини ).
Нечто подобное представлено здесь для семейства Хаскелл.Есть ли (желательно простой) способ сделать это в Clojure?
РЕДАКТИРОВАТЬ : Я решил добавить некоторые пояснения после прочтения комментариев.
(a) Сначалавсе, что происходит после исчерпания пула потоков, имеет меньшее значение.Я думаю, что создание пула потоков, достаточно большого для наших нужд, является разумным соглашением.
(b) Наиболее важным требованием является то, чтобы вызовы предикатов начинались параллельно и после завершения вызова предиката возвращали true
,все остальные работающие потоки прерываются.Предполагаемое поведение таково:
- , если есть вызов предиката, возвращающий
true
: параллель или возвращает true
- иначе, если есть вызов предиката, который не завершается: параллель или не заканчивается
- иначе: параллель или возвращает
false
Другими словами, он ведет себя как объединение в 3-элементной решетке, заданной false
<<code>undefined <<code>true, где undefined
представляет не окончание.
(c) Параллель или должна быть в состоянии принять в качестве входных данных много предикатов и много входных предикатов (каждый из которых соответствуетпредикат).Но было бы еще лучше, если бы в качестве входных данных использовалась ленивая последовательность.Затем, назвав параллель или pany
(для «параллельного любого»), мы могли бы иметь такие вызовы, как:
(pany (map (comp eval list) predicates inputs))
(pany (map (comp eval list) predicates (repeat input)))
(pany (map (comp eval list) (repeat predicate) inputs))
, что эквивалентно (pany (map predicate (unchunk inputs)))
В качестве последнего замечания я думаю, что вполне естественно просить такие вещи, как pany
, двойной pall
или механизмдля того, чтобы такие параллельные сокращения с ранним завершением могли быть легко реализованы или даже встроены в язык, ориентированный на параллелизм, такой как Clojure.