Fork me on GitHub
Arto Kalishian06:10:43

Yesterday I had a thought, what if Clojure was built on Erlang VM instead of JVM. Wrote that on and figured out someone already made Clojerl 🙂 It was interesting. Now that the activity is very low on this channel I wonder if many already moved to Clojerl 😄


might also checkout LFE from co-inventor of Erlang:

❤️ 4
Arto Kalishian11:10:11

Wow. Thanks for sharing

benzap15:10:39 I would find it difficult to move to the Erlang VM, since I feel like there's a wealth of libraries to choose from within the JVM ecosystem. What sort of benefits would switching to the Erlang VM entail? I've always been interested in Erlang and Elixir, but I haven't found a reason to really embrace it.

Arto Kalishian15:10:05

Not moving.. more like using it for specific use cases where scalability is needed.. if you can write clojure anyway why not leverage that on erlang. Their library ecosystem is not on par with Java but it's still huge.


you’re talking about some pretty crazy scale if you’re out-scaling the JVM itself


With reader conditionals, I wonder if some of the more popular clojure(script) libraries could be ported to clojerl. That would definitely give me reason to consider trying it out some more in hobby projects.


That actually begs the question on whether there are any clojure libraries that have used reader conditionals to work between clojure, clojurescript, clojerl and clojureCLR


and do clojerl and clojureCLR even have a standard key to produce the necessary reader conditionals?


ie. :clj --> <clojure JVM> :cljs --> <clojurescript>, ? --> <clojure erlang>, ? --> <clojure CLR>

Alex Miller (Clojure team)17:10:58

There are lots of libs that work between clj and cljs

Alex Miller (Clojure team)17:10:08

There is a constant defined for clr and it’s supported there, but I don’t remember what it is

Alex Miller (Clojure team)17:10:20

Clojerl could pick their own

Alex Miller (Clojure team)17:10:54

:default can also be used for stuff that’s the same across


i'm trying to write a zip function that would be similar to python's zip


i've found how (map vector coll1 coll2 ...) will give the proper zip behavior


but i'm having trouble figuring out how to write a new function that is multiarity in the same way


i'm also a bit unclear on what a transducer is


why does ((map vector) coll1 coll2 coll3) throw Wrong number of args (3) passed to: clojure.core/map/fn--5847?


@U0M21EATB Most transducers only accept one collection argument. I think you'll need to use the sequence transducer to map over multiple collections...?


(sequence (map vector) coll1 coll2 coll3)


user=> (def coll1 (range 10))
user=> (def coll2 (range 20 30))
user=> (def coll3 [:a :b :c :d :e :f :g :h :i :j])
user=> (sequence (map vector) coll1 coll2 coll3)
([0 20 :a] [1 21 :b] [2 22 :c] [3 23 :d] [4 24 :e] [5 25 :f] [6 26 :g] [7 27 :h] [8 28 :i] [9 29 :j])


Hmm. I'll have to chew on that one. Thanks!


i can also move this over to #beginners if that'd be a better place for it


has anyone read Elements of Clojure?


@juan.ignacio848 Yup, it's a good book. You have questions about some of its recommendations?


Nope. I haven't bought it yet. I wanted to check if it was worth it


I heard / read somewhere it was a good book


I would recommend it highly, yes. It has a lot of great advice and philosophy in it about programming in general, as well as Clojure-specific stuff.


Great! I'll buy it then


What's the value position of di frameworks for clojure over doing it manually by argument passing?


can you name a di framework? do you mean something like component?


The only DI in Component is the automated assembly / start / stop process. Then you're just passing a system/environment data structure around (and it's up to you how much you pass down the call chain).


But, yeah, in a complex system, that assembly / start / stop process could be a lot of work to maintain manually and get it correct in all cases.


How complex is complex? Do you mean Rich Hickey complex?


A dozen or so pieces, all with their own start/stop lifecycle?


Even half a dozen pieces is probably worth it to use Component.


Web app depends on Core app + Web Server; Web Server depends on Config; Core app depends on Database, Caches, etc; Database depends on Config; Caches depends on Config maybe...


I think we have 35 Components in our systems at work (although not all apps/service use all 35).


35 across all services? e.g. if you had 7 services, you'd have 7 web servers?


your described layout is actually fairly simple:

(let [config (aero/read-config "config.edn")
      db (hikari/start-pool (:db config))
      cache (cache/fifo-cache-factory (:cache config))
      core (myapp/core db cache)
      handler (myapp.http/handler core)
      http (jetty/run-server handler (:http config))]
  (fn stop!
    (.close http)
    (myapp/close-core core)
    (hikari/close-datasource db)))
I was thinking through the value proposition, and realized it's quite hard to articulate.


Those services would mostly reuse a generic WebServer Component.


@seancorfield but how did you count 35? through how many defrecords you have, or how many keys you have in system maps?


component/Lifecycle references.


So that doesn't count the app-level combinations of reusable components, just the actual components themselves.


Yeah. It doesn't reflect the size of the systems, just how many resuable pieces you have to put into those systems.


That said, we have 70K lines of production Clojure (and 20K lines of tests) so it's a "fairly big" system. Broken into about 30 subprojects, of which a dozen are top-level apps/services.


@seancorfield I've worked on many applications that size or larger. Most of them could have their system reduced to something like the above.


I wouldn't want to manage our dependencies and start/stop lifecycle code manually at this point. @hiredman would probably have more to say about our component model -- he uses it in a far more fine-grained way than I do, for the most part.


Yeah, you could do it all via manually passing arguments and ensuring things are started in the right order, but using component gives you the benefits of the argument passing style (vs global rederences) while automating everything


People often react badly to component because "oh, it's DI and that is terrible" but component really is just using topological sorting to determine what order to call things in. is a minimal reproduction of everything component does


One potential advantage of component over the hand wired together approach is in component you build your system as a dependency graph which is a data structure, which means you do things like take the defined system and manipulate it for doing things like running tests


In general, I would say component is going to more beneficial the more you decompose dependencies. For example I like to make each ring handler a component so for each one I can make independent decisions about what dependencies they have


I've done this, but have got loads of resistance to "boilerplate".