У меня есть проблема кодирования в Erlang, который является, вероятно, шаблоном общего умысла, но я не могу найти информацию о том, как разрешить его.
У меня есть список L. Я хочу применить функцию f к каждому элементу в L, и иметь его натыкается на все элементы в L одновременно. Каждый вызов к f (Элемент) или успешно выполнится или перестанет работать; в большинстве случаев это перестанет работать, но иногда это будет успешно выполняться для определенного Элемента в L.
Если/когда f (Элемент) успешно выполняется, я хочу возвратить "успех" и завершить все вызовы f для других элементов в L - первый "успех" - все, чем я интересуюсь. С другой стороны, если f (Элемент) перестал работать для каждого элемента в L, то я хочу возвратить "сбой".
Как тривиальный пример, предположите, что L является списком целых чисел и возвратами F {успех}, если элемент в L равняется 3 или {сбою} для какого-либо другого значения. Я хочу найти как можно быстрее, если существуют какие-либо 3 с в L; я не забочусь, сколько 3 с там, просто существует ли по крайней мере один 3 или нет. f мог быть похожим на это:
f(Int) ->
case Int of
3 -> {success};
_ -> {fail}
end.
Как я могу выполнить итерации через список Ints, чтобы узнать, содержит ли список по крайней мере один 3, и возвратитесь как можно быстрее?
Конечно, это - общий шаблон функционального проекта, и я просто не использую правильные критерии поиска в Google...
Прошло много времени с тех пор, как я делал какие-либо erlang, поэтому я не собираюсь пытаться предоставить вам синтаксис, однако erlang и OTP имеют решение, ожидающее вас.
Создать один процесс, представляющий функцию; пусть он перебирает список, порождая столько процессов, сколько вы считаете целесообразным для эффективного выполнения вычислений по элементам.
Свяжите каждый процесс с процессом-функцией и завершите процесс-функцию после того, как он вернет первый результат.
Позвольте erlang / otp очистить остальные процессы.
Есть два разных способа сделать это. Либо напишите свою собственную функцию, которая выполняет итерацию по списку, возвращая true
или false
в зависимости от того, найдет ли она 3:
contains_3([3|_]) -> true;
contains_3([_|T]) -> contains_3(T);
contains_3([]) -> false.
Вторая - использовать уже определенную функцию для выполнения фактических итерация до тех пор, пока тест для элементов списка не станет истинным, и предоставить ему тест. списки: any
возвращает истина
или ложь
в зависимости от того, успешна ли проверка хотя бы для одного элемента:
contains_3(List) -> lists:any(fun (E) -> E =:= 3 end, List).
будет делать то же самое. Что вы выберете, зависит от вас. Второй, вероятно, был бы ближе к шаблону проектирования, но я чувствую, что даже если вы его используете, вы должны иметь представление о том, как он работает внутри. В данном случае это тривиально и очень близко к явному случаю.
Это обычное дело, но я не знаю, можно ли его классифицировать как шаблон проектирования. Он кажется настолько простым и в некотором смысле «тривиальным», что я бы не стал называть его шаблоном проектирования.