LINUX.ORG.RU

История изменений

Исправление 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).