Исправление Ritmik, (текущая версия) :
И что такое «параллельная итерация»?
Это я перепутал - наоборот последовательная, как в твоём втором примере с doseq, но параллельная, когда «параллельно» осуществляется проход по нескольким коллекциям, тоже бывает нужна (в хаскеле называется zipWith).
А этот zipWith тоже может работать с побочными эффектами?
Вот твой код
Это всё разные варианты. Нужно взять что-то одно - например класс DoSeq и его инстансы. Как выглядят эти инстансы - не интересно, понятно что последовательный doseq для нескольких коллекций будет работать как вложенные циклы - и в clojure (в реализации doseq), и в haskell (там где у меня forM_ от forM_).
Кажется мы подошли к кульминации треда. Расширь свою реализацию foreach-а на хаскеле, чтобы он принимал произвольное количество параметров. У тебя реализовано сейчас для двух параметров, а нужно для произвольного числа.
Например, на clojure можно написать такой вариант для proof of concept (мой утрированный вариант, чисто для показа возможности)
(defmacro foreach [binds & body]
(letfn [(make-loop [binds]
(if (empty? binds)
(cons 'do body)
`(loop [col# ~(second (first binds))]
(when-not (empty? col#)
(let [~(ffirst binds) (first col#)]
~(make-loop (rest binds)))
(recur (rest col#))))))]
(make-loop (partition 2 binds))))
;; test
(foreach [a [1 2]
b [:a :b]
c ['x 'y]]
(println a ", " b ", " c))
=> 1 , :a , x
1 , :a , y
1 , :b , x
1 , :b , y
2 , :a , x
2 , :a , y
2 , :b , x
2 , :b , y
Вот и посмотрим как твое «ма, смотри, все на чистом ФВП» будет выглядеть здесь.
Ты еще приплел сюда монады и получил в конечном итоге не функции.
То что forM_ и прочие используют монадический интерфейс никак не делает их «не функциями» - они тоже обычные функции.
И поэтому для работы с ними придумали свою реализацию for, map и прочее? Не смеши меня. Ты не можешь работать с ними как с обычными функциями, т.к. результат и параметр должны быть «M _тип_».
Хосспади, какое убожество.
Это ещё что, вот если ещё log доставать из reader и писать в ReaderT IO.
Хех.
непонятное тело foreach-а
Ну там же free variable в body - wtf?
Какие free vaiables? Они забиндены в шапке. Если будет несвязанный символ, то компилятор ругнется. Так что опять мимо.
Странно, но на моей машине
Нужно тестировать оба варианта (clojure и ghc -O2) и делить.
Нафиг тестировать, мне и так все понятно. Я за то, чтобы структуры данных и алгоритмы выбирать в зависимости от задачи. Уже писал. Если нужен перформанс на больших объемах с императивными алгоритмами, то нужно писать императивно и возможно на низком уровне (джава, с++, etc).
Исходная версия Ritmik, :
И что такое «параллельная итерация»?
Это я перепутал - наоборот последовательная, как в твоём втором примере с doseq, но параллельная, когда «параллельно» осуществляется проход по нескольким коллекциям, тоже бывает нужна (в хаскеле называется zipWith).
А этот zipWith тоже может работать с побочными эффектами?
Вот твой код
Это всё разные варианты. Нужно взять что-то одно - например класс DoSeq и его инстансы. Как выглядят эти инстансы - не интересно, понятно что последовательный doseq для нескольких коллекций будет работать как вложенные циклы - и в clojure (в реализации doseq), и в haskell (там где у меня forM_ от forM_).
Кажется мы подошли к кульминации треда. Расширь свою реализацию foreach-а на хаскеле, чтобы он принимал произвольное количество параметров. У тебя реализовано сейчас для двух параметров, а нужно для произвольного числа.
Например, на clojure можно написать такой вариант для proof of concept (мой утрированный вариант, чисто для показа возможности)
(defmacro foreach [binds & body]
(letfn [(make-loop [binds]
(if (empty? binds)
(cons 'do body)
`(loop [col# ~(second (first binds))]
(when-not (empty? col#)
(let [~(ffirst binds) (first col#)]
~(make-loop (rest binds)))
(recur (rest col#))))))]
(make-loop (partition 2 binds))))
;; test
(foreach [a [1 2]
b [:a :b]
c ['x 'y]]
(println a ", " b ", " c))
=> 1 , :a , x
1 , :a , y
1 , :b , x
1 , :b , y
2 , :a , x
2 , :a , y
2 , :b , x
2 , :b , y
Вот и посмотрим как твое «ма, смотри, все на чистом ФВП» будет выглядеть здесь?
Ты еще приплел сюда монады и получил в конечном итоге не функции.
То что forM_ и прочие используют монадический интерфейс никак не делает их «не функциями» - они тоже обычные функции.
И поэтому для работы с ними придумали свою реализацию for, map и прочее? Не смеши меня. Ты не можешь работать с ними как с обычными функциями, т.к. результат и параметр должны быть «M _тип_».
Хосспади, какое убожество.
Это ещё что, вот если ещё log доставать из reader и писать в ReaderT IO.
Хех.
непонятное тело foreach-а
Ну там же free variable в body - wtf?
Какие free vaiables? Они забиндены в шапке. Если будет несвязанный символ, то компилятор ругнется. Так что опять мимо.
Странно, но на моей машине
Нужно тестировать оба варианта (clojure и ghc -O2) и делить.
Нафиг тестировать, мне и так все понятно. Я за то, чтобы структуры данных и алгоритмы выбирать в зависимости от задачи. Уже писал. Если нужен перформанс на больших объемах с императивными алгоритмами, то нужно писать императивно и возможно на низком уровне (джава, с++, etc).