2
votes

Consider the following snippet:

(require '[clojure.core.async :refer :all])


(def my-chan (chan (buffer 10)))

(go (while true
      (>! my-chan (rand))))

This basically provides a buffered channel, which always contains some 10 random numbers. When the channel is consumed, the buffer is filled again.

Is there an abstraction for this in core.async? As there are transducers for manipulating the consumption of channels, there might be something for the production of them as well:

For sequences one would go for something like this:

(def my-seq 
  (map (fn [_] (rand)) (range)))

or, just:

(def my-seq (repeatedly rand))

Which of course is not buffered, but it might give an idea of what I'm looking for.

1
I'm not really sure what you're looking for here.....? - Alan Thompson

1 Answers

0
votes

Transducers don't manipulate the consumption of channels -- they affect the values, but they don't affect the consumption of the data on the channel.

You seem to be asking of a way to abstract the creation of a channel, and then get values off of it as a sequence. Here are some ideas, though I'm not convinced that core.async really offers anything above normal clojure.core functionality in this case.

Abstraction is done here the way it usually is done -- with functions. This will call f and put its result on the channel. The implication here is of course that f will be side-effecting, and impure, otherwise it would be quite a boring channel to consume from, with every value being identical.

(defn chan-factory
  [f buf]
  (let [c (chan buf)]
    (go-loop []
      (>! c (f))
      (recur))
    c))

If you then wanted to create a lazy sequence from this, you could do:

(defn chan-to-seq [c]
  (lazy-seq
    (cons (<!! c) (chan-to-seq c))))

Define your seq:

(def rand-from-chan (chan-to-seq (chan-factory rand 10)))

(take 5 rand-from-chan)
=>
(0.6873518531956767
 0.6940302424998631
 0.07293052906941855
 0.7264083273536271
 0.4670275072317531)

However, you can accomplish this same thing by doing:

(def rand-nums (repeatedly rand))

So, while what you're doing is a great thought experiment, it may be more helpful to find some concrete use cases, and then maybe you will receive more specific ideas. Good luck!