сделать последовательность побочных эффектов в Clojure - PullRequest
3 голосов
/ 31 октября 2010

То, что я хочу сделать, похоже на следующее.

(def mystream (stream (range 100)))

(take 3 mystream)
;=> (0 1 2)

(take 3 mystream)
;=> (3 4 5)

(first (drop 1 mystream))
;=> 7

Функция потока делает последовательность побочной, как io stream.
Я думаю, что это почти невозможно. Вот моя попытка.

(defprotocol Stream (first! [this]))

(defn stream [lst]
  (let [alst (atom lst)]
    (reify Stream
       (first! [this]
         (let [[fs] @alst]
           (swap! alst rest)
           fs)))))

(let [mystream (stream (iterate inc 1))]
  (map #(if (string? %) (first! mystream) %)
       [:a "e" "b" :c "i" :f]))
;=> (:a 1 2 :c 3 :f)

К сожалению, этот подход должен реализовывать все функции, которые я буду использовать.

Ответы [ 2 ]

5 голосов
/ 31 октября 2010

Судя по вашему последующему комментарию к Маврикию, вам не нужна мутация, а просто нужно создать новую последовательность с элементами в нужном месте.

Например:

(defn replace-when [pred coll replacements]
  (lazy-seq
    (when (seq coll)
      (if (seq replacements)
        (if (pred (first coll))
          (cons (first replacements) 
                (replace-when pred (rest coll) (rest replacements)))
          (cons (first coll) 
                (replace-when pred (rest coll) replacements)))
        coll))))
user=> (def seq1 [:a :b :c])
#'user/seq1
user=> (def seq2 [:x "i" "u" :y :z "e"])
#'user/seq2
user=> (replace-when string? seq2 seq1) 
(:x :a :b :y :z :c)                                                                                                    
2 голосов
/ 31 октября 2010

Это не будет работать со стандартным взятием и выпадением, но вы можете довольно легко написать свой собственный для работы с изменяемым атомом, например, вы можете сделать что-то вроде этого:

(def mystream (atom (range 100)))

(defn my-take [n stream]
  (let [data @stream
        result (take n data)]
    (reset! stream (drop n data))
    result))  

(my-take 3 mystream)
=> (0 1 2)

(my-take 3 mystream)
=> (3 4 5)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...