This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-05-14
Channels
- # announcements (13)
- # aws (2)
- # babashka (17)
- # beginners (80)
- # biff (10)
- # cljs-dev (51)
- # cljsrn (6)
- # clojure (42)
- # clojure-australia (9)
- # clojure-boston (2)
- # clojure-europe (17)
- # clojure-sweden (3)
- # clojure-uk (53)
- # clojurescript (44)
- # code-reviews (2)
- # core-async (5)
- # cryogen (3)
- # cursive (32)
- # datahike (1)
- # datomic (11)
- # events (1)
- # fulcro (22)
- # helix (3)
- # honeysql (3)
- # leiningen (4)
- # lsp (30)
- # luminus (13)
- # malli (5)
- # off-topic (115)
- # other-languages (5)
- # pathom (10)
- # polylith (23)
- # re-frame (24)
- # reagent (10)
- # releases (2)
- # shadow-cljs (124)
Can anyone recommend a simple way to evalue a user generated expression within my CLJS app (e.g. eval but sandboxed). An interpreter is fine really - not super worried about performance. I see references to cljs.js
and also borkdude/sci
which sound like candidates. Not familiar with pros/cons of different approaches.
Use case is to allow user configured behaviour of single page webapp without recompiling frontend. (e.g. setting component properties based on simple formula)
if the language is very restricted I would probably just consider writing your own interpreter
@olivergeorge yes, that is one of the use cases of sci. It’s also used by Chlorine/Clover for configuration
Thanks guys
How do I use react from cljs? I'd like to use react/useEffect
, but importing react with ["react" :as react] ;; shadow-cljs
gives me this error in the developer console:
env.cljs:198 error when calling lifecycle function mount-components Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
I'm guessing the reason is point 3 here since I am likely importing react
a second time.
The code example I am trying to get to work is taken from https://juxt.pro/blog/react-hooks-raw#_side_effects (but using js/React.useEffect
like in that example did not work).@endrebak85 how are you rendering the function component that calls useEffect
?
I am rendering it in hiccup like this: [render-function-from-example]
.
I am using reagent in my code, yes 🙂
Understood, thanks.
those get turned into classes. and the warning "Hooks can only be called inside of the body of a function component" speaks right at that
here's how to use React hooks in reagent: https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md#hooks
if you're using reagent 1.0 or above, you can render your component like:
[:f> render-function-from-example]
Thanks, now it works :)
I was advised to use useEffect
to be able to update DOM elements with D3 graphs after the DOM elements had rendered. I think I am close, but that I am making a mistake here:
(defn graph-page []
(let [[graph set-graph]
(react/useState ;; the state is a dagre graph
(-> (dagre/graphlib.Graph.)
(.setGraph (clj->js {}))
(.setDefaultEdgeLabel (fn [] {}))
(.setNode "hi" (clj->js {:label "hi" :width 144 :height 100}))
(.setNode "ciao" (clj->js {:label "ciao" :width 144 :height 100}))
(.setEdge "hi" "ciao")))
render-graph (fn [graph] ;; this renders the graph with dagre-d3
(js/console.log "render-graph is executed!")
(let [renderer (dagre-d3/render)
svg (d3/select "svg")
inner (-> svg
(.append "g"))
_ (renderer inner graph)]))]
[:div
[:svg]
[:button {:on-click #(set-graph (render-graph %))} "Graph!"]]))
Is this correct? Clicking the button just adds an empty <g></g>
to the DOM (from render-graph
). I am wondering whether the error is in my use of hooks, or my use of the dagre-d3 library (proper JS-usage of the code I am trying to write use in Clojurescript is https://dagrejs.github.io/project/dagre-d3/latest/demo/sentence-tokenization.html).
One potential problem with my code is that graph
is not something that should be included in the hiccup, but it the graph that should be rendered.With [:button {:on-click #(set-graph (render-graph graph))} "Graph!"]
it renders.
(render-graph %)
would pass the button event to the render-graph
fn which doesn't seem right
But is not my code equivalent to the one from the reagent example?
(defn example []
(let [[count set-count] (react/useState 0)]
[:div
[:p "You clicked " count " times"]
[:button
{:on-click #(set-count inc)}
"Click"]]))
[:button {:on-click #(set-graph (render-graph %))} "Graph!"]
expand this to:
[:button {:on-click (fn [button-event]
(render-graph button-event))} "Graph!"]
Ah, I see. Thanks for your patience.
A most trivial item of trivia, but: I was rather surprised to find that defprotocol
evaluates to false
. I had a quick look at the GitHub docs and the last line of the defprotocol
macro is a (set! ~'*unchecked-if* false)
, so I guess that’s it. What should defprotocol
evaluate to?
I didn't see it described anywhere, but FWIW Clojure explicitly returns the symbol for the protocol. So CLJ and CLJS behavior here is different. But if the behavior itself is not described anywhere, then it's probably fine.
I believe most programs completely ignore the value returned from such expressions.
You are welcome to add a question on http://ask.clojure.org about this if it disconcerts you enough. Realize that it may not disconcert the ClojureScript maintainers as it does you. I do not know.
hi, @dnolen https://www.reddit.com/r/Clojure/comments/mcce4h/everything_i_have_learned_i_have_learned_from/ "29:36 - is source code for this available anywhere ?"
funny story I think someone from Apple was there and at least some of that paper ended up in the Swift pattern matcher?
Also funny story: I shared the core.match literature with someone which almost turned into a thing to optimize state machines in Yosys, but I don't think it was ever completed.
Is there a way to tell if we're in the Clojure cljs macroexpansion stage vs just regular Clojure?
Here's my motivation:
I have a log util namespace util.clj
with macros like
(defmacro logp
"Impl for log macros. Log `args` at `level`."
[level & args]
(macros/case
:clj
`(clojure.tools.logging/logp ~level ~@args)
:cljs
`(js-logp ~level ~@args)))
(I'm using https://github.com/cgrand/macrovich here).
When expanding a macro for CLJS compliation, I want js-logp
. When expanding a macro for Clojure (in normal usage), I want clojure.tools.logging
.
My issue is one of may namespaces that gets loaded during the Clojure cljs macroexpansion stage does some logging as a side-effect of being loaded. So during cljs macroexpansion it's expanding the macro as clojure.tools.logging.logp
in Clojure land in order to do the macroexpansion. However, I don't have clojure.tools.logging
as a dependency in that situation, so the macroexpansion is causing my Clojurescript build to fail. (This code is also used elsewhere as a sub-project where clojure.tools.logging
is available.)
I want to do something like
(defmacro logp
"Impl for log macros. Log `args` at `level`."
[level & args]
(when-not *clojurescript-macroexpansion*
(macros/case
:clj
`(clojure.tools.logging/logp ~level ~@args)
:cljs
`(js-logp ~level ~@args))))
and have the macro expand to nil
or some other sort of no-op if we're expanding it while running in Clojure to do ClojureScript macro expansion. Is there some way I can possibly figure out if the code is running in "Clojure for ClojureScript macroexpansion mode"?Found this recently while digging, I think it's what you're after https://github.com/plumatic/schema/blob/master/src/clj/schema/macros.clj#L10