This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-16
Channels
- # babashka (48)
- # beginners (44)
- # biff (3)
- # calva (1)
- # cider (42)
- # clj-kondo (8)
- # clojure (93)
- # clojure-australia (2)
- # clojure-europe (3)
- # clojure-taiwan (1)
- # clojurescript (10)
- # conjure (4)
- # deps-new (5)
- # joker (9)
- # lsp (12)
- # membrane (16)
- # minecraft (12)
- # missionary (4)
- # mount (3)
- # off-topic (60)
- # reitit (9)
- # releases (13)
- # ring-swagger (1)
- # shadow-cljs (18)
- # sql (67)
- # tools-deps (2)
i was checking use of apply and found this example (map #(apply max %) [[1 2 3][4 5 6][7 8 9]])
where I get expected result, what if the collection is in vector of vector i,e (map #(apply max %) [[[1 2 3][4 5 6][7 8 9]]])
how can i get maximum ib this case ?
You can call first to get it out of the additional vector:
(->> [[[1 2 3] [4 5 6] [7 8 9]]]
(first)
(map #(apply max %)))
I would say that in general, your input collection shouldn't be of arbitrary shape like that. Whatever would be providing or returning such vector is probably the code you'd want to fix.
(->> [[[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]]
(tree-seq sequential? identity)
(rest)
(filter #(and (vector? %) (not (sequential? (first %)))))
(map #(apply max %)))
And if you don't mind not being lazy, you can use loop/recur which can do it in an eager way say like so:
(->> (loop [coll [[[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]] prev-coll nil]
(if (sequential? (first coll))
(recur (first coll) coll)
prev-coll))
(map #(apply max %)))
Ah, here, I think I found something slightly nicer:
(->> [[[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]]
(iterate first)
(take-while (comp sequential? first))
(last)
(map #(apply max %)))
just trying a way on walk and found this . What is your thoughts on this ?
(flatten (prewalk #(apply max %) [[[[[[[1 2 3][4 5 6][7 8 9]]]]]]]))
I had thought about using walk at first, you can see that with my use of tree-seq. If you look at the implementation of flatten itself, you'll see it uses tree-seq itself a bit like I did in my first approach
just have the question , i was checking prewalk-demo
and postwalk-demo
, and how it opeartes the function, but did not get whey (flatten (postwalk #(apply max %) [[[[[[[1 2 3][4 5 6][7 8 9]]]]]]]))
gives eeror
Because apply takes a seqable, but poswalk does depth first traversal, which means the first element is 1
and that's not a seq, it is a long.
in prewalk also it apply the function on 1 right?
user=> (prewalk-demo [[[[[[[1 2 3][4 5 6][7 8 9]]]]]]])
Walked: [[[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]]
Walked: [[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]
Walked: [[[[[1 2 3] [4 5 6] [7 8 9]]]]]
Walked: [[[[1 2 3] [4 5 6] [7 8 9]]]]
Walked: [[[1 2 3] [4 5 6] [7 8 9]]]
Walked: [[1 2 3] [4 5 6] [7 8 9]]
Walked: [1 2 3]
Walked: 1
Walked: 2
Walked: 3
Walked: [4 5 6]
Walked: 4
Walked: 5
Walked: 6
Walked: [7 8 9]
Walked: 7
Walked: 8
Walked: 9
(cmd)(user=> (defn stupid-max
[coll]
(->> coll
(tree-seq coll? seq)
(filter coll?)
(filter #(every? number? %))
(map #(apply max %))))
#'user/stupid-max
(cmd)user=> (stupid-max [[[[1 2 3]] [4 5 6] 7 [8 9]] [10 11 12]])
(3 6 9 12)
prewalk is good if you want a consistent transform across all levels of the structure, but that's not what you want here what you want is to apply your function to arbitrary parts of the structure that meet a predicate (eg. a collection of numbers)
also wanting code to ignore input structure is a terrible smell (but has valid use cases, eg. where the input is badly structured or inconsistent) - if it has to happen it should be an isolated (and dedicated) layer of your code that doesn't mix in with application logic
thanks @U051SS2EU
Prewalk will not walk to the numbers 1,2 and 3, because the way prewalk and postwalk work is recursive. What the function returns becomes the new node.
user=> (clojure.walk/prewalk #(do (println "Walked: " %) (let [ret (apply max %)] (println "Returned: " ret) ret)) [[[[[[[1 2 3][4 5 6][7 8 9]]]]]]])
Walked: [[[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]]
Returned: [[[[[[1 2 3] [4 5 6] [7 8 9]]]]]]
Walked: [[[[[1 2 3] [4 5 6] [7 8 9]]]]]
Returned: [[[[1 2 3] [4 5 6] [7 8 9]]]]
Walked: [[[1 2 3] [4 5 6] [7 8 9]]]
Returned: [[1 2 3] [4 5 6] [7 8 9]]
Walked: [1 2 3]
Returned: 3
Walked: [4 5 6]
Returned: 6
Walked: [7 8 9]
Returned: 9
[[[3 6 9]]]
But I just realized that your solution is very accidental, if you have an uneven number of brackets it won't work anymore
user=> (clojure.walk/prewalk #(apply max %) [[[[[[1 2 3][4 5 6][7 8 9]]]]]])
java.lang.ClassCastException: class clojure.lang.PersistentVector cannot be cast to class java.lang.Number (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')
Hello, I have a basic question about Reitit routes syntax. I want to use a handler function which is NOT anonymous and can accept args, something like below:
(def routes
[["/home" (handler-one arg-1)]
["/about" (handler-two arg-1 arg-2)]
]
The above syntax will cause error. How to correct it?
I haven't found such examples. Doc shows how to use anonymous functions as handlers with decomposed map as args. Can what I described above be possible? If yes, could anyone show me a simple example? Thanks so much for your helpThank you. This is a good suggestion. Yet the problem is ["/home" (hander-one arg-1)]
seems wrong indeed. My bad for not making it clear.
Most examples are like ["/home" handler]
where handler is either an anonymous function or a function that receives no args. Thus I'm. a bit confusing how to write a named function with args and use it in a specific route. Thanks for your quick response again:smile:
I'm improvising here, but I'd guess you could try one of these approaches
(defn foo
[a b req]
{:status 200 :body "ok"})
(defn bar
[a b]
(fn [req]
{:status 200 :body "ok"}))
(defn no-extra-args
[req]
{:status 200 :body "ok"})
(def routes
["/with-partial" (partial foo 1 2)
"/nested-fn" (bar 1 2)]
"/plain-fn" no-extra-args
"/anonymous" (fn [req] {:status 200 :body "ok"}))
foo
is an example of how you can use partial to supply some of the parameters while building routes
and the final req
parameter is provided by reitit at runtime when the request actually occurs
I'm assuming here arg-1
and arg-2
are some constants you know beforehand
Sorry for the late reply. Your suggestions look excellent. I'll definitely try them out. Thank you so much for the help:+1:
saw this code one of the doc is this just a way where used 2 colons as a key? or it is a purpose ?
{::data-source {:db-spec db-spec}
::get-article-by-id {:data-source (ig/ref ::data-source)}
::get-article-handler {:get-article-by-id (ig/ref ::get-article-by-id)}
::router {:route->handler {:get-article (ig/ref ::get-article-handler)}}}
You are welcome to ask on #beginners of course, but in case you were unaware of it I wanted to mention the Clojure cheatsheet, which has a section attempting to describe the meaning of most non-alphabetic characters you will come across in Clojure: https://clojure.org/api/cheatsheet
That section (bottom left of the sheet) has a link "guide" at the top that links to a longer form article with more description of each thing.
But there's no link to :: for a description from what I can tell it has something to do with keywords? If I search on the cheatsheet for :: I get "::in-cur-namespace ::namespace-alias/kw" with no links to anywhere? Am I missing something here?
I agree that the cheatsheet does not give links to every possible thing that one can possibly imagine giving a link for. There is a link from the word "literals:" just before the examples of different kinds of keyword syntax to this page, which explains more: https://clojure.org/reference/reader#_literals
I have been maintaining the cheatsheet for about 8 years now. If you have suggestions of links you wish were there, feel free to create an issue for this repo: https://github.com/jafingerhut/clojure-cheatsheets
it's a shorthand for a keyword namespaced by the current ns:
user=> ::foo
:user/foo
by context, that looks like integrant, where you are expected use namespaced keys for components (the namespacing makes things easier, because then you know where various parts of that map come from)