Fork me on GitHub

Given Clojure's focus on abstractions, I suspect the second approach would be less surprising -- but I also suspect the first approach would be "easier" for beginners.

👍 4

since you are comfortable with the "high level" data structures, you can start learn JAVA doing class in all structs and exploring the clojure source (I learned java with this path)


i've learned FP by manipulating Data on lists in a language based on Lisp too. So i think the way that books and guides present the data structures from clojure is weird... but that's just because there's a ton of abstraction on top of them, but seeing how lSeq works, i can see more less how those abstractions works. My mind demands that i know how some of those abstractions were made, in order to comprehend the language, but that's just me and the path i took


since you are comfortable with the "high level" data structures, you can start learn JAVA doing class in all structs and exploring the clojure source (I learned java with this path)


There are performance guarantees associated with some of the abstractions (e.g., Counted) and then there's the whole thing about (coll ix) where several collections know how to look things up in themselves -- collections can behave like functions -- and also (kw coll) where the keyword can look itself up in certain collections -- and those are based on abstractions too (Associative, etc). So the abstractions are important.


e.g., ([1 2 3] 2) => 3 because a vector is associative:

user=> (-> [1 2 3] type ancestors)
#{... clojure.lang.Associative ... clojure.lang.Counted ...}


i see how important they are, and i've found a great joy in clojure abstractions, because when i was learning, some of them, i was doing by my own, and learning how to build abstractions by replacing signatures and producing high order functions... then i see a lot of websites and some books that focus primarily on the abstractions mechanisms and (off course) not how they are implemented or how they work... and i'm avoiding that way of programming by thinking that's some kind of magic happening and that i shouldn't bother about how


so i tend to keep digging into those data structures to find how they work, and turns out that i could build most of them by my own, just constructing a lSeq with (cons)


by seeing this way i can learn more being more confident when coding


Hi guys, I'm studying Clojure and I feel that I need to build a project to better understand this language. I want to build an API for a web app, just for fun and learning experience. Which "framework" do you recommend for a beginner? I heard about Pedestal. Any other interesting library for a begineer? 🙂


@leandrotk100 i'm planning on learn by using Luminus, which is not a framework, but most like a collection of libraries to dev back end for web


@leandrotk100 Clojure doesn't really have "frameworks" -- it has a few project templates which use collections of libraries but the mindset is composable libraries instead.


Pretty much every Clojure web app has Ring at its core (or a Ring-compatible alternative) and then there are various routing libraries -- I think Compojure is the most popular/easiest to learn when you're getting started.


Whilst you can just start with a template like Luminus, there are a lot of moving parts in such templates so if things start to go wrong, there's a huge amount of stuff to try to understand and debug -- which can be overwhelming. I highly recommend just starting with Ring and Compojure and seeing how you get on.


You will probably want to render HTML if you're not doing just a REST-style API app, so you'll either want to look at Hiccup (data as HTML) or Selmer (Django-style HTML templates).


For now I just want to build a REST-style API. Interesting to know that it's a collection of libraries. It's a different "concept" for me


I'll try this Compojure 🙂


@seancorfield what about the book Web Development with Clojure by Dmitri Sotnikov? i was planning on reading it on the future


wow. Dmitri Sotnikov is the author of the Luminus micro-framework. This book seems good


@cybersapiens97 @leandrotk100 Per my comment above: Luminus encompasses a lot of stuff -- I think you're better off learning basic Ring and Compojure first before diving into something as big and complex as Luminus, when you're getting started.


If you look at it shows it is aimed at more Expert level Clojure (see the skills meter on the left -- "About this title").


thats why i'm planning on trying it later, but i'll remember this, if things starts to get a little too complicated, i'll give a try by using one lib after another


why does Numbers are listed as Data Structure on i don't get it, wasn't Numbers supposed to be a atomic data type/java primitive, not a data structure ?


Maybe a better name for that page would be data_types rather than data_structures

👍 8
Eric Ervin01:10:45

The skills meters on some of the Pragmatic Bookshelf books are incorrect. For example, Getting Clojure is shown as Intermediate -> Advanced when it is really a beginner book. Web Development with Clojure is actually Intermediate -> Advanced, but maybe not if you consider that it includes a Clojure primer in one of it's appendixes.


Are there any modules/functions/macros to help with error tracing (in Clojure 1.9.0)? I have a small workaround but using it (introducing it to the code) is too manual:

(defn trace [name f & args]
  (print "Calling" name "with ")   
  (clojure.pprint/pprint args)
    (let [res (apply f args)]
      (print name "returning ")
      (clojure.pprint/pprint res)
    (catch Throwable e
      (print "Threw" e)
      (throw e))))
Then I insert trace "description" before function calls, like (trace "+ on numbers" + 1 2) Any tips, please?


Unfortunately, that disables compile time validation of number of parameters, so if functions/calls change, I remove to trace "message" to check the signature, then I re-add trace "message" back if need be.


