Fork me on GitHub
#beginners
<
2018-02-09
>
hawari03:02:39

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])

hawari03:02:07

I need to kinda "filter out" unwanted kwargs here

hawari03:02:32

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

hawari03:02:25

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?

seancorfield03:02:59

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.

seancorfield03:02:00

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.

hawari03:02:01

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

seancorfield03:02:16

The let form sort of "works by accident".

seancorfield03:02:06

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

hawari03:02:12

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?

seancorfield03:02:25

Yes, exactly that.

hawari03:02:28

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

seancorfield03:02:07

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])
boot.user=>

hawari03:02:35

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

seancorfield03:02:06

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

hawari03:02:55

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

seancorfield03:02:51

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.

seancorfield03:02:06

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

seancorfield03:02:10

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

hawari03:02:17

I see, I'll look into it

hawari03:02:10

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?

seancorfield03:02:18

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]

seancorfield03:02:03

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

hawari03:02:09

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

hawari03:02:50

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

seancorfield06:02:06

@hawari.rahman17 And since then I've evolved the clojure.java.jdbc 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.

roelof06:02:04

good morning all

hawari06:02:22

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.

roelof07:02:59

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

roelof07:02:31

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

roelof07:02:44

where do I took the wrong path

hawari07:02:55

I thought that you just have to type * 2?

hawari07:02:04

Works for me that way

andy.fingerhut07:02:08

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

andy.fingerhut07:02:25

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

andy.fingerhut07:02:03

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

andy.fingerhut07:02:18

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.

roelof07:02:51

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

hawari07:02:05

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

hawari07:02:32

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

roelof07:02:10

both thanks

hawari07:02:37

(#(* 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

roelof08:02:32

im also trying the webdevelopment with clojure book

roelof08:02:02

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

roelof08:02:05

(ns guestbook.db.core
(:require
  [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})

roelof08:02:50

I connect my repl into the development repl of luminus

roelof08:02:26

and do this

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

roelof08:02:51

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

roelof09:02:53

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"]]

roelof09:02:16

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

joshkh12:02:36

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?

joshkh12:02:55

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

Richard13:02:16

@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.

joshkh13:02:39

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.

Richard13:02:45

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

joshkh13:02:20

oh, thanks!!

pablore14:02:01

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

pablore14:02:22

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)

moxaj14:02:03

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

pablore14:02:30

@moxaj what would you use?

pablore14:02:06

@sundarj I think that may

pablore14:02:16

Gonna try it real quick

pablore14:02:36

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

pablore14:02:25

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

moxaj14:02:57

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

pablore14:02:17

:c sadness

moxaj14:02:52

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

pablore14:02:24

What about a PersistentQueue of <type>

moxaj14:02:14

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

pablore14:02:42

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

moxaj14:02:46

well, not the expression, but the function

drewverlee15:02:12

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

drewverlee15: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.

joelsanchez15:02:31

I'd use clojure.tools.namespace.repl/refresh: it will reset the state of the reloaded namespaces but you don't have to restart your REPL / reset the state of unaffected namespaces

drewverlee15: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.

drewverlee15: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

joelsanchez15:02:01

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

joelsanchez15:02:20

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

joelsanchez15:02:41

and just lein repl into it and write and reload code

drewverlee15:02:05

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

joelsanchez15:02:22

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

roelof16:02:16

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

drewverlee16:02:46

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

drewverlee16:02:16

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

roelof16:02:27

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

roelof16:02:34

on Windows

drewverlee16:02:32

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

roelof17:02:13

Nope that was not mentioned in the book

drewverlee17:02:00

can you link the book for me?

drewverlee17:02:11

I’m guessing thats the solution though 🙂

roelof17:02:33

I use the "web development with clojure" book

roelof22:02:22

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

roelof22:02:22

error message : CompilerException java.io.FileNotFoundException: 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

drewverlee22: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.

roelof23:02:13

and hope that someone could help me solve this ?

drewverlee03:02:12

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

drewverlee03:02:18

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

drewverlee03:02:47

or asking #luminus

drewverlee03:02:14

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

drewverlee03:02:51

in guestbook/db/core.clj

drewverlee03:02:42

i should read this book

drewverlee03: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

roelof08:02:28

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

roelof08:02:41

where did you find it to change things

roelof08:02:54

it works but I cannot find any reference to this change

drewverlee14:02:18

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

tstelzer16:02:25

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

drewverlee16: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.

tstelzer16:02:49

hm, can you define 'broad and deep'?

tstelzer16:02:09

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

drewverlee16: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”.

schmee16:02:32

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

tstelzer16:02:41

yeah, brave and true is a very easy read

schmee16:02:02

I meant The Joy of Clojure 🙂

tstelzer16:02:21

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”.

tstelzer16:02:41

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

tstelzer16:02:18

prefer paper or digital? 😄

drewverlee16: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 🙂

drewverlee16: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 😕

tstelzer16:02:25

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

tstelzer16:02:48

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

drewverlee16:02:50

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

tstelzer16:02:54

which is why i take a while to work through books

schmee16:02:06

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

drewverlee16:02:24

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

tstelzer16:02:33

@U3L6TFEJF one thing i dislike is the tendency to meme

tstelzer16:02:52

i come to ignore that stuff, but its distracting

tstelzer16:02:33

though i appreciate that its going for a lighter tone

drewverlee16: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.

drewverlee16:02:55

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

seancorfield17:02:09

"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 https://pragprog.com/book/shcloj3/programming-clojure-third-edition as well.

tstelzer18:02:59

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

tstelzer18:02:20

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

seancorfield18:02:13

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.

schmee18:02:05

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

drewverlee03:02:22

it doesn’t handle entire cups of coffee though

joelsanchez16:02:54

I'd try to build something tbh

tstelzer16:02:42

well, im doing that anyways

tstelzer16:02:51

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

tstelzer16:02:05

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

tstelzer16:02:13

to get a new perspective

drewverlee16: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…

drewverlee16:02:43

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

drewverlee16:02:48

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

jlmr16:02:50

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?

jlmr16:02:56

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

pablore16:02:28

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

pablore18:02:53

Is there an official spec for this data structure?

alexmiller18:02:10

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

alexmiller18: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)

