Fork me on GitHub

Hey guys what is the most efficient way of importing large javascript libraries (in this case THREE.js) inside clojurescript?


Same as any other library. Either use shadow-cljs as your build tool, or see the ClojureScript webpack guide


Why is this returning 3 instead of 1+1 + 1+2 + 1+3 = 9: (reduce #(+ 1 %) [1 2 3])


the reducer function takes two arguments. an accumulator and the current element


#(+ 1 %) is only using the first one, the accumulator


so you end up repeating:

(+ 1 nil) ;; => 1, which will be passed in to the next one as the accumulator
(+ 1 1) ;; => 2
(+ 1 2) ;; => 3


Hmm, I don't think I understand. This is still not working: (reduce #(+ 1 %2) [1 2 3]) (returning 4 instead of 9)


It seems like maybe you are trying this using clojurescript, not clojure


Correct, I am playing with Planck


Clojure proper will throw an error for your first example


Your second example is really the same issue, you need to use both the accumulated value and the element


It will likely be clearer to you if you use fn and explicitly list out the arguments and give then names


Thanks, I'll try that.


What I don't get now is why (reduce #(+ 1 %1 %2) [1 2 3]) is returing 8 instead of 9. Same with (reduce (fn [x y] (+ 1 x y)) [1 2 3])


Remove the reduce and write it out


(+ 1 (+ 1 1 2) 3)


you are expecting something like (+ 1 (+ 1 (+ 1 _ 1) 2) 3), so the question is what _ needs to be and where and how you communicate it to reduce


the doc string for reduce might be helpful there


I thought reduce would work like this: Step 1: 1 (from my vector) + 1 (hardcoded) = 2 Step 2: 2 (acculmated) + 2 (from my vec) + 1 (hardcoded) = 5 Step 3: 5 (accumlated) + 3 (from my vector) + 1 (hardcoded) = 9


but you have a function of two arguments, and one is missing in your step 1, so that cannot be what is happening


right? you step one doesn't have an accumulator to use, and reduce obviously doesn't make up an initial accumulator value from nothing


so in order to call your function it needs an item from the vector and an accumulator value


Ah, so: (reduce #(+ 1 %1 %2) 0[1 2 3])


Yeah, this works. Thanks for the explanation. I need to get more used to the functional way of thinking 🙂


The docstring for reduce is quite complex but it is also very specific about what happens.

If val is not supplied,
  returns the result of applying f to the first 2 items in coll
-- so the first call in your case was (+ 1 1 2) (just so you understand where @hiredman’s expression above came from).


Thanks for the very helpful addition. I see now. In the case of (reduce #(+ 1 %1 %2) [1 2 3]), I am getting 8 because: Step 1: 1 (first elm in coll) + 2 (first elm in coll) + 1 (hardcoded) = 4 Step 2: 3 (third elm in coll) + 1 (hardcoded) = 4 = 8


It's much safer to always provide the initial val to avoid the somewhat strange cases (empty collection, one element, two-or-more elements).


for a function, I don't know if I should use a named args or just accept a map, the fn has to create a map from the values given, some args are required, some are optional - what's recommended to do here?


@lockdown- Accept a map, in general.


Named arguments are good for functions that will only ever be called by humans but they don't compose well if they're called by other functions.

👍 4

how to split {1,2} to [1 2] in clojure?

Drake Nelson11:04:59

I haven't eval tool on hand, but I think into function will be solution.


@haiyuan.vinurs {1,2} is the same as {1 2} in Clojure, because commas are treated as white space. If you were asking how to create a vector from a map, then this is one simple approach

(vec {1 2})
;; => [[1 2]]

  (vec {1 2}))
;; => (1 2)


@haiyuan.vinurs as in the string or the dictionary?


@haiyuan.vinurs then a regex would do the trick.


or if you know your input is safe you could be really cheeky convert "{1,2}" => "[1,2]" and call read-string on it.


Is there a way to get partition-all or similar Clojure core function to partition (or group) starting at the end of a sequence? So if I had an argument of "abcdefg I would get a result (("a") ("bcd") ("efg")) Of course I could reverse before partitioning, just wondering if I missed something


({:xAxis 48}{:yAxis 35}) This is my map .I want value of only xAxis.


(:xAxis ({:xAxis 48 :yAxis 35})


If you have a single map of {:x-axis 48 :y-axis 35} then you can do (:x-axis {:x-axis 48 :y-axis 35}


this is not single map. How can i convert it to single map?


You could merge maps.


Or you could map over the collection using: (some :x-axis '({:x-axis 48} {:y-axis 35}))


or you can use map, but you also get a nil value because :x-axis only exists in one map (map :x-axis '({:x-axis 48} {:y-axis 35}))


if i want {:x-axis 48 :y-axis 35} then how to do it ??? above solutions giving me nil value


the above some and map functions work on the sequence of maps. If you want to combine the maps, then use (reduce merge '({:x-axis 48} {:y-axis 35}))


Remember, when using a list () as an argument (data) then you need to quote the list, '() or Clojure will try to call the first element of a list as a function.


Thank you worked

bananadance 4

Thanks for the very helpful addition. I see now. In the case of (reduce #(+ 1 %1 %2) [1 2 3]), I am getting 8 because: Step 1: 1 (first elm in coll) + 2 (first elm in coll) + 1 (hardcoded) = 4 Step 2: 3 (third elm in coll) + 1 (hardcoded) = 4 = 8


Hey all 👋 I’m using Visual Studio Code + Calva. In Clojure, is it possible to put a breakpoint on a line in the source file, stop execution there and start stepping in/over the code?

Alex Miller (Clojure team)13:04:29

It is generally possible (other tools like Cursive can do so via the JVM debugging API), but I don't know if Calva does it


Thank you for your answer.


@UHBCE1X7D ask on the #calva-dev channel, they are very responsive. As Calva is modelling itself after CIDER in Emacs, then Calva should have debugging at some point (if not already)


Will do, @U05254DQM, thank you 🙂

Lennart Buit13:04:20

well, the debugging in Cursive is a bit strange sometimes. For example, you sometimes “continue” to the same line three times, because the form was a macro that happened to expand to multiple “lines”

Alex Miller (Clojure team)13:04:16

well, that's true of all Clojure debuggers, both from macroexpansion and having multiple expressions per line in the bytecode

Lennart Buit13:04:46

(mean no disrespect, I love cursive! just warning newcomers for that caveat!)


same is true in CLJS 🙂 the places you can actually set a breakpoint in Chrome is a bit mysterious sometimes

Lennart Buit13:04:33

yeah, I guess both debuggers are made for non-functional languages

Lennart Buit13:04:51

(not sure how a functional language debugger would look tho)


I think it just has to do with the fact that there’s not a 1:1 correspondence with a Clojure expression and an expression on the host platform


I don’t think it’s functional vs non-functional thing


anyone seen illegal access when starting lein repl. just updated to 1.11.0.

Lennart Buit14:04:43

java 11 you mean?

Lennart Buit14:04:55

or clojure 1.10 😛


clojure 1.10 opendjdk 1.11

Lennart Buit14:04:42

yeah, Java >=9 has a new module system that hides certain implementation details from you. They are slowly removing access to those implementation details. I am sure others call explain it better than me

Lennart Buit14:04:31

and already apparently have! Thanks Alex!


--illegal-access=deny, do I add this to my profiles.clj: :jvm-opts ^:replace ["---illegal-access=deny"] (that didn't seem to help)

Alex Miller (Clojure team)15:04:14

you have one too many --- there

Alex Miller (Clojure team)15:04:28

but this is the right place


I think this needs to be passed to the jvm. It isn't clear from the site where to pass it, especially for someone new to Clojure and using mainly the lein tool.


or perhaps an environment variable


if you guys had to name a temporary folder and a zip file, that later will be requested by the user front-end application. What would you use to name it? i was thinking on using a UUID

Alex Miller (Clojure team)17:04:25

The JDK has an api for this that can create unique things in an os-friendly location


@cybersapiens97 make a sha1 of the content, set the sha1 as the filename. Instant collision-free 🙂


also gives the benefit of people being able to verify the contents of that specific file (but yeah, 99.99999999% of users won't care about that)

👍 4

Hi, would anyone be able to explain a couple of things about Clojure spec? I am trying to wrap my head around how it compares to a static type system. I understand that it is extremely tunable and flexible (obviously different than static types), but what are some ways that it's not as powerful as a type system?


spec is used at runtime, so you do not get the ability to "check your program" by just adding specs and running a tool against your code


Okay, thanks. Since Clojure is so extensible, could one devise a program that runs everytime before you compile code to basically do static type checking via spec?


Like a middleware that checks against spec before clojure code gets read by the reader.


Oh shite, I just realize what @U064X3EF3 messaged after you


The answer to my question haha

Alex Miller (Clojure team)17:04:00

(Although Spectrum does this better than I would expect using specs)

🤯 4

In effect, is this library any different than having static type checking, or is it basically the exact same thing?

Alex Miller (Clojure team)17:04:04

It can’t handle everything

Alex Miller (Clojure team)17:04:54

And it can’t protect you from things that happen at runtime

Alex Miller (Clojure team)17:04:22

Ultimately, types are about proving things. Specs will not help you prove things.


👋:skin-tone-2: I have a map that has some metadata, I'm trying to read a key from it, who's value is a string, but I get a ClassCastException error, as strings are not able to have metadata


sounds like you are flipping something, because metadata is a map, and it's allowed to have strings as both keys and values


oh nm this works which kills my assumption on what was wrong

(def a (with-meta {:a "ok"} {:type "a map!"}))
(meta a) ;; => {:type "a map!"}
(:a a)


I thought the last line would error

Robert Nikander19:04:14

Is there any reason I can't put docstrings on my deftype methods?

Alex Miller (Clojure team)19:04:00

How would you see them?

Alex Miller (Clojure team)19:04:54

deftypes can only implement interface methods and protocol methods, and those are the visible abstractions


the method on a deftype isn't data that it owns, so it doesn't contain storage for a doc string - on the jvm methods aren't Objects


nominally the doc should go on the protocol or interface owning that method


(or on the type owning the method)


Poll: Leiningen or Boot?


wondering which is more used


clj and deps maybe


leiningen is used more by far

Robert Nikander19:04:30

I like clj and deps so far. But my project is only 6K lines of clj/cljs.


I kinda see clj being the standard in the future.


but for now I stick to lein, just because the tutorials tend to use them.


is there a good tutorial on using clj and deps as far as workflow?


though probably someone has something better.

Robert Nikander19:04:50

I got cider, repls, and cljs working with it. I doubt I'll ever use lein now.


clj / deps is a tool for starting a repl, and a dependency manager, you will usually still need a build / packaging / deployment tool(s) for library dev or deploying apps


there are ways to use deps and/or clj with lein or boot, and various relatively young build tools that use deps


They do are planning some cool things with boot, like being part native and supporting other languages. But for me it's still Leiningen, mostly because I now know how it works, and haven't really felt limited by it so far.


@sotrhraven At World Singles Networks, we started with Leiningen back in 2011 (because that was the only choice), switched to Boot in 2015 (I blogged about that at ), and then switched to clj / deps.edn completely last year (I have not blogged about that yet!).


what do you use for build / package / deploy with deps.edn?


Our code base is currently 81,461 lines (production source + tests)


With a total of 986 lines of EDN (config files + deps.edn) across our monorepo.


(822 lines are the various deps.edn files)


We use (my fork of) depstar for build JAR files for deployment to production and we have a handful for small dev/build "tasks" written as Clojure namespaces containing -main functions that we invoke with clj and :main-opts in various aliases.


Various clj/`deps.edn` tools available (including depstar):


just to anyone who would like to try out: i'm a relative beginner on clojure web development, and i'm finding much more easier to work with my projects using Polylith, not only more easier but more fun and simple after you get how it works!


does anyone have advice or reading on composing promises? i'm defining several simple but computationally-intensive processes, which I want to combine in a few ways. Some can be done in parallel, others must wait for completion of earlier ones.


the big thing is that a Clojure promise (as opposed to other implementations like JavaScript) isn't an execution mechanism, it's a container that starts empty and gets filled exactly once

👍 4

you can wait on it in a blocking manner but there's no "chaining" and it doesn't allocate a thread


there are abstractions meant for managing parallel / async execution - and promises can even be part of it, but they will be a small part if they are (they are a straightforward way to make one thread wait for a specific action in another thread)


AFAIK attend, then, recover, and fail from the page you linked were never implemented


hmmmmmm. well i don't think what i've got is complicated enough for core.async, maybe I'm wrong --- my big problem is, I'm the guy who has to start all the different components of our app several times a day, to test different revisions and scenarios, and i'm getting v. tired of forgetting to start components, or having to restart some but not others, and none of it's in code


i was inspired by a talk that suggested, maybe async is an elite carbon-fiber mountain bike, and i need a fixie 🙂


there are other mechanisms before core.async - eg. agents (which use a threadpool and abstract a value that you send functions to)


that page predates core.async, which to some degree supersedes it


it sounds more like you want something to start things and make sure there dependencies are started first, and do the reverse when you stop things


yes. i figure i'm heading in the integrant direction but i've never written async in clojure


I haven't used integrant, but I am a big fan of component


also on the table


kinda figured i should figure out how to async, at least a little, before datafying it all


but I don't think any of that has anything to do with async/promise/futures/threads/etc


yeah i guess you could say, i can see i have a problem with multiple pieces but i don't see the seams yet


you could always just create a dependency graph then toposort the graph and do whatever with that (which is what component does)


there's also plumatic/plumbing/graph which has a data / value oriented approach to this


i'll take a look


graph lets you define data dependencies, then hand them to an execution strategy (single threaded or async)


the promise thing came in, btw, when i was looking into ways to shell and i started playing with clj-commons-exec. it returns a promise instead of a value so I was thinking, huh, is it time to learn this aspect of clojure


but it might be a red herring


you can get a plumatic graph kind of thing from a dependency graph and a topo sort as well


cool cool, i will check these out, thanks y'all


When one does (defn foo [{:keys [a b c]]....), is the arg converted to a seq, then map, or to map directly?


the arg isn't converted - the clojure.core/destructure function is used inside the defn macro to pull the values out of the map and bind them


perhaps you were thinking of (defn foo [& {...}] ...) syntax? that starts with a seq of args and builds a hash-map


user=> (macroexpand '(fn [{:keys [a b]}] [a b]))
(fn* ([p__143] (clojure.core/let [{:keys [a b]} p__143] [a b])))


user=> (macroexpand '(let [{:keys [a b]} y] [a b]))
(let* [map__146 y map__146 (if (clojure.core/seq? map__146) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__146)) map__146) a (clojure.core/get map__146 :a) b (clojure.core/get map__146 :b)] [a b])


@noisesmith heh yeah, missed the & there


user=> (macroexpand '(fn [& {:keys [a b]}] [a b]))
(fn* ([& p__149] (clojure.core/let [{:keys [a b]} p__149] [a b])))


hmm, per @hiredman's example, looks like with & doesn't make any difference


it is different in that seq? will return true, and turn it into a map