Fork me on GitHub
Richard Bowen00:02:35

With Reagent, say one has a large number of props which al have a default value, how would that translate to ClojureScript? Would they just be function parameters initialized with a default value?


assuming reagent? if so yes


Specifically it can be helpful to take those function parameters as a map - that gives you a place to put defaults


{:keys [a b c]
 :or {a 1
      b "awdawd"
      c 3}}

👍 1
Richard Bowen02:02:50

@U3JH98J4R for the map is it a 1 or :a 1?

James Amberger01:02:31

I have a question about state management. It seems to me that a tree or map of atoms, e.g (atom {:west-office {:sales-calls (atom []) :salespersons (atom [])} :east-office {..etc}}makes sense as then top-level keys can be added dynamically, and your west-office etc components can be made to update only when those atoms change. Is this viable/intelligent/common?


not really - you should just have a singular top level atom


the way atoms work is via CAS, which doesn't really make sense if any of the contents stored and updated within are mutable


if you want a nested view into an atom, reagent in particular provides cursors


compare and swap


its not super important in the context of cljs actually - i don't even think its the mechanism there so maybe ignore me on that


And when you start using a global atom, it might be a good time to check out re-frame. ;)

James Amberger15:02:46

Ok. I’ve been poring over re-frame. It looks cool. But going over it I feel this question nagging at me: how far off is this from cljs-flavored react/redux ?


Last time I had to deal with redux was ages ago and in someone else's project so I might be wrong. But it's not that far off. Both are a way to organize your data into a global storage, both are done in a similar model where you trigger events and receive data changes. It's likely that there are significant differences, but I'm not in a position to tell.


I'm starting to use re-frame as a SPA framework and am having issues getting a small example running. There doesn't seem to be a re-frame channel on this Slack. Is this the proper place to ask questions, or is there somewhere more appropriate for this discussion?


There is one: #re-frame


That's odd - I searched specifically for that in the channel list and it didn't seem to find anything. I'll try again.


That's really odd. Now I see it there.



👍 1

I’ve got a question about some differences I am seeing between macros in clojurescript vs clojure. First, this is a bit of an odd case where I am defining a macro inside of a macro. The background for this is that I am migrating a .clj namespace to .cljc . The original clj code is a wrapper for defrecord which both creates the record and creates another macro which enforces some compile time restrictions on creation of the record for performance reasons. I am seeing a case where the inner macro used in clojuresript appears to gobble the first two arguments passed to it. The same code works fine in clojure, and if I use a defn instead of a defmacro as the inner “create record” operation, it works as expected in clojurescript. Given that it appears to be possible to have a defmacro inside a defmacro for cljs (I wasn’t sure initially), and that some of the arguments make it as expected, I’m confused where the other two arguments are going. Code example in the thread.


macro definition:

   (defmacro myrecord
     [record-name fields]
     (let [record-name (symbol (str "custom-record-" record-name))
           macro-maker-name (symbol (str "macro-make-" record-name))
           fn-maker-name (symbol (str "fn-make-" record-name))]
          (defrecord ~record-name ~fields)
          (defmacro ~macro-maker-name
            [& key-values#]
            ;; compile-time validation elided here
            `[:args '~key-values#])
          ;; this following fn is for comparison, not part of the original solution
          (defn ~fn-maker-name
            [& key-values#]
            [:args key-values#])))))
When I call this from clojure, we can see that all the args are passed through:
=> (myrecord clj [a b])

=> (macro-make-custom-record-clj :a 2 :b 5)
[:args (:a 2 :b 5)]

=> (fn-make-custom-record-clj :a 2 :b 5)
[:args (:a 2 :b 5)]
When I call it from clojurescript (via a test, using olical/cljs-test-runner, if that is important), we can see that the macro version appears to gobble the first two arguments:
(myrecord cljs [a b])

(deftest mytest
  (println (macro-make-custom-record-cljs :a 1 :b 2))
  (println (fn-make-custom-record-cljs :a 1 :b 2)))

-- (output) ---
[:args (quote (:b 2))]
[:args (:a 1 :b 2)]
Notice that the :a 1 appears to get gobbled up somehow in the macro-make-custom-record-cljs version, but not the fn-make-custom-record-cljs version. Is this expected?


My guess is that it has something to do with the implicit &form and &env macro arguments, although no idea why CLJS behaves differently here. Seems to be relevant:

Mícheál Ó Catháin18:02:50

Is there a basic tutorial describing how to include a google closure compatible javascript in a clojurescript project? I have read whatever I can find (e.g., and think I understand the principles. I have saved (what I believe is!) a closure compatible js file mylib.js (with header goog.provide('ab')) in my project's src/js directory, and include :libs "src/js/mylib.js" in my dev.cljs.edn file. I get no errors on the repl, until I try to call functions from the ab namespace from my main cljs file. The following error is thrown: #object[ReferenceError ReferenceError: ab is not defined]. Any pointers or useful resources would be great, thanks!


If you have exported a function like ab.Foo = function(...) {...} You would call it from Clojurescript as (ab.Foo ...)


Is that how you are doing it? If not, how are you exporting the function, and how are you calling it?

Mícheál Ó Catháin19:02:22

hi @U08JKUHA9 thanks for the response! I was not calling as (ab.Foo ...) but rather trying (.Foo ab ...) . Unfortunately neither working!

Mícheál Ó Catháin19:02:39

To export the function, I have used goog.provides('ab') and defined as you've listed as ab.Foo = function (...){...} It is actually a class with methods I am trying to import. It is a pseudo random number generator (sfc32) which needs to be right, and so I don't want to reimplement in clojurescript and risk errors in the implementation.


first of all you don't need :libs


assuming src in your classpath then just src/ab.js


in CLJS (:require [ab :as ab]). then ab/Foo


requiring it is the important part


@micheal.ocathain for Closure compatible things you don't need to anything other than place the file on the classpath - no configuration required

Mícheál Ó Catháin19:02:10

Thanks @U050B88UR! Is there any good resource on writing Closure compatible javascript? Apologies for the super-basic question!!


There's a Google Closure book there still lots of relevant stuff. Other than that reading the Google Closure Library sources is probably the best way to understand the conventions

Mícheál Ó Catháin19:02:31

Can I double check I am understanding correctly - regarding no configuration being required? Is this for latest clojurescript versions? I am have removed the :libs key value pair from my dev.cljs.edn and now get an error: No such namespace: ab, could \ not locate ab.cljs, ab.cljc, or JavaScript source providing "ab" in\ file /home/ubuntu/cljs/jslibtest2/src/simplyonmyway/jslibtest2.clj\ s. I'm using clojurescript v 1.10.773,


it must be on the classpath


examine this project, it uses


there is no configuration


the location and the namespace of the JS file must be the same - like ClojureScript source files

Mícheál Ó Catháin19:02:55

Fantastic - thanks so much I will study the Transit projects

Mícheál Ó Catháin19:02:17

The location and namespace being the same was catching me out. I have a basic Closure function working now!