bwstearns19:02:23

@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.

dpsutton20:02:28

speak of the devil:

dpsutton20:02:33

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.

alexmiller20:02:00

Nice! You found out before I did! :)

dpsutton20:02:59

haha. well congratulations!

alexmiller20:02:02

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

dpsutton20:02:47

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

alexmiller20: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 Compiler.java 7526]}
{:type java.lang.NullPointerException
:message nil
:at [java.util.regex.Matcher getTextLength Matcher.java 1283]}]
Code:
(let [[n k] (->> (clojure.string/split (read-line) #" ")
(map #(Integer/parseInt %)))
... )

alexmiller21: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 😅

drewverlee22: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.

drewverlee22:02:10

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

noisesmith22:02:28

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

noisesmith22:02:34

it also uses pomegranate under the hood

drewverlee22:02:39

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

drewverlee22:02:49

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

noisesmith22:02:48

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

drewverlee22:02:10

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

gonewest81822:02:41

Every time someone mentions alembic, I have to remember not to think this one: http://www.alembic.io/

gonewest81822:02:21

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

seancorfield22:02:52

@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.

drewverlee23:02:20

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

seancorfield23:02:39

Leiningen requires a restart. Boot does not.

seancorfield23:02:25

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

drewverlee23: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

seancorfield23:02:33

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!

seancorfield23:02:06

(end of 2015 was when we switched)

drewverlee23:02:12

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

seancorfield23:02:31

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

seancorfield23:02:37

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.

seancorfield23:02:16

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

drewverlee23:02:40

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

seancorfield23:02:26

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

drewverlee23:02:49

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

drewverlee23:02:35

i guess i should take this to #boot