This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-19
Channels
- # announcements (52)
- # asami (83)
- # atom-editor (1)
- # babashka (143)
- # beginners (123)
- # calva (18)
- # chlorine-clover (21)
- # cider (7)
- # clj-kondo (57)
- # cljs-dev (4)
- # clojure (209)
- # clojure-boston (1)
- # clojure-europe (27)
- # clojure-germany (12)
- # clojure-italy (17)
- # clojure-nl (3)
- # clojure-serbia (6)
- # clojure-spec (1)
- # clojure-uk (59)
- # clojurescript (82)
- # conjure (9)
- # core-async (6)
- # cursive (20)
- # data-science (1)
- # datahike (1)
- # datascript (1)
- # datomic (86)
- # duct (5)
- # emacs (6)
- # events (6)
- # figwheel-main (4)
- # fulcro (27)
- # graalvm (19)
- # leiningen (14)
- # lsp (30)
- # malli (48)
- # meander (3)
- # off-topic (6)
- # pedestal (2)
- # practicalli (1)
- # rewrite-clj (21)
- # shadow-cljs (18)
- # sql (15)
- # tools-deps (9)
- # vim (3)
- # wasm (3)
- # xtdb (18)
Is there any difference between using partial
and an anonymous function? Anonymous functions seem more readable and flexible to me at least.
Anonymous functions are definitely more flexible.
I am not aware of any noticeable performance difference, or memory use difference, but haven't tried to measure them.
I prefer anonymous functions for their flexibility, personally, but some people like things such as comp, partial, etc.
A big difference with partial that very often trips people up is partial is just a function, like any other function and its arguments get evaluated that way
So for example (partial str "foo")
derefs #'str once, and then closes over the value, where #(str "foo" %)
derefs every time it is invoked
And it may or may not make a difference to you that Rich Hickey has said he considers anonymous functions more idiomatic than partial
.
Thank you for the detailed responses! Appreciate it a lot.
I like partial, comp, etc. because they are much less powerful, so they don't require the same level of close reading as fn / #()
I still like comp
— I find I’m using it much more now we have transducers. I have to be honest and say that I don’t, generally, like partial
. Over the years, we’ve moved away from it in our work codebase, either to explicit arities that provide just the intended amount of currying or anonymous function invocations, depending on context.
hey all, i have a map that maps an id to a map that represents a player, i have a list of maps that represent a collection of stats, those maps contain the player’s id, which is the key to the first map
in a more imperative language i’d write a loop on the second one and update the first one
(reduce (fn [player-info {:keys [id] :as stats}]
(update player-info id update :stats (fnil conj []) (dissoc stats :id))) ;; fnil conj because i don't know how many maps will be there so just keep a list of them
{1 {:name "bob"} ;; id -> map that represents a player
2 {:name "sue"}}
[{:id 1 :strength 8} -> sequence of maps with an id and other keys
{:id 2 :strength 12}])
->
{1 {:name "bob", :stats [{:strength 8}]}
2 {:name "sue", :stats [{:strength 12}]}}
i hadn’t thought about making a whole new thing, i was thinking about “updating” the original map
but it's how to wrap a function and give it a substitute value for nils.`(+ nil 1) #_vs ((fnil + 0) nil 1)`. I used (fnil conj [])
so that when it update's the :stats
key on a player map, if there's nothing there it will "substitute" an empty vector and use that. its a common idiom
these are immutable data structures so i have made new things but they efficiently share structure with the old things
and to be a bit more precise its because they are immutable and persistent data structures. (if you find yourself looking them up at some point)
@cschep The biggest mental shift, coming to Clojure -- depending on your background, is effectively the removal of the assignment operator, and with that the whole idea of a traditional "loop" (because in most languages those are inherently based on side-effects and, of course, the loop condition inherently assumes that you're assigning new values to something).
;create league out of players
(def league (atom (into {} (map (juxt :id identity)) sb-players)))
(defn get-player
[id]
(get @league id))
(defn update-player
[id key value]
(swap! league
(fn [current-state]
(assoc-in current-state [id key] value)))
nil)
;import stats
(doseq [stats hitting-stats]
(update-player (stats :id) :stats stats))
For some context:
Clojure source 348 files 88298 total loc,
3554 fns, 898 of which are private,
571 vars, 29 macros, 91 atoms,
849 specs, 33 function specs.
Clojure tests 378 files 23437 total loc,
4 specs, 1 function specs.
That's our codebase at work. 91 atoms in just over 110K lines and most of those are caches of some sort.@U04V70XH6 what do you use to generate this summary?
@UG00LE5TN Just a dumb shell script that knows the structure of our repo. It's just fancy wc -l
and some fgrep
calls.
When you are using immutable data, you are always building new things from things you have (or things you are reading in from outside).
is that a sane way to do this? I’m so burned out of writing database migrations and the scale of this is 1
If you just have a single process, in memory, with no persistence, an atom makes a fine "database" 🙂
Yup. And the Agile crowd advocate for that quite strongly -- several of the original signatories to the Agile Manifesto are proud of how many projects they've built that don't use a database 🙂
i suppose when i’m updating based on id’s and joining maps together based on keys it leaks out that i’m already in the database mindset
check out clojure.set/index
to solve your above problem in a different way. you could keep them as separate collections and just "join" when you need to
Easy: I never write JS 🙂
I started learning Clojure in 2010 and started using it in production in 2011 -- and I pretty much never write any other code now.

A long arc: C, assembler, COBOL, C++, Java, ColdFusion, Groovy, Scala... then Clojure.
(there have been other languages in there, but those are the main ones)
That's what we're all here for in this channel!
You have to wrap Java methods in a Clojure function -- Java methods are not "first class functions".
But look at the clojure.string
namespace. It has an index-of
function that returns nil
for no match else the index of the match.
https://clojure.github.io/clojure/clojure.string-api.html has a lot of nice wrappers for the underlying Java (or JavaScript) functionality that lets you avoid interop syntax and reflection.
There's also re-find
(in clojure.core
) for doing regex pattern matching.
normal regex's are fairly simple and for the most part universal, so it's useful just to learn the syntax
but if you want to have programmatic capabilities or have something really complicated, you can check out https://github.com/lambdaisland/regal
ended up with
(defn search-players [search]
(filter #(re-find (re-pattern (str "(?i)" search)) (% :name)) (vals @league)))
yeah that'd work, but definitely consider not closing over mutable state and keeping that function pure
one reason being testing, as you'd need to setup your state as well to test the function, whereas what the function is actually doing is just search, which can be pure
I have a property file :prod
in key
{
:dev "id=dev;host=
If I understand the question correctly, it would be something like:
(:prod (clojure.edn/read-string (slurp "location/of/property.example")))
if you’re doing more substantial runtime configuration, perhaps you can use a library like https://github.com/juxt/aero. e.g.
{:webserver
{:port #profile {:default 8000
:dev 8001
:test 8002}}}
You can specify the value of profile when you read the config.
(read-config "config.edn" {:profile :dev})
has anyone written or come across something like clojure.set/rename-keys-by
(like rename-key
, but takes a fn
from key name to key name, rather than a map of remapped key names)?
several util libs have map-keys
that can do this
(noting that a hash-map is a good function from name to name)
aha, I see that in medley.core
, I think
weavejester/medley, clj-commons/useful, etc
many thanks, Alex
we may add something like this to core too - feel free to vote at https://ask.clojure.org/index.php/1926/adding-functions-map-vals-and-map-keys !
Is there an idiomatic way to set different environments (eg. production, testing…) with tools deps?
@g3o There are a number of libraries folks use for that sort of thing but nothing specific to tools deps.
https://github.com/juxt/aero is quite popular I gather, and not tied to Leiningen.
Hi all, anyone here ever work with Emberjs? Would love any feedback on tips for getting productive in clojure coming from the ember world.
Hi @aramz! Are you looking to learn Clojure on the JVM or ClojureScript for the browser?
Hi @U04V70XH6 - Both, but I’m more curious on transitioning on the front end first. I’ve been working with re-frame now for a month. I’ve played with Fulcro for another month. I love everything so far, but I’m struggling to be as productive as I can be in Ember, mostly just the libs, addons all the things you get with a big framework like Ember.
I have a long history with Clojure but not much with ClojureScript so I find Fulcro pretty overwhelming. I’ve made more progress with re-frame: https://day8.github.io/re-frame/ but I’m not sure how it compares to the Ember ecosystem (you can use the whole React.js ecosystem with re-frame, as I understand it).
I took an Ember.js workshop many, many years ago but I don’t remember much about it (I just looked at the website and it reminded me about the workshop — so parts of it are still familiar I guess).
It might be easier to see if someone will share React -> Clojure experience as I’m sure it’s somewhat similar
I used Angular.js in the time before React existed, and used plain reagent
in the time before re-frame
existed. FWIW, I would also suggest kicking the tires of re-frame
. It seems like just enough structure: not a million tiny pieces for you to wire together, and not an opinionated & monolithic framework.
To expand on my previous question, as Ember is relatively small, anyone coming from Angular or React? If so, any tips on getting productive quickly? The main point for us right now is moving from something with a ton of guard rails and convention, like rails, to what feels like something that we need to roll our own solution or patch together micro libs. I know it’s a pretty open ended question, but any thoughts are much appreciated.