Fork me on GitHub

Hello everyone, can someone explain on how this is possible:

(let [{:keys [a b]} '(:a 1 :b 2)]
        [a b])
But this is not:
(select-keys `(:a 1 :b 2 :c 3) [:a :b])


I need to kinda "filter out" unwanted kwargs here


but if that's not possible, guess i need to use a map instead of a kwargs


I also notice that associative destructuring from a list is noticably slower than map, so in general, do I need to avoid kwargs from now on?


Keyword arguments are fine for functions that "people" call but they don't compose when they're part of a call chain so it's better to use them only sparingly.


Regarding your list of alternating keywords and values, you can (apply hash-map ...) to turn it into a regular map and then select-keys will work.


Yes @seancorfield primarily the optional arguments are chained into another function


The let form sort of "works by accident".


It's generally better to pass around named / optional arguments in a single hash map argument. That will compose easily when chaining function calls.


So are you suggesting that the "outer part" of the call chain can still use a kwargs but then I'd better off to use that in a map inwards?


Yes, exactly that.


Thank you @seancorfield, that was pretty clear. By the way what do you mean when the let form is a "works by accident"?


boot.user=> (macroexpand-1 '(let [{:keys [a b]} '(:a 1 :b 2)] [a b]))
(let* [map__1817 (quote (:a 1 :b 2)) map__1817 (if (clojure.core/seq? map__1817) (clojure.lang.PersistentHashMap/create (clojure.core/seq map__1817)) map__1817) a (clojure.core/get map__1817 :a) b (clojure.core/get map__1817 :b)] [a b])


I see, so clojure unknowingly to me create a hash map


Behind the scenes it creates a hash map. That's why select-keys doesn't work: it just expects a hash map.


Thank you for the comprehensive explanation (as always) @seancorfield


Usually Clojure "helps" by calling seq on things to get sequences -- so passing a hash map will often produce a sequence of pairs (`MapEntry` objects that look like vectors with two elements). This is one of those weird cases where it goes the other way and if if finds something that implements ISeq (which is a pretty narrow set of things really), it tries to create a hash map from it.


Note in particular that if you had {:a 1 :b 2] it would not work (because a vector does not implement ISeq).


(you'd need to explicitly convert it to a sequence: (seq [:a 1 :b 2]))


I see, I'll look into it


If in the inner layer there's a function (from a library that is expecting a kwargs), does apply still works to a hash map?


It requires a bit more than apply because a hash map isn't a sequence of kw val kw val... it's a sequence of [kw val] [kw val]


(apply some-fn (mapcat identity my-map)) will work. There's probably something simpler/faster tho'...


I'll check with the said library, hopefully they also allow a hash map to be passed


Nope, haha. But is it possible though to construct a function that allow both (optional) kwargs and a map?


@hawari.rahman17 And since then I've evolved the API so it doesn't use any keyword arguments now -- it just uses option hash maps everywhere. It's made the code much simpler and it's made the library easier to use.


good morning all


Yeah, I agree that it seems to be simpler that way @seancorfield now in my code. Unfortunately I still need to work with another library which doesn't use the same convention, but it's manageable.


I thought this would work : (#(* %1 2))


but now I see this error message : clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox4852$eval183066$fn


where do I took the wrong path


I thought that you just have to type * 2?


Works for me that way


So #( %1 2) is another way to write (fn [x] ( x 2))


Both of those expressions evaluate to: a function that takes one argument, and returns it multiplied by 2


Oh, I should use backticks to avoid mangling: #(* %1 2) is another way to write (fn [x] (* x 2))


By putting one set of parens around it, you are saying: That first thing in parens is a function, please call it with no arguments.


works but the challenge says to write a function and * 2 looks not a function to me


After reading the question thoroughly, yes, it seems that it was expecting a function, haha


Then #(* 2 %) should suffice, as @andy.fingerhut just point out


both thanks


(#(* 2 %)) that you wrote does not return a function, it evaluates a list with your function as the first element, but then since it doesn't have an argument in it and your function expects an argument, the arity exception was thrown


im also trying the webdevelopment with clojure book


I have now this in the db/core.clj file


(ns guestbook.db.core
  [yesql.core :refer [defqueries]]
  [config.core :refer [env]]))

(def conn
  {:classname "org.h2.Driver"
   :connection-uri (:database-url env)
   :make-pool? true
   :naming {:keys clojure.string/lower-case
            :fields clojure.string/upper-case}})

(defqueries "sql/queries.sql" {:connection conn})


I connect my repl into the development repl of luminus


and do this

Connecting to remote nREPL server...
Clojure 1.9.0
(use 'guestbook.db.core)


but then this appears : ` CompilerException Could not locate yesql/core__init.class or yesql/core.clj on classpath., compiling:(guestbook/db/core.clj:1:1) `


oke, yesql does not seem to be installed :

:dependencies [[clj-time "0.14.2"]
                 [com.h2database/h2 "1.4.196"]
                 [compojure "1.6.0"]
                 [conman "0.7.5"]
                 [cprop "0.1.11"]
                 [funcool/struct "1.2.0"]
                 [luminus-immutant "0.2.4"]
                 [luminus-migrations "0.5.0"]
                 [luminus-nrepl "0.1.4"]
                 [luminus/ring-ttl-session "0.3.2"]
                 [markdown-clj "1.0.2"]
                 [metosin/muuntaja "0.5.0"]
                 [metosin/ring-http-response "0.9.0"]
                 [mount "0.1.11"]
                 [org.clojure/clojure "1.9.0"]
                 [org.clojure/tools.cli "0.3.5"]
                 [org.clojure/tools.logging "0.4.0"]
                 [org.webjars.bower/tether "1.4.3"]
                 [org.webjars/bootstrap "4.0.0"]
                 [org.webjars/font-awesome "5.0.6"]
                 [org.webjars/jquery "3.2.1"]
                 [ring-webjars "0.2.0"]
                 [ring/ring-core "1.6.3"]
                 [ring/ring-defaults "0.3.1"]
                 [selmer "1.11.6"]]


wierd, that there is no mention about adding yesql to the dependencies


i'm trying to switch from cursive to spacemacs and one thing i really miss is full symbol replacement (such as replacing anon functions with lambdas). spacemacs loads clojure-enable-fancify-symbols which replaces some things, but i'd like to customize it to replace more (such as defn to ƒ). as a complete newcomer to spacemacs, how can i go about hacking away at this?


for instance, i don't know where to find clojure-enable-fancify-symbols 😉


@joshkh in dotspacemacs-configuration-layers, change the clojure layer to (clojure :variables clojure-enable-fancify-symbols t) I’m away from my setup, so there maybe a typo.


thanks, that's what i have and it works as advertised. it's just that i want to add more symbol swapping than the default, such as replacing defn.


There’s a #spacemacs channel. You may get a better response there.


oh, thanks!!


What clojure seq would you use for a simple FIFO queue?


I was using vectors, but (rest vector) returns a list, which fucked up my insertion with conj (conj in a vector appends to the end, while conj in a list appends to the beggining)


@pablore I don't know if vectors are the best choice here, but if you take that route, use (subvec vector 1)


@moxaj what would you use?


@sundarj I think that may


Gonna try it real quick


PersistentQueue do all the things I want, but does it has a spec?


so i can do something like (s/def ::queue persistent-queue?)


@pablore queues are kind of a hidden feature, so you may have to roll your own


:c sadness


not that it's hard, (instance? clojure.lang.PersistentQueue ...)


What about a PersistentQueue of <type>


(s/coll-of pred :kind queue?)


where queue? is (instance? clojre.lang.PersistentQueue ...)?


well, not the expression, but the function

Drew Verlee15:02:12

Is there a way to have a global (project independent solution) to being able to pick up changes to multimethods?

Drew Verlee15:02:38

I feel like my options are: * restart my repl * use something that does state management (like component, mount, integrant) The first removes all my state (which i only wanted a bit refreshed) and the later seems to be project dependent and requires some setup.


I'd use it will reset the state of the reloaded namespaces but you don't have to restart your REPL / reset the state of unaffected namespaces

Drew Verlee15:02:51

is there a way to remove some of the setup time with using them? I’m thinking that if i want to use component to solve this problem i have to a) include it in my project b) restart my repl anyway to get those changes c) write code for the refresh d)… if i’m writing a big app this isn’t a problem, but for some quick poking around this is tedious.

Drew Verlee15:02:44

or maybe i’m not leveraging some idea or abstraction in the community. I haven’t worked professional under someone in clojure so i might be missing something


you can create your own lein template that includes dependency and mount/component dependency, and a default dev namespace (`user`) that suits your workflow


then if you want to create a quick project you lein new mytemplate random-small-project


and just lein repl into it and write and reload code

Drew Verlee15:02:05

This is what i was imaging i might do given the tools i know about.


consider using mount/component/integrant for managing state, it really pays off


someone who can help me with a luminus problem I asked before

Drew Verlee16:02:46

what was the question? i’m not sure i can still see it

Drew Verlee16:02:16

also asking in #luminus might get you to ppl that can help you faster


when I open a repl and try to open my guestbook I see this message : CompilerException Could not locate yesql/core__init.class or yesql/core.clj on classpath., compiling:(guestbook/db/core.clj:1:1) `


on Windows

Drew Verlee16:02:32

did you add yessql to your project.clj as a dependency?


Nope that was not mentioned in the book

Drew Verlee17:02:00

can you link the book for me?

Drew Verlee17:02:11

I’m guessing thats the solution though 🙂


I use the "web development with clojure" book


I added yesql but still this error message when trying (use 'guestbook.db.core) on a repl


error message : CompilerException Could not locate config/core__init.class or config/core.clj on classpath., compiling:(guestbook/db/core.clj:1:1) on a Windows 10 machine

Drew Verlee22:02:14

hard to say. I would push your code to github and share it with ppl. I’m guessing the issue is that there is a config/core.clj file that you reference in guestbook/db/core.clj that it can’t find.


and hope that someone could help me solve this ?

Drew Verlee03:02:12

Sorry roleof. For some reason i dont get updates on your threads. I’ll take a look. thanks

Drew Verlee03:02:18

you might want to keep asking in beginners. is it web development version 2 or 1?

Drew Verlee03:02:47

or asking #luminus

Drew Verlee03:02:14

change [config.core :refer [env] -> [guestbook.config :refer [env]

Drew Verlee03:02:51

in guestbook/db/core.clj

Drew Verlee03:02:42

i should read this book

Drew Verlee03:02:09

if you want, maybe we can work through this book together. i know a bit of this already so i might be able to help


I will try. Sorry for responding this late but it appears we live in different timezones


where did you find it to change things


it works but I cannot find any reference to this change

Drew Verlee14:02:18

i just pulled down your code and made the change locally.


hey, im going through 'clojure for the brave and true' at the moment -- would 'the joy of clojure' be a good follow up book?

Drew Verlee16:02:08

joy of clojure is broad and deep, so its a lot of effort. It might be more fun to jump into doing something after you finish that book. But yea, its a good second book imo. I also think “elements of clojure” will be a great second book.


hm, can you define 'broad and deep'?


you mean, understanding it 'is a lot of effort'?

Drew Verlee16:02:33

hm, can you define ‘broad and deep’? at 360 pages its not a light read. It covers a lot of ground and dives into topics about how clojure works under the hood (implementation details). As such, it requires a lot more effort and time to get through then “clojure for the brave and true”.


it is a really great book though, it’s by far the book I’ve referred back to the most in the years I’ve done Clojure


yeah, brave and true is a very easy read


I meant The Joy of Clojure 🙂


i was referring to your statement >As such, it requires a lot more effort and time to get through then “clojure for the brave and true”.


agreeing on the notion that "brave and true" does not take a lot of effort to read through


prefer paper or digital? 😄

Drew Verlee16:02:52

ideally i would pair reading a book with some interactiveness either by trying code snippets or asking questions. Sometimes its nice to just read through a book though 🙂

Drew Verlee16:02:23

brave and true lends itself to trying things out. i recall just reading joy of clojure like a book. incidently i recall a lot less of whats in it 😕


i don't ever work through a book without coding every single snippet myself


if i get stuck, i go deeper into that, instead of just continuing

Drew Verlee16:02:50

if your into web development. i’m currently really excited about fulcro


which is why i take a while to work through books


brave and true style doesn’t really cater to me, even when starting out I found TJoC to be a better fit cause it is much more formal

Drew Verlee16:02:24

Whats great is, most of the authors of clojure books hang out in this slack. so asking questions is easy 🙂


@U3L6TFEJF one thing i dislike is the tendency to meme


i come to ignore that stuff, but its distracting


though i appreciate that its going for a lighter tone

Drew Verlee16:02:46

Yea. i think brave and true is aimed at being fun and light hearted. Get you feeling like “yea, this isn’t scary”. I think its safe to recommend because if your put off by that, your also the kind of person that will find the other resources on your own. but if your a newcomer thats not really invested and i push joy of clojure on you and ask you to “figure it out yourself” your probably going to just walk away.

Drew Verlee16:02:55

living clojure is probably the more light weight more formal version of brave and true.


"Joy" is very much a "why" book about Clojure and functional programming. It's a wonderful book (and the 1st ed was my first Clojure book -- and I have the 2nd ed as well now), but I had Lisp / FP background. Take a look at the 3rd ed of Clojure Programming in Beta right now as well.


do you guys prefer the paper versions or the digital versions?


i do have a paperwhite, but technical books read horribly on those things


I have a handful of tech books in print form. I have literally hundreds in PDF form, all on OneDrive so I can read them on my phone, tablet, laptop, and desktop wherever I am.


I prefer paper copies, TJoC is one of the few books that survived my last book cleanout 🙂

Drew Verlee03:02:22

it doesn’t handle entire cups of coffee though


I'd try to build something tbh


well, im doing that anyways


but i like to have something at the side to work through


p.e. im a front end dev, im constantly building something both professionally and personally, but i still like to work through javascript books from time to time


to get a new perspective

Drew Verlee16:02:36

cross posting from spacemacs because i figure this is really basic. How do you work in multiple Clojure projects at once in spacemacs? have two repls open, etc…

Drew Verlee16:02:43

it looks like for my setup. projectile switch project works.

Drew Verlee16:02:48

i mean, you should open a repl per project right?


Hi all, is there a merge-with-like function that let's you determine which function to apply based on the keys of the maps you're merging?


Never mind, I wrote my own version... Turned out to be easier than I thought.


Are ordered-sets the best way to have priority queues in clojure?


Is there an official spec for this data structure?

Alex Miller (Clojure team)18:02:10

do you mean like a specification or a clojure.spec.alpha spec?

Alex Miller (Clojure team)18:02:00

if the latter, then no, as this code greatly pre-dates the existence of spec. but it’s pretty generic. it’s a map of any? to something comparable (I would need to think about what the best way to spec the latter is)


@wushee I haven’t read joy of clojure but I’ve been enjoying clojure applied. (thanks @alexmiller!) for learning some deeper aspects of the language for real world projects.


speak of the devil:


This is just to let you know that Programming Clojure, Third Edition (eBook) has recently been updated. You own an electronic version of this book, and so you'll be able to download this latest version.

Changes in This Release
The book is complete and has been through production. Now it’s on to layout and the printer.

Alex Miller (Clojure team)20:02:00

Nice! You found out before I did! :)


haha. well congratulations!

Alex Miller (Clojure team)20:02:02

afaik, that’s the final version that will go to print other than the layout adjustments.


this has been my favorite clojure book written. i really enjoy it. you should be very proud

Alex Miller (Clojure team)20:02:34

thanks!! To be fair, Stu and Aaron really “wrote” most of it. It’s the book I used to learn Clojure from!

Denis G21:02:25

Does anybody know whether or not I am not allowed to start a repl while having (read-line) or regex in code? Example: Error message:

[{:type clojure.lang.Compiler$CompilerException
:message java.lang.NullPointerException, compiling:(test_project/core.clj:217:1)
:at [clojure.lang.Compiler load 7526]}
{:type java.lang.NullPointerException
:message nil
:at [java.util.regex.Matcher getTextLength 1283]}]
(let [[n k] (->> (clojure.string/split (read-line) #" ")
(map #(Integer/parseInt %)))
... )

Alex Miller (Clojure team)21:02:40

if that code is at the top level, then it’s going to be evaluated when the namespace is loaded and seek input

Denis G21:02:46

I guess I was having a compile error 😅

Drew Verlee22:02:27

is the best way to add out dependencies and not lose system state (not have to restart the repl) to use pomegranate? it seems a bit heavy handed to have to list the repository once in the project.clj and then again at the command line.

Drew Verlee22:02:10

i feel like i’m probably missing some easier way via some toolchain


there’s alembic which implicitly uses (and even updates) your project.clj


it also uses pomegranate under the hood

Drew Verlee22:02:39

i also feel like i keep asking this question. forgetting what ppl said. then asking again like a month later.

Drew Verlee22:02:49

right alembic. fml. thats what i was supposed to be using


big caveat: neither alembic nor pomegranate work for updating a dep version - for that you need some kind of fancy OSGi nonsense, or to just restart the repl

Drew Verlee22:02:10

hm. ok. that i come across less often but its good to know


Every time someone mentions alembic, I have to remember not to think this one:


Which is a graphics interchange format used in visual effects and animation shops.


@drewverlee If you use Boot, you can just say (boot.core/merge-env! :dependencies '[[something "RELEASE"]]) and it'll be loaded into your running REPL.

Drew Verlee23:02:20

when i add something to my lein ~/.profile.clj under :user :dependencies is that ‘available’ in user namespace?


Leiningen requires a restart. Boot does not.


With Boot you can start a REPL anywhere, with any dependencies you want, and add extra dependencies while you work.

Drew Verlee23:02:55

@seancorfield thats good to know. maybe i would be better off using boot for things that aren’t coupled to lein in some way


We switched from Leiningen to Boot at work back in... I'd have to go look it up... and it's been so much more pleasant to work with!


(end of 2015 was when we switched)

Drew Verlee23:02:12

Is there any reason why boot isn’t going to play nice with the new git deps functionality they added?


I maintain boot-tools-deps which already supports all of that.


One of the things I love about Boot is how easy it is to experiment with a new library, without needing to set up a project or any plugins in your user config etc. Just boot -d whatever/library repl and you have a REPL with that dependency loaded and available! And you can easily add more libraries in the REPL with the merge-env! function.


(much like you can do with clj and the -Sdeps argument -- although you can't easily add deps once your REPL is running)

Drew Verlee23:02:40

If i want to use my editor, then i would just connect to that repl i take it?


Yup, most editors that have REPL integration know how to start Boot instead of Leiningen (but may need some settings changed to do that).

Drew Verlee23:02:49

any ideas why cider wont pick up on finding functions in my namespace when i use boot?

Drew Verlee23:02:35

i guess i should take this to #boot