Fork me on GitHub
Lone Ranger18:09:06

alright what am I doing wrong here (clojurescript environment)

(ns demo.sidecar
  (:require [cljs.core.async :as a]
            [cljs.core.async.interop :as ai]
            [sci.core :as sci]))

(def ctx (sci/init {:classes {'js goog/global}
                      (sci/create-ns 'cljs.core.async))
                      (sci/create-ns 'cljs.core.async.interop))}}))

 (apply str
        '((ns gogosci.core
            (:require [cljs.core.async :as a]
                      [cljs.core.async.interop :as ai]))
 {:cause #error
          {:data {:column nil,
                  :file nil,
                  :line nil,
                  :phase "analysis",
                  :type :sci/error},
           :message "Could not resolve symbol: a/go"},
    {:column 86,
     :file nil,
     :line 1,
     :message "Could not resolve symbol: a/go",
     :phase "analysis",
         {:val ({:column 86,
                 :file nil,
                 :line 1,
                 :ns #object [sci.lang.Namespace]})}],
     :type :sci/error},
  :message "Could not resolve symbol: a/go"}

Lone Ranger18:09:05

the rest of core.async works, it's just not happy about the channels

Lone Ranger19:09:49

ok think I have a workaround


Are you trying to use core.async with SCI?


in CLJS, I mean?

Lone Ranger20:09:29

I have the most horrible hack


For CLJS, I usually recommend using the platform's promises in combination with promesa There is a configuration here which you can directly use:


The core.async go macro is a bit too complicated for my taste to use in CLJS


but if you got it working, I'm interested :-)

Lone Ranger20:09:50

using promesa would be the right thing. But why would you do the right thing when you could do something horrible like this:

(defmacro make-sci-macro-fn
  "makes a function with multi arrity dispatch and returns it.
   used to make a macro for sci
   expands to:
   (do (defn fn-name 
         ([a] (sym a))
         ([a b] (sym a b))
         ([a ... z] (sym a ... z))
  [fn-name sym]
  (let [fn-name#             `~fn-name
        multi-dispatch-decl# (let [alpha "abcdefghijklmnopqrstuvwxyz"]
                               (loop [n   (dec (count alpha))
                                      res []]
                                 (if (zero? n)
                                   (let [args    (mapv #(symbol (str %)) (drop-last n alpha))
                                         go-form (list* sym args)]
                                     (recur (dec n)
                                            (conj res
                                                  (list args go-form)))))))]

       (def ^:sci/macro ~fn-name# (fn  ~@multi-dispatch-decl#))


could you describe in words what you did there? :)

Lone Ranger20:09:12

It expands to this:

(do (defn ^:sci/macro fn-name 
         ([a] (sym a))
         ([a b] (sym a b))
         ([a ... z] (sym a ... z))
which I used in the sci macro machinery

Lone Ranger20:09:52

So I made a context

(def ctx (sci/init {:classes {'js goog/global}
                       (merge (sci/copy-ns
                               (sci/create-ns 'cljs.core.async))
                              {'go  (make-sci-macro-fn go a/go)})}}))

Lone Ranger20:09:03

then tried it out:

      (def data
          (apply str
                 '((ns gogosci.core
                     (:require [cljs.core.async :as a]))
                   (a/go 1 2 3 4)))))))

Lone Ranger20:09:08

and data resolves to 4

Lone Ranger20:09:45

I'm not gonna pretend it's elegant 😅

Lone Ranger20:09:56

I just don't want to have to write thousands of lines of core.async code to promesa


if it works for you, it's fine :)

Lone Ranger21:09:09

ah sadly this does not actually work

Lone Ranger21:09:28

it breaks down when a/<! gets involved. That's alright, it will be a useful constraint

Lone Ranger22:09:28

yeah promesa was a great recommendation, the switch is rather painless

Lone Ranger23:09:16

that's a lot of work!!


@U04V15CAJ but it should be possible and not hard to get core.async working with sci, right?


might need a lot of copying I guess so more annoying work rather than being complicated, right?


@U5H74UNSF it should be possible, but I don't think it's worth doing so. you need to basically include a CLJS version of tools.analyzer at runtime, etc.

👍 1

just use promises on JS