Humm... actually, I was happy too soon...
Ends up this following example doesn't work:
(let [value-chan (fn [v] (let [c (chan 1)] ; simple helper to simulate an
async operation that just returns the input
(go
(>! c v)
(close! c))
c))
xform (comp (async filter value-chan) ; can be used
) ; now filter sync
c (chan 1 xform)]
(async/onto-chan c [1 false 2 3])
(go
(println (<! (async/into [] c))))) ; got an empty list instead of [1 2
3]
It seems that it only works if the channel had the value before the
transducer call the `take!`, seems that unless it has the value immediately
available, it doesn't works...
---
Wilker Lúcio
http://about.me/wilkerlucio/bio
Woboinc Consultant
+55 81 82556600
On Mon, Sep 22, 2014 at 12:00 AM, Wilker <[email protected]> wrote:
> Ok, I think a got into a reasonable solution :)
>
> The code first:
>
> (defn -expand [v f]
> (if (satisfies? cljs.core.async.impl.protocols/ReadPort v)
> (take! v f)
> (f v)))
>
> (defn async [t f & args]
> (fn [f1]
> (fn
> ([] (f1))
> ([result] (f1 result))
> ([result input]
> (-expand (f input)
> (fn [v]
> (((apply t (cons identity args)) f1) result v)))))))
>
> (let [value-chan (fn [v] (let [c (chan 1)] ; simple helper to simulate an
> async operation that just returns the input
> (put! c v)
> (close! c)
> c))
> xform (comp (async map value-chan) ; using async!
> (async filter value-chan) ; same thing with filter
> )
> c (chan 1 xform)]
> (async/onto-chan c [1 false 2 3])
> (go
> (println (<! (async/into [] c))))) ; [1 2 3]
>
> Ok, what I did was create a transducer wrapper that relies into the
> wrapped transducer to take a function as the first argument (that's usually
> the function that needs the expanded value) and makes the proper calls for
> it.
>
> It worked great for the most transducers that I needed here, so, I
> consider a solution to my issue :)
>
> Hope it can help others that may got into similar issue.
>
> ---
> Wilker Lúcio
> http://about.me/wilkerlucio/bio
> Woboinc Consultant
> +55 81 82556600
>
> On Sun, Sep 21, 2014 at 11:29 PM, Wilker <[email protected]> wrote:
>
>> Hi, I did some progress here, I was able to manage to create a custom
>> filter transducer that works seamlessly with regular values and channels
>> and can be composed with other transducers:
>>
>> ; on JVM I did this using protocols, but in ClojureScript I could not
>> make it work (some error when I tried to extend the ReadPort type), but
>> this works as same
>> (defn -expand [v f]
>> (if (satisfies? cljs.core.async.impl.protocols/ReadPort v)
>> (take! v f)
>> (f v)))
>>
>> ; my filter transducer that supports async operations
>> (defn filter-ext [pred]
>> (fn [f1]
>> (fn
>> ([] (f1))
>> ([result] (f1 result))
>> ([result input]
>> (-expand (pred input); here is the trick, so in this case I made
>> every operation dependent on a callback, so they can be normalized
>> (fn [v]
>> (if v
>> (f1 result input)
>> result)))))))
>>
>> (let [value-chan (fn [v] (let [c (chan 1)] ; simple helper to simulate an
>> async operation that just returns the input
>> (put! c v)
>> (close! c)
>> c))
>> xform (comp (filter-ext value-chan) ; ok, filter async
>> (filter-ext #(>= % 2))) ; now filter sync
>> c (chan 1 xform)]
>> (async/onto-chan c [1 false 2 3])
>> (go
>> (println (<! (async/into [] c))))) ; prints: [2 3]
>>
>> I could have my extended versions of every transducer to add the support,
>> the code is pretty much the same but has the extra step of checking for the
>> returned value on the operation.
>>
>> Not sure how that could ever be integrated into regular transducers
>> (maybe they could be extended somehow to include this feature selectively
>> to avoid the overhead), but for now this is the best that I could came up
>> with.
>>
>>
>> ---
>> Wilker Lúcio
>> http://about.me/wilkerlucio/bio
>> Woboinc Consultant
>> +55 81 82556600
>>
>> On Sun, Sep 21, 2014 at 10:39 PM, Wilker <[email protected]> wrote:
>>
>>>
>>> On Sun, Sep 21, 2014 at 10:08 PM, Sean Corfield <[email protected]>
>>> wrote:
>>>
>>>>
>>> Hi Sean,
>>>
>>> Sorry, I don't really understood your suggestion... But let me try to
>>> make myself more clear of what I'm trying to accomplish:
>>>
>>> First let me say that I have a more Javascript background than Java, and
>>> my issue is more into ClojureScript world
>>>
>>> Javascript has a lot of async issues, specially when you are working on
>>> Node.JS world, every IO operation is async, although they have sync
>>> versions those versions block the world so I need to keep away from then,
>>> so, async callbacks is my only real options here.
>>>
>>> The first thing that I like to do in my async code is to wrap than into
>>> something that I can handle generically, in JS I used to do a lot of
>>> promises code, but now I'm core async, so I think making then "single
>>> channel value" just fits nice, and wrapping that way I can compose very
>>> well.
>>>
>>> Now I'm at this place, I have all those async functions that I wanna use
>>> to process my data, I wanna use those async functions, also regular
>>> functions.
>>>
>>> Before transducers, I've used the David Nolen's reactive helpers (on his
>>> blog source) to do my data processing using those channels, a good example
>>> on how I used to manage complex async pipelines are like this:
>>>
>>> (->> (scan-path "root/path") ; this will produce a channel that will
>>> output every file/dir path recursive from given path
>>> (r/filter-async is-file?) ; this requires async call to filter
>>> (f/filter (match-extension? #{"avi" "mpg"})) ; this will just check
>>> on the name, no async required
>>> (r/map-async read-hash-info) ; another async call, will generate a
>>> hash info from the path
>>> (r/map #(hash-map :hash %)) ; build a map from the value
>>> )
>>>
>>> So, I like how the previous code is build, because I can really just
>>> composed from my simple sync and async functions, but all these use "custom
>>> transducers" you can say...
>>>
>>> Then comes Transducers that can rise the bar on the abstraction level,
>>> so I now can get rid of all those custom transducers, right?
>>>
>>> So, it just would be nice if I could get the same clean way to build my
>>> pipeline like I did before, but with transducers.
>>>
>>> ---
>>> Wilker Lúcio
>>> http://about.me/wilkerlucio/bio
>>> Woboinc Consultant
>>> +55 81 82556600
>>>
>>
>>
>
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.