Something like this?

dev> (defmacro debug [msg body]
       `(let [val# ~body]
          (println "DEBUG (MSG): " ~msg)
          (println "DEBUG (RET): " val#)
dev> (debug "adding" (+ 1 1))
DEBUG (MSG):  adding


@peter.kehl I think you're better of using Cider has direct support for it (you can trace both individual functions and whole namespaces)


Thank you @dadair and @jumar. I'll use both your macro and Cider.

Pankaj Shet07:10:20

Hi Team, I am new to this forum, I have 8+yrs of experience in java, spring, I am very interested in learning Clojure. I believe it's latest version is 1.9. I wish to get a Kickstart on Clojure. How to begin it, which book should I prefer? I want make fundamentals strong. Request you to guide me on the same. Regards, -Pankaj.


I think the book "Programming Clojure" is a good choice.

Charles Fourdrignier07:10:40

“Living Clojure” by Carin Meier is a good one too.


“Getting Clojure” has also a very gentle ramp-up and also targets 1.9. I advise both.


“Joy of Clojure” is good for experienced programmers IMO

👍 8

Yes, and “Clojure Applied” very much so — I wish there would be an updated version soon. Such good value of how to structure your code, but some of the libraries there might have been superseded by other things now.


Mainly what I like about Programming Clojure is that it explains why things happen, sometimes in terms of the JVM and in comparison with java

👍 4

hi all, any recommendations for a good way to learn cljs and clojure simultaneously (preferably with boot, which I gather is superceding leiningen)? I tried to follow the modern-cljs tutorial but it's just out of date enough that none of the examples quite works so I've spent most of my time debugging version / dependency errors instead of just learning the language. I'm a fairly experienced front-end js dev, and I'm comfortable in emacs, fwiw.


@samface boot does not supersede lein, and clj does not supersede lein or boot, they’re just different tools for similar problems. for beginners lein might be easier.


@borkdude good to know, thanks!


for learning cljs, just learn clojure the language and then start with e.g. Reagent to build some toy app


there is now figwheel.main which combines with clj and there’s also shadow-cljs. both are targetting easy getting started with cljs, but I don’t use either, so can’t advice on that


i did look at figwheel but left it to pursue the boot-based tutorial I was doing -- I'll circle back and check it out. thanks for the advice!


I do have a project in mind and I definitely agree that trying to build something is the best way to learn anything


once you get the project going, it doesn’t really matter which build tool you’re running, but boot is sometimes hard on beginners


yeah that makes sense


to see the differences between lein and boot: (may be a bit outdated)


that blog post also references a simple working clj + cljs project which may serve as an example for beginners


i think I'll be totally fine once I get the basic project / workspace going; so probably going with lein is the move until i'm more comfortable


I stumbled over a function that potentially calls itself a lot recursively, similar to this:

(defn fun
  (let [foo ["lots" "of" "strings" "but" "always" "the" "same" "ones"]]
    (if (some-checks-with-x-and-foo)
      (fun some-values)
      (fun other-values))))
Is having foo inside the let there for every call of fun bad?


Regarding performance you mean? I think the JVM Clojure compiler is smart enough to perform constant extraction, meaning that foo will only be computed once when fun is compiled. But you'd be relying on an implementation detail here. You can also wrap the (let [foo ...]) around the defn, or if that disturbs you do something like (def fun (let [foo ...] (fn fun [x] ...))))


Thanks, I think I like the last syntax more, even if looks new to me. I'll check it out!


>You can also wrap the (let [foo ...]) around the defn What does that mean?


@U63JKCFC3 Like this I think:

(let [foo ["some" "values"]]
  (defn fun
    ; function body, use foo here

👍 8

Oh btw, how can I make the above snippet highlighted as clojure code?


In Slack, I'm not sure you can in this format, but you could post a Snippet with Clojure syntax.


I have a question. How can I turn (< [1 2 3]) into (< 1 2 3) ?


@coinedtalk do you mean (apply < [1 2 3])?


or do you want to transform the literal list of symbols/numbers to the other?


(let [expr '(< [1 2 3])]
  `(~(first expr) ~@(second expr)))



(let [expr '(< [1 2 3])]
  (apply list (first expr) (second expr)))


clojure is really fascinating


Hello, Here is this repo. That is shadow-cljs mixed clj part. I run successfully and setup as in the readme part. How could I create from this a real solution? compile with lein uberjar for backend and different way to frontend? with lein uberjar I get

Can't find 'shadow.cljs.devtools.clj' as .class or .clj for lein run: please check the spelling.
Exception in thread "main" Could not locate shadow/cljs/devtools/clj__init.class or shadow/cljs/devtools/clj.clj on classpath.


@sb there are some typos shadow.cljs.devtools.clj should be shadow.cljs.devtools.cli, i not j.


and this is supposed to be "release" "app" not "build" "app"


Oh i see, the original question in this way works, can i use the shadow cljs?


With ‘lein uberjar?


Ok, thanks!! 👍


Hello macro experts. How do I get the macro's call code as a string from &form, please? I worked out how to access the code of one parameter: (defmacro print-code [param] (list 'print (str param))) which called as (print-code (+ 1 2)) prints: (+ 1 2). How can I do the same with &form in either unquoted macro source (list ...) or in a back tick-quoted one, please?


