This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-08
Channels
- # aatree (3)
- # announcements (1)
- # architecture (5)
- # beginners (27)
- # boot (22)
- # cider (17)
- # cljsrn (8)
- # clojure (93)
- # clojure-canada (1)
- # clojure-dev (7)
- # clojure-nl (10)
- # clojure-poland (216)
- # clojure-russia (35)
- # clojurescript (163)
- # community-development (6)
- # cursive (25)
- # datavis (6)
- # datomic (18)
- # dirac (10)
- # dysphemism (4)
- # editors (3)
- # editors-rus (1)
- # emacs (15)
- # hoplon (124)
- # instaparse (25)
- # jobs (10)
- # ldnclj (78)
- # lein-figwheel (11)
- # leiningen (6)
- # off-topic (20)
- # om (149)
- # onyx (2)
- # parinfer (5)
- # portland-or (1)
- # proton (62)
- # quil (2)
- # re-frame (8)
- # spacemacs (4)
- # yada (20)
Anything can be a key in a map but typically you use keywords as they resolve to their own identity everytime and they are useful as they implement IFn
to look themselves up in a map.
Hi, I'm looking for a function that is equivalent to PHP's compact()
or ES6's “object literal property value shorthand”, which take a list of variables/symbols that exist in the current scope and return a map with the names and values of each one.
Here's what I came up with:
(defmacro compact
[& args]
(let [keys (map keyword args)
vals `(~@args)]
(zipmap keys vals) ))
; Example
(let [artist "The Beatles"
track "Let It Be"]
(compact artist track))
; => {:artist "The Beatles", :track "Let It Be"}
Surely there has to be a built-in function or a more idiomatic way to do this with Clojure?
You don’t need the macro. You can just do (zipmap (map keyword [keyword-vec]) [vals-vec])
.
@raphaelsaunier: That looks like a reasonable solution to me, though you could avoid using a macro by passing in symbols and using eval
. For the record, here's my version of your macro: (defmacro compact [& args] (into {} (map (juxt keyword identity) args)))
.
@akiva, right, but is there a way to generate keyword-vec
programatically? I only ended up using a macro because with functions I could only get the values of the symbols but not their names…
I think it would be better to implement it as a function as a function, like (defn compact [& args] (into {} (map (juxt keyword eval) args)))
. Then you'd call it like (let [a 1 b 2] (compact 'a 'b))
.
@codonnell: nice! Hadn't thought of that!
As a function it's clearer you're working with the symbols, rather than their values.
Having said that, is there a more idiomatic way of solving this? I'm using this in a function that defines a couple of bindings and does a few computations within let
and then returns a map.
@raphaelsaunier: in clojure we rarely use those kind of "magic" macros that rely on locals names
@raphaelsaunier, I think @codonnell is on the right track here.
I wouldn’t try to use the binding symbols themselves but have that information as part of the val.
@raphaelsaunier: It's hard to say without more context. If there are too many variables to explicitly write the map, you should probably have them already grouped in a data structure which tells you what's what.
Thanks! Yeah sorry, I realised that my last question was a bit too vague after hitting enter. I'm not returning that many variables (<5), but it's just a convenience function that you get used to very quickly when writing ES6.
@codonnell: this should give you some more context: https://gist.github.com/raphaelsaunier/12d5f41cd0ca3eba82a2#file-api-clj-L41
That's how I would write your function, I think.
But maybe with slightly more correct parens.
Thanks! Yes obviously, but I get the gist!
Guys, totally a newbie question How can i edit a date object? (i want to add to hours)
@olegakbarov: Take a look at https://github.com/clj-time/clj-time it works really well for that
i sure did
alright — i just needed to parse the string 😅
(t/plus (f/parse iso-8601 2016-02-06T12:45:00) (t/hours 2))