This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-01-31
Channels
- # aleph (24)
- # announcements (2)
- # aws (1)
- # babashka (2)
- # beginners (46)
- # calva (15)
- # chlorine-clover (1)
- # clojure-europe (27)
- # clojure-nl (3)
- # clojure-norway (13)
- # clojure-uk (7)
- # clojurescript (16)
- # datomic (29)
- # emacs (4)
- # fulcro (16)
- # hugsql (6)
- # hyperfiddle (65)
- # lsp (9)
- # malli (3)
- # off-topic (29)
- # pedestal (1)
- # releases (1)
- # shadow-cljs (52)
- # specter (5)
- # xtdb (1)
Suppose I am running my code like this: clojure -M -m my.core
, is there anything I can put in my deps.edn to make that even shorter?
I believe you could throw :main-opts
into an alias and make it a vector of "-m" and "my-core"
and then you’re left on the cli with what, clojure -M:thealias
?
hmm. doesn’t it seem like there ought to be a way to specify this in the deps.edn? So for example you come back to the project or you share the project or whatever, you wouldn’t have to consult the deps.edn or documentation or a helper script in order to launch. I know there are lots of options here (build a jar, etc.) but my intuition is that should be one of them.
I think there's some ambiguity/preference around "launch"... clojure -M
will start up a REPL for the project, so that's a "launch". I think there's a convention from deps-new, if memory serves, of creating a "run-m" alias, so that could be a convention that wouldn't require consulting more than knowledge of the convention.
My guess would be that questions along this line may have been discussed in the past, so it might not hurt to poke around on http://ask.clojure.org and see if a similar discussion (or different approaches to a similar idea) have been unearthed. <https://ask.clojure.org/index.php/11355/could-clojure-main-read-the-main-namespace-from-manifest-mf?show=11355#q11355> feels like it might be going for a similar/related goal (albeit with a different motivation)
Yes I see what you mean. In practice though how many people are calling clojure -M
by itself just for the naked repl? If e.g. I actually want to interact with the repl via tty I use M:repl/rebel
and if (more often) via the editor, I invoke via an alias for the nrepl that my editor needs.
I jack-in without specific aliases quite often. Calva adds stuff to the command line for its deps, but tbh editor-specific configuration is something I'm less fond of putting into my deps.edn than, say, an alias for starting a main function that's part of the project no matter who is using it in what editor.
oh, so your editor does the invoking for you? (I use vim-fireplace and unless I missed something it’s on me to get the nrepl running [which is fine by me]). Anyway, I agree that a “run-m” convention is 99% of the way there
In a project deps.edn
file I include an alias to run the project using its main namespace which contains a -main
function (this is what clojure.main looks for by default)
Using Clojure CLI to run Clojure code, then clojure.exec can be used to run a specific function from the project. So I will have an aliases section like:
:aliases
{;; Clojure.main execution of application
:run/service
{:main-opts ["-m" "practicalli.gameboard.service"]}
;; Clojure.exec execution of specified function
:run/greet
{:exec-fn practicalli.gameboard.service/greet
:exec-args {:name "Clojure"}}
;; test runner alias
;; tools build alias
}
The https://practical.li/clojure/clojure-cli/projects/templates/practicalli/ provide these aliases by default.
I also include a Makefile in my projects to provide a consistent CLI interface for all projects, e.g. make repl
, make tests
(just and babashka are other tools that can be used as a layer on top)Clojure challenge! Write a function that returns ["7" "9" "11"]
when the following form is evaluated:
(pipe str inc (partial * 2) [3 4 5])
Edit: human math errorit's not immediately clear to me how this code gets from 3 4 5 to 7 8 9... doubling each then requires inc'ing, identity'ing, and dec'ing to get to the end numbers... is that definitely the desired output?
wait is the idea to (defn pipe …)
such that that form evals to [7 8 9] ?
Each item in the collection should be curried through any number of functions to the left of the collection.
if the correct output is ["7" "9" "11"], then it's mapping (apply comp fns) over coll
And then each item in the coll gets “piped” though the fns from right-to-left (hence idiosyncratically non-Clojure named pipe
operator).
I mean you can write map in terms of reduce
if we ignore the laziness aspect of map, map can be written in terms of reduce, so you could reduce (to re-implement map)
To be clear, the pipe
function is basically just comp
but taking exactly one extra parameter (assuming the let
with last
), and since the last thing is assumed to be a collection, map
(or mapv
for an eager vector) is then used to apply the function. Using comp
would allow for extra arguments by delineating the operation(s) from the subject.
(def frobnicate (comp str inc (partial * 2)))
(frobnicate 17)
=> "35"
(map frobnicate (range 2 8 2))
=> ("5" "9" "13")
frobnicate 😂 Very nice, but I still want to work out how I can define my own fn so users can pass arbitrary fns to pipe.
I don't have any particular use in mind, just think it would be a good exercise and was surprised the concept didn't already exist in clojure.core (but probably for good reason!)
(defn pipe [& fs-and-coll]
(let [fs (butlast fs-and-coll)
coll (last fs-and-coll)]
(mapv (apply comp fs) coll)))
(pipe str inc (partial * 2) [3 4 5])
=> ["7" "9" "11"]
that'll do the trick (again, assuming the math was just wrong), but if the right-most function takes multiple params or if the final argument isn't a collection, then it won't work (which I'd imagine is why the concepts are separated in clojure.core)There are many ways to slice this cake. For example, using https://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/.
(defn thrush [& args]
(reduce #(%2 %1) args))
(thrush 5 #(+ % 4) -)
;=> -9
Or, since functions are first-class values, one can stick them into collections, and https://github.com/adityaathalye/clojure-by-example/blob/master/src/clojure_by_example/ex03_data_and_functions.clj#L216.
(def minimal-good-conditions
"A collection of functions that tell us about the
good-ness of planetary conditions."
[co2-tolerable?
gravity-tolerable?
surface-temp-tolerable?])
(def fatal-conditions
"A collection of functions that tell us about the
fatality of planetary conditions."
[(complement atmosphere-present?)
air-too-poisonous?])
(defn conditions-met
"Return only those condition fns that a planet meets.
An empty collection means no conditions were met."
[condition-fns planet]
(filter (fn [condition-fn]
(condition-fn planet))
condition-fns))
(defn planet-meets-no-condition?
[conditions planet]
(empty? (conditions-met conditions planet)))
(def planet-meets-any-one-condition?
(complement planet-meets-no-condition?))
(defn planet-meets-all-conditions?
[conditions planet]
(= (count conditions)
(count (conditions-met conditions planet))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Composite checks to
;; - test whether a given planet meets a variety of conditions.
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn habitable?
"We deem a planet habitable, if it has all minimally good conditions,
and no fatal conditions."
[planet]
(when (and (planet-meets-no-condition?
fatal-conditions
planet)
(planet-meets-all-conditions?
minimal-good-conditions
planet))
planet))
#_(map :pname
(filter habitable? p/target-planets))
hey all, I'm looking for a lightweight cljs web server (like js express). What do you guys recommend?
I don't know about cljs server but it should be possible to use the same express via interop
I made a deno based example with cljs back in the day. It's not up-to-date but maybe you can use it as reference? https://github.com/valerauko/cljs-deno-example
hey thanks, I am currently using express, but I thought perhaps there's a cljs implementation, as there are plenty in clj
https://www.surveymonkey.com/stories/SM-_2BH3b49f_2FXEkUlrb_2BJSThxg_3D_3D/ probably because mostly people are using clojure as a backend for clojurescript apps
What is the idiomatic way to iterate through a hash map using (for ...)
and (doseq ...)
? I'd like to add an example to https://clojuredocs.org/clojure.core/for
What I normally do is the following, but it seems I'm doing more work than necessary
(for [k (keys hash)
:let [v (get hash k)]
...
I thought I tried that and it failed. it must have failed for some other reason, and I misinterpreted the error messages.