I tried various combinations, like (defmacro print-code2 [& param] (print ~&form))` (defmacro print-code2 [& param] (print ~@&form)` (defmacro print-code2 [& param] (print @&form)) ;most likely incorrect`


user=> (defmacro hello [s] (let [f (str &form)] `(let [s# ~s] (str s# ~f s#))))
user=> (hello (do (println "Hi!") "World!"))
"World!(hello (do (println \"Hi!\") \"World!\"))World!"


You just use &form on its own at the macro level -- if you need it in the expansion, you'll need to bind it at the macro level and unquote that binding in the code level.

Pavithra Kannan16:10:33

Hello Clojurians, I'm new to Clojure, can you please suggest or give ideas to work on a beginner project to enhance my knowlegdge.


if you have nothing particular that you want to do, I would suggest

👍 8

while searching here in Slack I just noticed that the "workspace is over the storage limit".


do we have ever considered to go to Gittr or something else which is not limited?


there's a separate channel for this sort of discussion, for context IRC is still around with hundreds of users and other channels are welcome but there's no real centralized leadership that's going to tell everyone to stop using a particular channel and go somewhere else AFAIC


iirc #community-development was where this discussion happened, ironically the entire contents are gone thanks to slack storage limits

😂 4

I just found dev-ua/clojure


@U0TSNMT53 There are several Clojure rooms on Gitter. Let me go get the link for the main one(s)...


There are also rooms for core.cache, core.memoize, java.jdbc, and tools.cli (since I maintain those four).


I don't do Emacs though, I'm a vi person since 1995


I don't do Emacs either -- but CIDER's Orchard library and nREPL (which is part of that same team now) are core to most editors' Clojure integration 🙂


Im setting up a newer osx laptop and installed jdk 11 and tried to run a new luminus web app created from leiningen. I am getting some strange errors when running the repl.

Exception in thread "main" java.lang.ExceptionInInitializerError
	at clojure.main.<clinit>(
Caused by: java.lang.IllegalArgumentException: Must hint overloaded method: toArray, compiling:(flatland/ordered/set.clj:19:1)...
Caused by: java.lang.IllegalArgumentException: Must hint overloaded method: toArray
	at clojure.lang.Compiler$NewInstanceMethod.parse(
	at clojure.lang.Compiler$
	at clojure.lang.Compiler$NewInstanceExpr$DeftypeParser.parse(
	at clojure.lang.Compiler.analyzeSeq(
	... 328 more

I did a little research and found that you may get errors like this if building clojure from source but I am not, so im not sure what's happening.


Might come from core.rrb-vector, not Clojure @dfcarpenter - try specifying version 0.0.12 for that


If I need the “ssh task” before compile with lein uberjar, how can I add to :prep-tasks in project.clj?


:prep-tasks ["ssh-task-here" "compile" "js-build" "css-build"]


ok, works with lein shell.


@ghadi I added it to my lein deps but I am still getting the error. How can I find which dependency is using an older version?


lein deps :tree


Thanks. Well how frustrating. I can't find out what is using rrb-vector. Guess i'll downgrade java


@dfcarpenter the answer is in your stacktrace earlier


It's flatland/ordered/set.clj that is the problem


(I missed that earlier)


Yeah, a similar problem with OpenJDK 11 and Clojure has bitten a handful of Clojure libraries, as well as those who build Clojure from source code themselves. Looks like flatland/ordered/set is one of those.


Ahh I see its a dependency of the lacinia project


this is one of those rare examples of an addition that is incompatible


usually additive things are compatible


Well thank you for the help


Is there a way to exclude a dependency of a dependency so that I can just include rrb-vector 0.0.12 in my deps and it should use that?


You could try pinging amalloy on that PR, perhaps, to see if he is interested in merging and releasing an updated version.


rrb-vector is unrelated to your problem -- unless you know otherwise @dfcarpenter


(But an identical problem exists there)


Oh of course, sorry I need coffee


If you need "work real quick now -- will later update to use official release versions when/if available", you could apply that path to flatland/ordered/set yourself and create a JAR for it, either local or on Clojars.


Then your question above would be the same, except how to override a different dependency.


Does the argument passed in a Macro, can be described as an S-Expression ?


@cybersapiens97 sure. The arguments can also be called “forms”

🙂 4

I’ve learned to deal with meta-programming by manipulating S-Expressions, so I think I can mimic the structural design for s-expr data when working with macros