Is there any difference between using partial
and an anonymous function? Anonymous functions seem more readable and flexible to me at least.
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.
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.
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
i’d like to make each map in the list a member of the map that id points to
in the first map
in a more imperative language i’d write a loop on the second one and update the first one
any pointers for the clojure take?
is it appropriate to use map just to loop over each value?
feels .. wrong
for
also seems like it’s more for building a list
oo maybe doseq
(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}]}}
reduce eh
what’s fnil?
😄
check out (doc fnil)
oh that’s cool
i hadn’t thought about making a whole new thing, i was thinking about “updating” the original map
but that’s probably the wrong idea
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 in that sense you can't update the original
right, right
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)
ok thanks!
a bit to chew on here
@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).
yeah, totally
;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))
it does feel like i essentially wrenched the language into a mutable class
ha ha ha
but it does “work”
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.@seancorfield what do you use to generate this summary?
@robertfrederickwarner Just a dumb shell script that knows the structure of our repo. It's just fancy wc -l
and some fgrep
calls.
yeah so the context of this is i’m using this atom instead of talking to a database
When you are using immutable data, you are always building new things from things you have (or things you are reading in from outside).
so there should just be the one
make json out of it and return it from web routes
and update it by getting posts
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" 🙂
spitting it to a flat file
voila, persistence!
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 🙂
ha ha, ok awesome
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
but it’s fun to poke around in your own little world
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
wow
how do you learn about this stuff and then go write javascript
for 8 hours a day
not gonna work
🙂
Easy: I never write JS 🙂
ha, bingo
I started learning Clojure in 2010 and started using it in production in 2011 -- and I pretty much never write any other code now.
what were you writing before?
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)
sounds like you landed in a good spot
🙂
i’m gonna keep firing noob questions but i hope no one feels too obligated to keep up
That's what we're all here for in this channel!
i’m trying to pass the function java.lang.String.contains
to a function
.contains
doesn’t seem to work
You have to wrap Java methods in a Clojure function -- Java methods are not "first class functions".
ahh ok i’m glad i’m not crazy
#(.contains % %1)
like that?
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.
ohhh that will probably work
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.
oh yes, how to programmatically construct a regex?
finding a string that contains a string would be like #“.thestring.” or something?
can you string interpolate into them?
oh.. re-pattern
i think
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
in this case i’m passing in a search string
from a user
so if the user types “mike” i want to list all the names that contain “mike”
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
it doesn't need to know about league
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 <http://property.as|property.example
>as below which is located in the my deployed server, How can I read the property file and fetch the data from :prod
in key
{
:dev "id=dev;host=<http://127.0.0.1/update>"
:prod "id=prod;host=<http://example.com/update>"
}
in clojure
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?
I would like to use a different db when I run my tests
@g3o There are a number of libraries folks use for that sort of thing but nothing specific to tools deps.
I saw environ
but it looks like is only for lein, at least from the Readme
https://github.com/juxt/aero is quite popular I gather, and not tied to Leiningen.
sweet! I’ll have a look
thank you very much Sean!
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 @limix! Are you looking to learn Clojure on the JVM or ClojureScript for the browser?
Hi @seancorfield - 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.
Wondering if anyone from the Ember community has made the transition and how that went
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).
Thank you
It might be easier to see if someone will share React -> Clojure experience as I’m sure it’s somewhat similar
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.