This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-10
Channels
- # announcements (2)
- # babashka (15)
- # beginners (174)
- # calva (16)
- # chlorine-clover (10)
- # clara (7)
- # clj-kondo (27)
- # cljdoc (10)
- # clojars (4)
- # clojure (50)
- # clojure-europe (10)
- # clojure-gamedev (3)
- # clojure-greece (1)
- # clojure-italy (4)
- # clojure-losangeles (1)
- # clojure-nl (16)
- # clojure-sg (1)
- # clojure-spec (7)
- # clojure-uk (41)
- # clojurescript (22)
- # data-science (15)
- # datascript (38)
- # datomic (2)
- # duct (15)
- # emacs (2)
- # fulcro (110)
- # funcool (9)
- # graphql (10)
- # jackdaw (8)
- # jobs (23)
- # joker (1)
- # leiningen (15)
- # luminus (1)
- # malli (20)
- # off-topic (26)
- # pathom (5)
- # pedestal (1)
- # reitit (19)
- # shadow-cljs (78)
- # spacemacs (2)
- # sql (52)
- # tools-deps (99)
- # vim (13)
Is there a way to read in a csv and assign the headers or first row to create a map with the headers as keys?
Clojure.data.csv is usually used to transform CSV data to Clojure data structures. https://github.com/metasoarous/semantic-csv parses CSV data and allows you to do more specific transformation and conversion.
@jdwoodsy1 in the README file of https://github.com/clojure/data.csv has a section about "parsing into maps"
@iagwanderson Thanks.
I have a list of functions (f g h)
and values (1 2 3)
and I want to get a sequence of values of evaluating the function to the argument of the same index, as in:
((f 1) (g 2) (h 3))
I thought this would work:
(map #(%1 %2) '(str inc) [1 2])
but it does not. I ended up doing this:
(map #(eval (list %1 %2)) '(str inc) [1 2])
("1" 3)
This seems overly verbose, and that I am missing something simple. Is there a more idiomatic way to do this?
(map #(% %2) [str #(* % 2)] [1 2])
=> ("1" 4)
It looks like you just numbered your first arg wronguser=> (map (fn [f arg] (f arg)) [inc dec +] [1 2 3])
(2 1 3)
#()
syntax is nice in the majority of cases when it works, but sometimes just using (fn [ ...] ...)
can make it easier to figure out how to make it work correctly.
Thanks both. One of the things I tried that I didn't post and didn't work was using a list of symbols for the functions rather than a vector of function (symbols?):
(map (fn [f arg] (f arg)) '(inc dec +) [1 2 3])
(nil nil nil)
converting to a vector gives me nils as well:
(map (fn [f arg] (f arg)) (vec '(inc dec +)) [1 2 3])
(nil nil nil)
So I think my question refines down to "what is the difference between a vector of functions and list of quoted symbols in this case?"
Resolution of the symbol to the actual value.
Thank you @seancorfield --- I haven't seen resolve
...
'inc
is the symbol named inc
. inc
(no quote) will be evaluated by Clojure -- resolved to the symbol's current bound value. In this case clojure.core/inc
is bound to a function (value) that increments its argument.
That makes the #()
formulation work too:
(map #((resolve %1) %2) '(inc dec +) [1 2 3])
(2 1 3)
Yes, #()
is just shorthand for (fn [,,,] ,,,)
Back to '(x y z)
vs [x y z]
-- the former is a quoted list so it is not evaluated; the latter is a vector of values so the symbols are looked up (resolved). '[x y z]
is also quoted and not evaluated.
I'm not into macros yet, but I have a question for this specific problem, would be easier to handle this list of symbols inside a macro? even avoiding the resolve
call?
(list x y z)
would evaluate the elements, resolving the symbols to their bound values.
@iagwanderson macros just rewrite code to code - they don't evaluate anything (they are executed at "read" time, before code is compiled and then executed).
yeah, I changed my eval for resolve and it looks like the same as the map version
(defmacro custom-map [fs args]
(list 'map '(fn [v arg] ((resolve v) arg)) fs args))
You don't need a macro for that.
For completion, that also explains why I was getting nil
values out. I was evaluating things like ('inc 2)
which yields nil
. I don't understand why having a "symbol named 'inc'" in the function postion in a list passed to the evaluator returns nil
though...
Because it looks itself up in its argument, as if it were (get 2 'inc)
which returns nil
.
user=> ('inc 2 :not-found)
:not-found
user=> (get 2 'inc :not-found)
:not-found
Keywords and symbols look themselves up in their argument, in the same way that maps and sets look their argument up inside themselves. It makes working with associative data structures very easy.
So, to state in my own words: inc
is the name of the symbol 'inc
.
In the sexp type into the repl (inc 2)
In the repl, you use the name, inc
. The name will resolve to the symbol
'inc
.
-----------------
| name | symbol |
-----------------
| inc | 'inc |
-----------------
That symbol 'inc
is associated with a function val
in a var
:
------------------------------
| var |
------------------------------
| symbol | val |
------------------------------
| 'inc | #'clojure.core/inc |
------------------------------
And then, the function at #'clojure.core/inc is put into the function position of the Abstract Syntax Tree, and 2 is put into its first argument position, and then evaluated.
Is that correct? Are there two levels of indirection going from the text in the repl -- looking up the symbol from the name inc
, and looking up the function from the symbol 'inc
?Thanks for this... this seems different from Sean's explanation of 'inc
as symbol, and inc
as name...
The evaluator (the compiler) says the meaning(the result of evaluating) of (quote inc)
is the symbol inc
Treating these thinks precisely takes a lot of care and it is very common for experienced clojure programmers to gloss over the details because everyone knows what you mean
Makes sense. These questions are helping clarify this a bit, I think...
so thanks
When Sean said 'inc
is the symbol named inc
what he meant was the evaluator evaluates 'inc
to the symbol inc
ah, ok, that helps. inc
is the symbol then...
Quoting is a general facility that can be applied to anything you pass to the evaluator
and +
is a symbol, not the name of the symbol...
Thanks. I thought I had symbols understood until I encountered the concept that symbols have names, which is not the same as the symbol itself...
The evaluator either resolves symbols to a var (something def'ed) or a local (something let bound or a function parameter)
Like, technically, symbols do also have names, the name of the symbol inc
is the string "inc"
Now, the var
has a value, correct? Like the symbol inc
maps to a var
that has a value, which is the function that increments a number. If I "rebind" the symbol inc
, do I point it at a different var, or do I stick a different function in the value of the var
? Or is that non-sensical?
Symbols are technically composed of a namespace part and a name part. So the symbol inc
has the name "inc"
and the namespace nil
while the symbol clojure.core/inc
has the name "inc"
and the namespace clojure.core
(the namespace part of a symbol is itself represented as a symbol)
When the evaluator encounters a symbol it from context figures out if the symbol is the name of a local (let bound, function parameter) or needs to be resolved (again using some context) to a var(something defined using def or some derivative)
A var is sort of a little mutable cell, like a 1 element array, so you can override it's value, or you could just have a local, the exact behavior will depend on what you mean by rebinding
ok, thanks. In your previous paragraph, then, for the symbol inc
with the namespace of nil
, is that the case when inc
is the name of a local?
ok, makes sense, you look to see if a symbol has a local binding, and if so, use that value. if not, you have to walk up to enclosing environments to find something it is bound to (a namespace, or possibly another local binding that encloses the first one)...
A wrinkle here is clojure is the evaluator compiles to jvm byte code and them hands the byte code to the jvm to run. All the symbol resolution stuff the evaluator does happens at compile time
To the above statement that inc
has a name of "inc"
and a nil
namespace, and the symbol clojure.core/inc
has the name "inc"
, then when I use inc
in the repl, how does it know to choose the clojure.core
namespaced one, and not the first one?
Thanks for your time here... I think I need some paper that lays this out somewhere, I'll see what I can find. If you have a resource that lays this out somewhere, I'd be happy to read it...
When reading the text of the expression in the REPL, the Clojure reader gets a symbol, and a number, which you can check yourself like this:
user=> (def tmp (read-string "(inc 2)"))
#'user/tmp
user=> (map class tmp)
(clojure.lang.Symbol java.lang.Long)
A bit confused... from above, if inc
is the name, how does the reader get the symbol 'inc
? Assuming I am interpreting that correctly. I assume if inc
is the name, there has to be some lookup path from name -> symbol -> var value...
Doing eval
on a symbol looks up a table of names in the current namespace (or in the namespace that is the prefix in the symbol, e.g. foo.bar/inc), e.g.:
user=> (eval 'inc)
#object[clojure.core$inc 0x426b6a74 "clojure.core$inc@426b6a74"]
user=> (class (eval 'inc))
clojure.core$inc
user=> (instance? clojure.lang.IFn (eval 'inc))
true
When Clojure is given a list in parentheses to evaluate, without a leading '
, and the first element does not name a macro, it evals all elements of the list, including the first, then invokes the function that is the value of the first expression.
I'm getting closer. One thing that seems odd is that the following is equivalent then:
sess3=> (eval 'inc)
#object[clojure.core$inc 0x7fbdb403 "clojure.core$inc@7fbdb403"]
sess3=> (eval inc)
#object[clojure.core$inc 0x7fbdb403 "clojure.core$inc@7fbdb403"]
functions (like most things) evaluate to themselves so the second eval returns the same thing
quote means "read, but don't evaluate"
so 'inc is read (as a symbol), the end
inc is read as a symbol, then evaluated. in general, everything in Clojure evaluates to itself, with the with the two main exceptions: symbols and lists
symbols, evaluate to what they refer to in the scope of the current namespace
(lists evaluate args, then invoke the first element)
and now you know 90% of the Clojure evaluation model
(macros being the next 9%)
Thanks! In a side channel, I'm working through the concept of a symbol vs. the name of the symbol, which I keep tripping on...
(is that the last 1%?)
symbols are names the way I think about it
(the last 1% is all the other special cases which we won't talk about :)
fair 🙂
I'm curious about best practices around calling APIs with Clojure. The code looks nice and elegant when just making the http request, but I'm not sure where to put the "parse the resulting json" code and the "http error handling" stuff.
It looks like clj-http will automatically handle the json parsing, so now it's just a question of best practices on error handling.
I typically use a cond
to check the HTTP status code and handle the error as appropriate. This usually means monitoring/reporting of some sort.
https://clojure.org/guides/learn/syntax#_evaluation might be helpful
I'll go back and re-read, but I read through "Joy of Clojure", and I don't have it here in front of me, but I recall the mention of names of symbols as distinct from the symbols, and I think the material difference was that you could associate metadata with one but not the other. I don't recall which one...
you can associate metadata with symbols
if I have a vector of maps like:
[{:firstname "test",
:lastname "test"}
{:firstname "test1",
:lastname "test2"}]
how can I get a new vector of maps with only the firstname in map ?
(mapv #(select-keys % [:firstname]) data)
Or do you mean (mapv :firstname data)
to get just a vector of first names?
thanks @seancorfield, this was just what I was looking for,. Just switching to clojure and had been figuring out this for a while now 🙂
Hi, using the carmine library for redis I wanted to scan and match some keys and found out I need to use the accumulator to get the whole output, seems like it's already implemented in carmine, but I don't know how to use it: https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine.clj#L750 In particular I don't understand what rf refers to, can anybody help?
rf
usually refers to a reduction function. So a function that takes the accumulated value, and the current, and produces a new accumulated value
So I need to provide my own function? I thought carmine would take care of that and I just give it my scan function, I'm a bit lost right now 😅
hi people I am live streaming my work. I am not advanced clojurescript guy but might be usefull for newbies
any opinions on the pros/cons of something like this let-map
macro?
https://gtrak.wordpress.com/2012/06/11/separation-of-concerns-or-let-map-birth-of-a-clojure-macro/
@UHK8B8STX I find the end result much harder to read. I think let-map
tries to be far too clever.
There are some libraries out there that have some variant of a "locals" macro for constructing hash maps from local bindings which is the core of what this is doing, but without all the destructuring magic.
For example, here's what we have at work https://github.com/worldsingles/commons/blob/master/src/ws/clojure/extensions.clj#L148
&env in the wild! Very good. I like the way local-map
gives control back to the caller, instead of wrapping let.
imo, the code before the macro was easier to read
maybe working more on the signature of some-magic-parsing-fn function would have been more profitable than correcting the results, not sure
my general suggestion would be - don't be too quick to dismiss obviousness :)
but that's more about the interface of the macro - overloading (let [x y])
without having a body using the bindings.
If there was a map literal declaration that let me access previous values, I'd probably use it here.
Is there a way to access the forms in a clojure.lang.ReaderConditional
?
So in the result of something like (read-string {:read-cond :preserve} "#?(:cljs (+ 1 2) :clj (+ 2 3)))")
@U050ECB92 Is there a way to obtain this information generally for clojure objects or you looked at the clojure source code?
in this case, no there is not an easy way to determine this without being told as the object implement lookup, but not the rest of the map contract
in this case, the ReaderConditional object is really a thin wrapper around a map-ish object with lookupable :form and :splicing? (a flag)
I don't honestly remember now why we made an object for this rather than just making a record or something, which seems like it would have been sufficient
yeah, that might have been it
I’m trying to wrap my mind around transducers — what’s the difference between sequence
and eduction
? Reading the source code didn’t help that much 😕
@teslanick common: they are both contexts where a transducer can be applied. Both presume that the source collection is at least iterable different: sequence caches realization of the xf+collection, eduction does not
(defn less-promises-eduction [xform coll]
(reify clojure.lang.IReduceInit
(reduce [_ f init]
;; NB (completing f) isolates completion of inner rf from outer rf
(transduce xform (completing f) init coll))))
one could imagine a variant of eduction that didn't require anything of the underlying collection except that it is reducible
I’m trying to get a handle on transducers by reimplementing them in a more familiar environment (JS) using a relatively familiar-to-me primitive (generators). Thus far it is going adequately well. The explainer on the Clojure website is kinda hard to grok in theory, but messing around in the repl makes it somewhat more obvious what’s going on, poking at a reimplementation makes it easier to see the holes in my understanding
I want to create a plot with a value distribution as follows: From week 0 to week 18, distribute the necessary goal weight for each week to hit a certain end goal by week 18. This is going to be used for a fun graph and bet with a coworker who is also trying to loose some weight. Basically I want to have weigh-ins every week and a small penalty if you're above the goal weight for that week
This function gets me pretty close:
(defn weigh-in [starting-weight]
(->> (range weeks-remaining)
(map #(hash-map :week % :goal-weight (- starting-weight (* 0.8 %))))))
is there any easy way to parse/read keywords in a namespace? So I can iterate over them? Otherwise I need to copy every used keyword in that file/namespace and put in a list manually, which I don't want to do
There are ways, but the difficulty of doing it correctly depends upon how general you want to be across all legal Clojure code constructs, or just one file that has a limited subset of Clojure features used (and which ones those are).
e.g. the clj-kondo and Eastwood linters can read most Clojure source code, as can clojure.core/read
, with the potential down side that clojure.core/read
can have side effects of executing arbitrary code. That is not a problem if it is your own code, and you know it doesn't do dangerous things when you read it: https://clojuredocs.org/clojure.core/read
oh, there is no dangerous stuff going on actually
It can be made more challenging if the code uses keywords like ::foo
or aliases, e.g. :my-alias/bar
-- if your code doesn't use those, then you don't have to worry about that.
I bring it up to warn you. If you are doing this for your own personal code, no worries. If you want to publish a tool to do this and run it on arbitrary Clojure source code, you might want to be safe, or at least have your documentation warn people of the dangers.
ok i'll be careful. thanks
If your file doesn't use ::foo
nor :my-alias/bar
, and you want to be open to potential arbitrary code execution, clojure.core/read
repeatedly run on a file should get all of the source code forms as Clojure data, e.g. nested lists, vectors, maps, symbols, keywords, numbers, etc.
If your code does use ::foo
and/or :my-alias/bar
then clojure.core/read
should work after evaluating the appropriate ns
forms, e.g. the one at the top of your source code file.
they will be expanded into their fully qualified versions
what about something like ns-map
? this one returns everything in java. So if it is on runtime, it can't be clojure code anymore?
Actually in my case I use these keywords as an enum and string representations. Only in one def I have
(def products {::car "Car" ::ps4 "PS4"})
The return value from ns-map does
s not contain the full code of the namespace, and thus not the keywords in your code.
What I really want is to get these ::car
and ::ps4
and iterate over them
because in the future I will add another product to that map
Clojure does not store the forms read when it loaded your code anywhere.
Actually I just realised I can simply get the keys of that map
The data structures it reads are temporarily in memory while the Clojure compiler compiles it to JVM byte code (or JavaScript in the case of ClojureScript), but then that data is discarded.
Sure, if there are particular data structures of your code that have the keywords you care about, then just walk the contents of those data structures.
My answers were assuming that there were keywords throughout your code, and you didn't want to miss any of them, but that is a more difficult problem to solve correctly.
true, you don't have to define them in one place, you can put them wherever you want
(keys my-map)
returns a sequence of all keys in the map my-map
. Keys of maps can be any Clojure value, e.g. numbers, lists, strings, keywords. The function keyword?
returns true exactly when its argument is a keyword, vs. something else.
I don't know exactly what problem you are trying to solve, and how general you want to be about it.
keys
actually worked for me
OK. Sorry for leading you down the garden path, but I was taking you at your word that you wanted the generality of finding all keywords in a namespace. Finding all keys in a single map at run time -- much easier.
No it's my fault actually. I was searching how to parse/read it since yesterday for no reason
But thank you anyway it helped a lot to understand what's going on behind the scenes. sorry for the misunderstanding though
Clojure has quite a few functions built in for manipulating maps, vectors, lists, sets, etc. The Clojure cheatsheet tries to categorize what kind of functions are useful for what kinds of data structures, and may be helpful: https://clojure.org/api/cheatsheet
Clicking on the "source repo" link on that page gets you to other variants of it, e.g. ones that let you narrow down the list of results by typing a string, and showing you the doc strings just by hovering the cursor over the function name.
this is nice!
I put it on my bookmarks
I cannot find any vars in my namespace even though they are there. I have stuff like
(def main-workflow-file (atom []))
(def five 5)
but when I do (dir my.namespace)
I just get nil. What am I doing wrong?how are you loading your namespace?