Skip to content

Conversation

@ojw
Copy link
Contributor

@ojw ojw commented Dec 4, 2024

Looks like the list? case in awalk is missing an outer <!.

Alternately, there's a case to do a bit more refactoring and pull the <! (and optionally even the <outer) out of the cond, which would also fix this.

For example, something like

(go
  (<! 
    (<outer
      (cond ...))))

I'm happy to write it up either way if you like, or of course you're welcome to close this and fix it in the style of your choosing.

@jtkDvlp
Copy link
Owner

jtkDvlp commented Feb 5, 2025

hey @ojw,

I sry for the late response, I will take a look and reply soon.

Thanks for your work.

@jtkDvlp jtkDvlp merged commit 9dfe27f into jtkDvlp:master Feb 5, 2025
@jtkDvlp
Copy link
Owner

jtkDvlp commented Feb 5, 2025

Approved and merged, thank you for your work.

@jtkDvlp jtkDvlp added the bug Something isn't working label Feb 5, 2025
@ojw
Copy link
Contributor Author

ojw commented Feb 6, 2025

For what it's worth, I later abandoned this approach to an async postwalk. The problem is that empty collections lead to nils put on channels, and that signals termination in core.async. So I rewrote this using promises instead to get an async postwalk, and that has worked fine for me. As far as I can tell, for cases where there might be empty collections, this approach using channels just doesn't work.

I'm now using something like:

(defn promise-walk
  "`clojure.walk/walk, but inner and outer return promises."
  [inner outer form]
  (cond
    (list? form)
    (-> (map inner form)
        js/Promise.all
        (.then #(apply list %))
        (.then outer))

    (map-entry? form)
    (let [kp (inner (key form))
          vp (inner (val form))]
      (-> (js/Promise.all [kp vp])
          (.then (fn [[k v]] (MapEntry. k v nil)))
          (.then outer)))

    (seq? form)
    (-> (map inner form)
        js/Promise.all
        (.then outer))

    (record? form)
    (-> (reduce (fn [rp x]
                  (let [ip (inner x)]
                    (-> (js/Promise.all [rp ip])
                        (.then (fn [[r i]]
                                 (conj r i))))))
                form form)
        (.then outer))

    (coll? form)
    (-> (map inner form)
        js/Promise.all
        (.then #(into (empty form) %))
        (.then outer))

    :else
    (outer form)))

For me, dealing with promises is convenient, but this could always be adapted by converting to/from promises/channels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants