This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-03
Channels
- # aleph (1)
- # announcements (9)
- # babashka (3)
- # beginners (200)
- # calva (22)
- # cider (74)
- # clojure (97)
- # clojure-dev (43)
- # clojure-europe (15)
- # clojure-italy (4)
- # clojure-nl (4)
- # clojure-sanfrancisco (2)
- # clojure-uk (103)
- # clojuredesign-podcast (2)
- # clojurescript (45)
- # core-async (5)
- # cursive (13)
- # datomic (42)
- # emacs (20)
- # fulcro (6)
- # graalvm (37)
- # jackdaw (10)
- # leiningen (7)
- # mid-cities-meetup (3)
- # off-topic (2)
- # pathom (1)
- # pedestal (3)
- # re-frame (6)
- # reagent (38)
- # reitit (5)
- # shadow-cljs (117)
- # spacemacs (1)
- # sql (1)
- # tools-deps (17)
- # vim (14)
- # xtdb (18)
Hello again, this is probably a really dumb question. I know map is such a common function in Clojure but I'm having trouble wrapping my head around it or something. I have a function akin to this:
(defn update-thing
[my-maps]
(map
(fn
[x]
map #(update x (key %) (str (val %) "somethingelse")) x)
my-maps))
And essentially this part (str (val %) "somethingelse")
is doing nothing. My expectation is that the inner map
function will be called on the seq that is the product of the outer map
function but I think I'm misunderstanding. Put simply for each hash-map in my-maps
I want to replace the value of each element in the hash-map with something else that's based on the existing value. For my example I just put (str (val %) "somethingelse") as something arbitrary. However I just get back the same values as the original my-maps
.@heatonsam The function that you're mapping over my-maps
isn't doing anything useful
(fn [x]
map ; evaluates to the function and is then ignored
#(update x (key %) (str (val %) "somethingelse")) ; evaluates to a function and is then ignored
x) ; returns the input value x
First off, are you trying to map a function over a sequence of sequences, that would need you to map
-over-`map`?
ugh, I am missing parens again around the inner map, I see that now.
my-maps
is what? A sequence of hash maps? In which case you don't want map
-over-`map` -- just a single map
over the sequence is enough.
it's a sequence of hash-maps yes
And what are you trying to do to each hash map?
I want to replace each value in each hash-map with a new value that includes the previous value, for example's sake a string concatenation like above
OK, so you want to figure out the function that is applied to each hash map -- and then just call map
using that over the sequence.
That headline seems to describe my mistake exactly
thank you
And you want to replace every value in each hash map?
yes, which is why I thought I should map
over them again
Probably the easiest way to process a hash map and apply a function to each key and/or value is reduce-kv
(reduce-kv (fn [m k v] (assoc m k (str v "somethingelse"))) {} a-hash-map)
That will process a single hash map and replace every value.
Then you just
(map #(reduce-kv (fn [m k v] (assoc m k (str v "somethingelse"))) {} %) my-maps)
thank you
that's much cleaner
I will read Stuart's article as well.
worked perfectly
If you do find yourself wanting to treat a hash map as a sequence of MapEntry
pairs, you can also do
(into {} (map (fn [[k v]] [k (str v "somethingelse")]) my-maps))
using destructuring to separate the key and the value, or the transducer version (which is very similar but is easier to compose)
(into {} (map (fn [[k v]] [k (str v "somethingelse")])) my-maps)
hey team! im super confused by this
user=>
(assoc-in {} [:id] (str (java.util.UUID/randomUUID)))
{:id "ee01c6a7-7692-485e-b125-a76a7908a993"}
user=>
(defn uuid [] (str (java.util.UUID/randomUUID)))
#'user/uuid
user=>
(assoc-in {} [:id] uuid)
{:id #object[user$uuid 0x6a244dbe "user$uuid@6a244dbe"]}
user=>
You are not calling uuid
, you're just using the function name.
(uuid)
would be calling it.
NP. These things often take a new set of eyes.
ok another one. last one i swear! why would a json include a namespace?
{
"patents/name": "Matt's Workout",
"patents/id": "8fa24c8d-2f78-47cc-9e46-bc339705dadb"
}
Was the json file created by a call you made to a Clojure function that writes it? Or did someone else provide it to you?
If you created it from the contents of a Clojure map, perhaps the keys in one or more of your maps have namespaces in the keys?
e.g. {:patents/name "Matt's Workout"}
seems possible -- I believe several Clojure libraries for dealing with databases have options to include/exclude such things.
and/or some existing code you are using (perhaps developed by others?) is doing that custom on its own.
i dont think it is that since i wrote everything haha 🙂 i think it is my inexperience with clojure and completely understanding it. ill dig more, thanks for helping me rubber duck andy!
https://github.com/seancorfield/next-jdbc/blob/master/doc/result-set-builders.md has some more rationale
(defn create
[db post]
(let [to-save (assoc-in post [:id] (repo-util/uuid))]
(sql/insert! db :patents to-save {:builder-fn result-set/as-unqualified-maps})))
@tjb Be aware that only PostgreSQL returns the whole newly inserted row. Other databases just return some representation of a newly inserted key from insert!
.
If you have a full stack app; as in, one with a back end and a front end. Is it advisable to separate out you code base's dependencies such that the clojurescript dependencies are in one project.clj
file and the clojure dependencies are in a different project.clj
file depending on the build tool you are using.
because when they are mixed up, sometimes it's hard to use lumo or Mike Fikes's plank
@franklineapiyo One of the benefits of using Clojure is that you can share code between the front and back end using .cljc
files so it's more common to have a single project containing both front and back end code in my experience.
Most of the full stack example apps I've seen have a single project control file in a single repo. That said, for large applications, I can imagine a front/back end separation (but I'm not sure what folks would do with shared code -- maybe have a third project and build sharable artifacts?).
(at work we use a monorepo anyway and CLI/`deps.edn` to manage each subproject -- but we don't use ClojureScript)
@seancorfield thanks for answering, so if you guys don't use clojurescript, do you use figwheel?
Nope. We looked at cljs years ago and it wasn't ready for prime time so we used JS for our front end. If we were starting over, we might reconsider that. I think, right now, I'd look at shadow-cljs first.
I keep meaning to take a more serious look at cljs. We've switched to the CLI/`deps.edn` at work (we switched from lein
to boot
back in 2015), so I'd have to figure out what's the best fit with the CLI tooling.
I think I went and confused myself. An implicit do
in a defn
would reach down through an if
and evaluate the forms in whatever branch the switch evaluates to in order, correct?
I am a little confused by the wording "through an if".
(defn f
[x]
(if (pred x)
true
false)
(prn x)) ; <= this will execute
But in the if
there are no implicit do
s. An if
can take one predicate and exactly 2 forms (actually, you can skip the else part too).
I meant if I had an if
that needs to branch out into two separate blocks of procedures, but yeah, thinking about it now I need to wrap it in a do
so if
doesn't complain about arity.
Yep. If either branch is more than one form, it needs do
or similar form (eg, let
) to wrap them.
(if (foo-p x)
;; true branch
(let [c (bar x)]
(println x "is foo-p-positive")
(baz c))
;; false branch
(do (thing-1)
(thing-2)))
Two alterantives to if with "implicit do" are when
and when-not
.
(when true
(allways-running-1)
(allways-running-2)
(allways-running-3))
Yeah, but with when
there is no else part. If you need both branches, if
with do
is arguably better than using when
and when-not
one after the other.
However, if you have only one branch instead of two, if
without the else part is sometimes considered bad (for example, clj-kondo will flag it). In that case, when
is preferred.
Good day! I came to Clojure from Haskell. Please help me understand the following notation:
(defn select
[{:keys [api-key] :as options}] ..._
What {:keys [api-key] :as options} means
It's called Destructuring.
You're telling the function that the argument is a map with a keyword/value pair with api-key
as the keyword (plus whatever else is in the vector), and that you want to bind that value to the name options
.
Destructuring is a good way to pull in a complex data structure in its entirety to a function and pick out what you need as you need it.
Thnx. I tried different searches cos I thought :as and :keys are keywords.
In given case.
well, they are, strictly speaking, they're just doing something specific here.
But yeah, any time you see a map inside an argument vector and that sort of structure inside it, you should be thinking of destructing a data object.
Destructuring is a little bit more magic than I usually attribute to Clojure, so studying the various forms of destructuring was the best way for me to recognize them when I see them.
@UKG0SELQY
It's equivalent to this:
(defn select [options]
(let [api-key (get options :api-key)]
... ))
Example:
user=> (let [{:keys [api-key] :as options}
{:api-key "secret" :other 99}]
[api-key options])
["secret" {:api-key "secret", :other 99}]
Principle: you can put a map where you would normally put a symbol. Instead of binding to the symbol, you do funny destructuring stuff based on a map-based syntax.
You can use destructuring in defn
, let
and a few other places where assignment makes sense.
Hi! Is it possible to do a sequential destructuring inside function args in this example:
(defn f [sum letters] ; expects int and vector of two elements
(let [[a b] letters] (if (= a b) sum (inc sum))))
something like
(defn f2 [sum [a b] letters]
(if (= a b) sum (inc sum)))
f2 doesn't work like I want, because it expects 3 args.Why
(defmacro zed [] `(println "----" ~(meta &form)))
(zed)
this evaluates correctly, but this
(defmacro zed [] `(println "----" ~(identity &form)))
(zed)
does not? :thinking_face: I just want to see what is available in the &form
var.because &form is (zed)
so the macroexpansion of (zed) includes (zed), which is macroexpanded to (zed) which is macroexpaned to (zed) ...
stackoverflow
user=> (defmacro zed [] `(println "----" ~(str &form)))
#'user/zed
user=> (zed)
---- (zed)
ok. I understood 🙂 so from ~(meta &form)
I can have line and column. Is it possible to get or somehow infere the calling function name?
Another similar question to yesterday trying to figure out map and reduce. The function below works, but instead of updating just one entry (`:value`) I want it to take a vector of keywords and apply update to all of them. I know I need reduce
for this but my attempts have failed. Can anyone suggest how I could call reduce
within map
here?
(defn parsed-csv [csv-data]
(let [data (csv-data->maps csv-data)]
(map (fn [csv-record]
(update csv-record :value #(Integer/parseInt %))) data)))
Trying this for instance just returns a function:
(defn parsed-csv [csv-data]
(let [data (csv-data->maps csv-data)]
(map (fn [csv-record]
(reduce (fn [x] (update csv-record x #(Integer/parseInt %))) csv-record) data))))
I'm so used to imperative programming where I would just use loops for everything
Are you expecting a single value or a collection as a return value from this function? Or will you run this function in order for side effects to do something like update a csv db record?
Expecting a seq of maps to come back. No side effects, this is just for parsing specific columns of a CSV file into ints.
data
is a seq of maps in this case
so csv-record
is a map then? Calling reduce on a map (collection) is going to convert it to a value.
csv-record is a map yes
ok, in that case then my approach was wrong. I just want to iterate over a seq of maps and apply a function (Integer/parseInt in this case) to the values associated with specific keys contained in a vector.
Is there any linguistic way to avoid using map as both a verb and a noun in basically all of my sentences? I feel like I end up saying the words "key value pair collection" a lot to not sound confusing.
I'll try that one on for size
still close but easier than "key value pair collection" 🙂
ah ok, that's probably a good approach thank you
i get it
I want to create image with clojure. Simple avatar simulator. Random background color and initials (2 letters of username) saved to a file. I feel like this is easy and trivial but i haven't found any clj libraries for this kind of purpose. Are there any resources you could point me to? should i use java interop for this? which lib?
if you know java2d you’ll probably be able to do what you want with java interop.
I've got a bit further but I'm pretty stuck conceptually. I have these two functions:
(defn value->int
[m k]
(update m k #(Integer/parseInt %)))
(defn values->int
[m kws]
(map #(value->int m %) kws))
The first is working fine for updating one value in a map based on the key.
In the case of the second, I want to iterate over the keywords whose values should be parsed into ints. But of course since I'm not mapping over the hash-map but the vector of keywords, it's returning one hash-map for each element in the vector of keywords, with just one of the values parsed into ints each. I get why this is happening, but I don't understand the solution. Example:
(values->int {:decimals "0",
:symbol "",
:geo "Country",
:value "16"} [:value :decimals])
returns:
({:decimals "0", :symbol "", :geo "Country", :value 16}
{:decimals 0, :symbol "", :geo "Country", :value "16"})
should return:
{:decimals 0, :symbol "", :geo "Country", :value 16}
In my typical imperative programming I would just do something like below, to illustrate what I'm trying to achieve:
for (keyword : Keywords) {
hash-map[keyword] = Integer.parseInt(hash-map[keyword])
}
reduce is a function, where the result of each application is fed into the next application
wow :star-struck:
I was trying to use reduce earlier but couldn't get the params right. thank you this is very cool
or as a recursive loop:
(loop [new-m m
kws kws]
(if (empty? kws)
new-m
(recur (value->int new-m (first kws)) (rest kws)))
the function reductions
can be helpful for understanding/debugging reduce. https://clojuredocs.org/clojure_core/clojure.core/reductions
oh, that's very cool. thank you. I was trying to use reduce by basically substituting it for map when the syntax I can see should be a bit different
so the big payoff: (reduce value->int m kws)
- this is why we clojure
Indeed
This is helping me refactor some of the code I wrote three weeks ago that now looks ghastly 😂
That was my experience for my first few months of using Clojure. The journey was well worth it!
So I've often heard function composition (comp f g)
vocalized as "`f` after g
", but it seems like composition of transducers is the reverse. Is this by design? An artifact of implementation?
Eg:
user=> (map (comp inc #(* % %)) (range 10))
(1 2 5 10 17 26 37 50 65 82)
user=> (transduce (comp (map inc) (map #(* % %))) conj (range 10))
[1 4 9 16 25 36 49 64 81 100]
Ah, here it is: > Composition of the transformer runs right-to-left but builds a transformation stack that runs left-to-right (filtering happens before mapping in this example). Thanks, @ghadi
Is there a discussion/write-up about how these transformation/composition mechanics work under the hood?
I can hand-wave my own mind to accept it and use the (->> ...
analogy, but would love a more detailed/nitty-gritty dive.
Rich Hickey explained transducers in his strange loop talk: https://www.youtube.com/watch?v=6mTbuzafcII
And he goes into much more detail in "Inside Transducers" explaining the implementation of some of the transducer-returning fns in clojure.core
including some stateful transducers: https://www.youtube.com/watch?v=4KqUvG8HPYo
If you prefer text to video, there are transcripts of those talks available here: https://github.com/matthiasn/talk-transcripts/tree/master/Hickey_Rich
But I'd definitely recommend watching the talks.
the tricky thing is a transducer is a function from a function to a function, so in use it is a two step process, you apply the transducer to the reducing function (when is when the comp'ed functions run, as usual, right to left), and the result is a reducing function wrapped in all the transducer transforms, where the last transform is the outer wrapper, and that reducing function is then used to actually reduce, and it runs outside to inside (or left to right)
I found this article helpful for that https://sixty-north.com/blog/deriving-transducers-from-first-principles.html
the function you get out of comp, doesn't actually do all those things (mapping, filtering, etc) it transforms the reducing function to do those things, which means wrapping the reducing function, and when you apply wrappers the first wrapper applied is the innermost wrapper
you would observe a similar behavior if it was common practice to compose ring middleware that way
(def middleware (comp (fn [handler] (fn [req] (handler (update-in req [:stack] conj :c))))
(fn [handler] (fn [req] (handler (update-in req [:stack] conj :b))))
(fn [handler] (fn [req] (handler (update-in req [:stack] conj :a))))))
(def handler (middleware identity))
(handler {})
;;=> {:stack (:a :b :c)}
I have a vector with integer [3 4 9 10 12]
and I need to iterate through the elements and multiply while decrementing the multiplier and finally add up all the elements once I'm done:
3*10 + 4*9 + 9*8 + 10*7 + 12*6
Any ideas?
If you're stuck, it can be useful to post what you've already got!
map
can go over two collections at once, pair-wise
why not use loop with recur? you can decrement the multiplier and sum up numbers until vector is empty
(defn my-fn [nums]
(loop [multiplier 10
numbers nums
sum 0]
(if-not (seq numbers)
sum
(recur (dec multiplier)
(rest numbers)
(+ sum (* multiplier (first numbers)))))))
There are probably other ways, maybe more efficient - but it should do the trickuser=> (apply + (map * (range 10 1 -1) [3 4 9 10 12]))
280
The (range 10 1 -1)
would stop at 2 though
good point
I think you're solution is actually correct, I've tried it out with some vectors and the output is as expected
right, it's just that it should extend to 1 for maximum generality
who knows what's expected after 1...
(range 10 0 -1)
solves the issue
Sounds like you could use map-indexed
and multiply the integer by, say, (- multiplier index), then use (reduce + data) to sum it all up
What is a nice way of reading a graph from a file? The undirected graph is written as a 2D matrix in a file (adjacency matrix). Currently I have this,
(defn read-edges
[reader]
(let [rows (into [] (->> reader
line-seq
(map #(str/split % #","))))]
(into (sorted-set-by #(< (:weight %1) (:weight %2)))
(apply concat
(map-indexed
(fn [i row]
(remove nil?
(map-indexed
(fn [j value]
(when (and (not= value "-")
(< i j))
{:weight (Integer/parseInt value)
:vertices #{i j}}))
row)))
rows)))))
Ignore the sorted-set
bit. I kept the edges ordered by weight but that is not a necessity.Looks pretty reasonable to me. There are libraries like Loom and Ubergraph that have a few algorithms on graphs implemented for them, e.g. connected components, depth/breadth-first search, shortest paths, etc., but they do not handle that particular file format, as far as I know, and are not necessary for you to use by any means. I mention them only in case you are looking to use an algorithm they already implement for you.
I am solving a puzzle, so trying to implement an algorithm myself. But these libraries can be useful later.
The problem with my approach is the nested map-indexed
. I don't like how the inner map-indexed
is using i
from the outer map-indexed
. It is preventing me from lifting the fn
s up into a letfn
.
I mean, some people positively love that functions declared inside of other code like that have access to all values in their lexical environment, without having to pass them as args.
(pointing at myself there)
🙂, Yeah, I like them too. But here the code has become a little cryptic. It is not easy to understand what is happening here.
You could try a for
that begins something like (for [i (range n), j (range n)] ...)
OK, maybe not that code I suggested, but the idea of a for
that has two 'loop variables', which is a way to get nested looping behavior but the code is not so nested.
Simply put, I need to traverse a 2D array while maintaining current row (`i`) and column (`j`). There might be idioms somewhere.
Maybe something like (for [[I row] (map-indexed (fn [I row] [I row]) rows), [j value] (map-indexed (fn [j val] [j val]) row) ...bodyhere...)
That looks better spread out over 2 lines, but still maybe not great
Those two fn
expressions are actually the same function, and could be replaced with vector
Actually, got an idea. If I at least pull out a defn map-indexed-2d
, the code will become more modular.
(for [[i row] (map-indexed vector rows), [j value] (map-indexed vector row) ] ...bodyhere... )
but yes, if you can pull out a map-indexed-2d
that sounds useful
I know this is a bit vague, but I was hoping for some guidance. I am currently beginning what will likely be a long journey in the process of understanding the real-time modeling of worlds. I am planning to start small, by creating a graph database and modeling some tiny subset of relationships found in our world. I am thinking of starting with scientific papers and their references to each other to build a historical web of papers and their influence on one another. I was wondering what technologies/cloud providers/etc. you all might use to accomplish. Ideally I would like to use clojure, and I definitely plan to introduce event sourcing at some point (current state of the world at any one point in time is the result of starting state + aggregation of events so far).