This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-16
Channels
- # announcements (8)
- # aws (28)
- # babashka (26)
- # beginners (125)
- # calva (18)
- # chlorine-clover (2)
- # cider (12)
- # cljs-dev (6)
- # cljsrn (4)
- # clojure (134)
- # clojure-europe (31)
- # clojure-italy (2)
- # clojure-nl (14)
- # clojure-uk (83)
- # clojurescript (81)
- # conjure (4)
- # cursive (2)
- # datomic (145)
- # emacs (13)
- # events (3)
- # figwheel-main (14)
- # fulcro (30)
- # graalvm (23)
- # graphql (15)
- # helix (21)
- # jackdaw (20)
- # juxt (1)
- # lambdaisland (4)
- # leiningen (2)
- # malli (12)
- # meander (22)
- # observability (22)
- # off-topic (27)
- # pedestal (3)
- # re-frame (12)
- # reitit (1)
- # releases (2)
- # rewrite-clj (3)
- # shadow-cljs (67)
- # spacemacs (7)
- # sql (1)
- # tools-deps (19)
- # unrepl (2)
- # xtdb (25)
I have a vector of maps, with a field in it that I want to make the key of a new map with the all the original content. What’s the idiomatic way forward?
good place for using transducers:
(into {}
(map (juxt :yd identity))
data)
still bit lost with dce + closure-defines. would like to make a registry function swappable, so that only one impl gets picked up and the rest get removed under advanced. Could use a string->function cond if I knew all the values in advance, but the users should be able to use their own registry-functions here too. I guess this needs som dynaload
and macros to work?
(ns user)
;; registries drag code from 700b to 200kb, just need one for the app
(defn registry1 [] 1)
(defn registry2 [] 2)
;; user-defined name of the registry to be used
(goog-define type "user.registry2")
;; just taking one, dce removes the others, how to do this?
(def registry (some-> type symbol requiring-resolve (apply nil)))
@ikitommi requiring-resolve
doesn't exist. the only option you have that is supported by DCE is using strict identical?
checks. for example https://github.com/clojure/clojurescript/blob/799d62fe3bba999287558538ca6b61501de02d49/src/main/cljs/cljs/core.cljs#L11747-L11753
that won't work with user registry functions of course since it must be completely static
so a consumer does
(ns
(:require
[your.registry.api :as reg]
[your.regsitry.variant1]
))
or if they want to able to swap it out more dynamically you can require it via the :entries
in the build config in shadow-cljs. dunno how to do it in regular CLJS though given that :main
only accepts a single symbol
the variant1
just sets up whatever it has to directly using the api
ns. eg. put things in an atom
but "registry" in general is going to limit what DCE can do given that is most likely can't track which part of the registry you are actually going to use at runtime
dynaload
also doesn't really exist since CLJS can't do that. it requires the user requiring the ns just as described above
I was hoping to get something like this:
(if (identical? type "default")
(default-registry)
...something-like-requiring-resolve-for-type...))
, where the else would be a macro to generate code to require and resolve the type. In my case, this is a default-registry. need to inject that into the library code as it is used in many places. I think either of the two would work:
1. define a boolean to indicate if the normal default registry should be used (if not, dce will remove it) and a programmatic way to once override the default registry via some set-default-registry!
fn
2. just not have any default registry in cljs, one needs to always call set-default-registry!
before use, could be in preloads
was hoping a more declarative way for this, e.g. one :closure-defines
definition…2 would be something like:
(require '[malli.core :as m])
;; always needed in cljs to get dce
(m/set-default-registry! (m/default-registry))
(m/validate [:map [:x int?] [:y int?]] {:x 1, :y 2})
; => true
(m/set-default-registry! (m/default-registry))
; => Exception, no mutable state here
I always recommend all apps to have the generic init/start/stop lifecycle anyways https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html
so that gives the user a chance to either init whatever registry they want in init or start
initializing things in the ns automatically often creates problems with DCE if not done very carefully
even the default registry setup means that the default registry is never removed if you put it into an atom or so
thanks. a lot to think about. but good to know the dynamic resolve + dce won’t work. spent half a day trying to make it work, via JCM System Properties and all 🙂
not so much a CLJS problem but rather that the JS platform just doesn't allow it because of async IO
but IMHO if you move each registry into its own ns and have it self-register on load is probably best
its just not possible to do any kind of dynamic resolve. this would require doing async IO since we can't block to wait for the load result.
Hi! I’m considering Clojure/Clojurescript for a project. (Don’t have a lot of experience with it yet!) I need to create a library that has to run on both our backend (java/kotlin) and in the browser. Is it possible to compile the source to both JavaScript and a JAR? And are there other things to consider or are there any pitfalls?
with cljc
files you can provide conditional expressions that evaluate differently per back-end, they can be compiled by both the regular clojure compiler and the cljs compiler
the conditionals are used for things that defer between clj / cljs
Clojure and ClojureScript are especially well suited for this. Most pitfalls I’ve been hitting has had to do with me not knowing the host platforms well enough. Both Clojure and ClojureScript run pretty close to the iron, so to speak. 😃
I’ll probably only need the standard lib (mainly graph traversal etc) so that should be fine 😄 If I create a JS package from a ClojureScript library I’m assuming this also contains the standard library. Does the Closure compiler also dead-code-eliminate the unused parts of the stdlib?
I do believe it will if you use advanced compilation
awesome! Now a final question: is there a good leiningen template to get started with or should I just craete a new leiningen project and add clsjbuild?
I am not sure what the current best lein template for clojurescript is, and I think a lot of the community there has moved to deps.edn
So deps.edn does not work with leiningen?
it's an alternative dep management system, there's at least one lein plugin to use deps.edn to manage deps inside leiningen though
while lein tries to be a build tool, and a host for plugins for all clojure dev tasks, deps.edn only does dep management
I’m still a n00b so for me i’m fine with whatever, just whichever is easiest or has the most learning materials around it 😄
I think lein still has more documentation / ease of access. Just be aware that if you are looking for the "latest" or "best" version of something, deps.edn will come up
thats good to know. I’m mostly concerned about the build tool as for the specific project I won’t need other dependencies other than maybe a test runner
Hi I'm using shadow-cljs and I try to use a plain JS file. I don't get it right and try to understand why.
I added the path "src/js" in the :source-paths
of my shadow-cljs.edn file. In my src/main/simulation/core.cljs file, I have this header:
(ns simulation.core
(:require
[...]
["/d3/gravity" :as gravity]
))
I don't get the import error from the compiler so I guess the require statement works.
In my src/js/d3/gravity.js file, I have just one function toto
:
export default function toto() {
console.log("INSIDE TOTO");
}
I cannot call toto
from my simulation/core.cljs with this error message:
> Failed to load simulation/core.cljs TypeError: module$d3$gravity.toto is not a function
What is the right syntax for the function toto
please?
@thheller, if you're there, you're certainly the right one to ask ^^@fabien.rozar either ["/d3/gravity" :as gravity :default whatever]
with whatever
being the defaulft
toto fn. or export function toto() { ...}
and gravity/toto
@thheller, nice thank you.
The ["/d3/gravity" :as gravity]
and export function toto() {...}
and the call (gravity/toto)
works fine for me.
You're always there, amazing
hi! what is the current way of using core.async in a cljc file? Trying
(ns mount.core
#?(:clj (:require [cljs.core.async :refer [<! chan go]]
...)
:cljs (:require [cljs.core.async :refer [<! chan go]]
...)))
and compiling with the latest cljsbuild fails with clojure.lang.Compiler$CompilerException: java.lang.IllegalAccessError: <! does not exist, compiling:(mount/core.cljc:1:1)
Any ideas?@jpmonettas I think that the :clj
branch should be (:require [clore.core.async :refer [<! chan go]] ...)
@lilactown I tried some of those also, doing that it fails with : clojure.lang.ExceptionInfo: No such namespace: cljs.core.async.impl.protocols {:ns cljs.core.async.impl.protocols, :form cljs.core.async.impl.protocols/ReadPort, :file "mount/core.cljc" :column 23, :line 81}, compiling:(mount/core.cljc:79:3)
oh wait
I have a typo
@lilactown hey that worked, thanks a lot! I think I tried the :refer-macros for cljs instead of the :include-macros and wasn't compiling
yeah, but shouldn't it also work?
Is it possible to do something like (var-get #'my.ns/my-var)
in Clojurescript?
iirc cljs doesn't have vars at runtime(?)
Maybe there’s a dirty way to do it? The function must be represented somehow in the global interpretation context 🙂
(referrable, I mean)
dev-local:cljs.user=> (def x "made it!")
#'cljs.user/x
dev-local:cljs.user=> (let [x 'cljs.user/x]
@(resolve 'cljs.user/x))
"made it!"
Seems to work!Ah, but I can’t assign 'cljs.user/x
to a different symbol, and then expect this to work. Dang.
@jpmonettas just [clojure.core.async :refer [<! chan go]]
is fine for both. no need for conditionals.
yes it should also work. but no need for it. and cljs rewrites it like @thheller put there
@reefersleep no, not possible.
Thanks 🙂
it is also working with refer-macros so nvm, @thheller the conditionals are there for other requires
anyway it is working now, thx!
Hello I am trying to integrate with a library and need to simulate classes in CLJS. I am using prototype extension to simulate them. But I have a very weird issue which is blocking me. Consider this minimum setup:
(defn class-one [])
(defn class-two []
(this-as this
(set! (.-some-property this) (new class-one))))
Guess what is the result of (instance? class-two (new class-two))
, it is false
and (instance? class-one (new class-two))
is true
any explanations for this behaviour?
But if (set! (.-some-property this) (new class-one))
is something like (set! (.-some-property this) <something other than another class i.e. function>)
then things work as expected
with-redefs?