This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-09
Channels
- # beginners (205)
- # boot (6)
- # cider (22)
- # cljs-dev (41)
- # cljsrn (4)
- # clojure (97)
- # clojure-dev (61)
- # clojure-greece (40)
- # clojure-italy (8)
- # clojure-russia (16)
- # clojure-spec (18)
- # clojure-uk (34)
- # clojurescript (14)
- # community-development (1)
- # cursive (45)
- # datomic (39)
- # fulcro (66)
- # jobs (2)
- # lein-figwheel (1)
- # lumo (9)
- # off-topic (8)
- # parinfer (98)
- # portkey (8)
- # re-frame (81)
- # reagent (54)
- # remote-jobs (17)
- # ring (2)
- # shadow-cljs (217)
- # spacemacs (32)
- # sql (24)
- # test-check (6)
- # unrepl (73)
- # yada (12)
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 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])
boot.user=>
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])
)
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'...
Nope, haha. But is it possible though to construct a function that allow both (optional) kwargs and a map?
Nevermind, found your answers here @seancorfield https://groups.google.com/forum/#!topic/clojure/yzLCZh-GiQ8, haha
@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.
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.
A 4clojure problem : http://www.4clojure.com/problem/15#prob-title
but now I see this error message : clojure.lang.ArityException: Wrong number of args (0) passed to: sandbox4852$eval183066$fn
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.
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
(#(* 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
(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})
and do this
Connecting to remote nREPL server...
Clojure 1.9.0
(use 'guestbook.db.core)
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) `
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"]]
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?
@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
.
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)
@pablore does https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentQueue.java work for you?
Is there a way to have a global (project independent solution) to being able to pick up changes to multimethods?
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 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
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.
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 clojure.tools.namespace
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
I kind of did that already though https://github.com/JoelSanchez/fast-repl-template
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
what was the question? i’m not sure i can still see it
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 java.io.FileNotFoundException: Could not locate yesql/core__init.class or yesql/core.clj on classpath., compiling:(guestbook/db/core.clj:1:1) `
did you add yessql to your project.clj as a dependency?
can you link the book for me?
I’m guessing thats the solution though 🙂
I added yesql but still this error message when trying (use 'guestbook.db.core)
on a repl
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
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.
I pushed the code to this repo : https://github.com/RoelofWobben/guestbook
Sorry roleof. For some reason i dont get updates on your threads. I’ll take a look. thanks
you might want to keep asking in beginners. is it web development version 2 or 1?
or asking #luminus
change [config.core :refer [env]
-> [guestbook.config :refer [env]
in guestbook/db/core.clj
i should read this book
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
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?
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’? 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
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
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 🙂
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 😕
if your into web development. i’m currently really excited about fulcro
#fulcro
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
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
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.
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 https://pragprog.com/book/shcloj3/programming-clojure-third-edition as well.
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 🙂
it doesn’t handle entire cups of coffee though
I'd try to build something tbh
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
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…
it looks like for my setup. projectile switch project works.
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?
do you mean like a specification or a clojure.spec.alpha spec?
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.
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.
Nice! You found out before I did! :)
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
thanks!! To be fair, Stu and Aaron really “wrote” most of it. It’s the book I used to learn Clojure from!
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 %)))
... )
if that code is at the top level, then it’s going to be evaluated when the namespace is loaded and seek input
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.
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
i also feel like i keep asking this question. forgetting what ppl said. then asking again like a month later.
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
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: http://www.alembic.io/
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.
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.
@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)
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)
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).
any ideas why cider wont pick up on finding functions in my namespace when i use boot?
i guess i should take this to #boot