hyperfiddle/electric

cannot access Clojure dynamic from electric body ("not a reactive var: clojure.core/*print-length*")

philoskim opened this issue · 3 comments

ExceptionInfo: Unable to resolve symbol: monitor-enter

(ns user.my-macro)
(defmacro my-macro1 [a]
  `(locking (Object.)
     (+ ~a 10)))

(ns user.demo-two-clocks
  (:require [hyperfiddle.electric :as e]
            [hyperfiddle.electric-dom2 :as dom]
            #?(:clj [user.my-macro :as mm])))

(e/defn TwoClocks []
  (e/client
    (dom/h1 (dom/text "Two Clocks — Electric Clojure"))
    (let [c (e/client e/system-time-ms)
          s (e/server (mm/my-macro1 100)                                ;; <== Here
                      e/system-time-ms)]
      (dom/div (dom/text "client time: " c))
      (dom/div (dom/text "server time: " s))
      (dom/div (dom/text "latency: " (- s c))))))

[:dev] Compiling ...
DEBUG hyperfiddle.electric.impl.env: reloading user.demo-two-clocks
[:dev] Build failure:
------ ERROR -------------------------------------------------------------------
 File: /Users/philos/src/electric/src-dev/user.cljs:7:20
--------------------------------------------------------------------------------
   4 |             hyperfiddle.rcf
   5 |             user-main))
   6 |
   7 | (def electric-main (hyperfiddle.electric/boot (user-main/Main.)))
--------------------------^-----------------------------------------------------
Encountered error when macroexpanding hyperfiddle.electric/boot.
Unable to resolve symbol: monitor-enter
{:file "user/demo_two_clocks.cljc", :in [monitor-enter]}
ExceptionInfo: Unable to resolve symbol: monitor-enter
	hyperfiddle.electric.impl.compiler/analyze-form (compiler.clj:643) 
...

not a reactive var: clojure.core/*print-length*

(defmacro my-macro2 [a]
  `(binding [clojure.core/*print-length* 50]
     (+ ~a 20)))

(ns user.demo-two-clocks
  (:require [hyperfiddle.electric :as e]
            [hyperfiddle.electric-dom2 :as dom]
            #?(:clj [user.my-macro :as mm])))

(e/defn TwoClocks []
  (e/client
    (dom/h1 (dom/text "Two Clocks — Electric Clojure"))
    (let [c (e/client e/system-time-ms)
          s (e/server (mm/my-macro2 100)                                          ;; <== Here
                      e/system-time-ms)]
      (dom/div (dom/text "client time: " c))
      (dom/div (dom/text "server time: " s))
      (dom/div (dom/text "latency: " (- s c))))))

[:dev] Compiling ...
DEBUG hyperfiddle.electric.impl.env: reloading user.demo-two-clocks
[:dev] Build failure:
------ ERROR -------------------------------------------------------------------
 File: /Users/philos/src/electric/src-dev/user.cljs:7:20
--------------------------------------------------------------------------------
   4 |             hyperfiddle.rcf
   5 |             user-main))
   6 |
   7 | (def electric-main (hyperfiddle.electric/boot (user-main/Main.)))
--------------------------^-----------------------------------------------------
Encountered error when macroexpanding hyperfiddle.electric/boot.
Not a reactive var: clojure.core/*print-length*
{:in [(clojure.core/binding [clojure.core/*print-length* 50] (clojure.core/+ 100 20))]}
ExceptionInfo: Not a reactive var: clojure.core/*print-length*
	hyperfiddle.electric.impl.compiler/analyze-form (compiler.clj:643) 
...

Missing #?(:cljs (:require-macros [app.my-macro :as mm]))

However once you fix the require-macros, you will then get Unable to resolve symbol: monitor-enter (emitted by the clojure.core/locking macro) which is a clojure special form that we do not currently support. I've opened a ticket for it to explore if it makes sense to support it.

as a workaround, you can move the locking macro into a regular Clojure body, by wrapping it like this:

(e/defn Todo-list []
  (e/client
   (let [s (e/server ((fn [] (mm/my-macro1 100))) e/system-time-ms)]
       ...)))

Clojure function bodies (even inside Electric exprs) follow Clojure rules and evaluate in an ordinary Clojure evaluation context.

You can also just extract an ordinary clojure.core/defn and call it from Electric.

Regarding Not a reactive var: clojure.core/*print-length* – 

  • Electric's interop with Clojure bindings is not finished, I will write some documentation about this to explain the current rules, the future expected behavior, what is and isn't expected to work and why, and how to workaround any missing functionality.
  • the workaround is the same - put this call in a Clojure function body