This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-29
Channels
- # architecture (3)
- # aws-lambda (1)
- # babashka (7)
- # beginners (60)
- # calva (33)
- # chlorine-clover (8)
- # cider (24)
- # circleci (4)
- # clj-kondo (13)
- # cljs-dev (1)
- # cljsrn (12)
- # clojure (75)
- # clojure-australia (6)
- # clojure-europe (100)
- # clojure-france (1)
- # clojure-nl (13)
- # clojure-uk (16)
- # clojurescript (49)
- # conjure (1)
- # crux (18)
- # cryogen (8)
- # datomic (43)
- # dirac (3)
- # etaoin (1)
- # exercism (4)
- # fulcro (32)
- # jobs (2)
- # kaocha (4)
- # nginx (1)
- # off-topic (106)
- # pathom (8)
- # reagent (5)
- # reitit (5)
- # sci (52)
- # shadow-cljs (37)
- # tools-deps (30)
- # tree-sitter (18)
what is a best way to generate a lazy sequence of ordered pairs from a given sequence? The output sequence can be in any order, I don't care. For example given (1 2 3 4)
, generate the sequence [[1 2] [1 3] [1 4] [2 3] [2 4] [3 4]]
which does not include [1 1]
(repeated elemente) unless 1 occurs twice in the input sequence, and does not include [2 1]
because 2 does not precede 1 in the input sequence.
Here's what I'm using, but I don't like calling rest
on something that might be an array.
(defn lazy-pairs [seq]
(cond (empty? seq)
()
:else
(concat (for [t (rest seq)]
[(first seq) t])
(lazy-pairs (rest seq)))))
Another option is using next
, but it's not much better. Here's what I came up with
(defn lazy-pairs
([coll]
(lazy-seq
(when-let [s (seq coll)]
(let [[h & t] coll]
(concat
(map #(list h %) t)
(lazy-pairs t)))))))
Why are you worried about it being an array? Why does it have to be lazy?the reason I was trying to make it lazy was that the list might be long sometimes. and if i'm using something like (some pred (lazy-pairs ...))
i'd like that to stop generating when it finds a match
Makes sense. I wonder if it can be expressed as a transducer, then you won't have an issue with laziness / next
@U010VP3UY9X note that your seq
argument is shadowing the clojure.core function, it's more idiomatic to name it coll
(defn lazy-pairs [coll]
(if-let [[x & xs] (seq coll)]
(concat (for [x' xs]
[x x'])
(lazy-pairs xs))
()))
what does if-let do when you bind multiple variables?
if-let supports only one binding form, which can contain destructuring, i.e.
(if-let [[x & xs] ,,,)
is valid, but (if-let [x ,,, y ,,,] ,,,)
is invalid
You can find online custom versions of if-let which support multiple bindings, usually called if-let*
Is there a (better) alternative using some higher order functions to avoid using loop/recur for the following:
(defn demo-loop-recur [n]
"update n maps of an ordered vec where (:changeable? m),
when changeable? then update (assoc m :did-change? true)
else
(assoc m :did-change? false)
"
(let [demo-vec [{:id 1 :changeable? true}
{:id 2 :changeable? false}
{:id 3 :changeable? true}
{:id 4 :changeable? false}
{:id 5 :changeable? true}
{:id 6 :changeable? true}
{:id 7 :changeable? true}]]
(loop [remain-coll demo-vec
change-count 0
result []]
(if (empty? remain-coll)
result
(let [[m & remaining] remain-coll
should-change (and (< change-count n)
(:changeable? m))
new-cnt (if should-change
(inc change-count)
change-count)]
(recur remaining
new-cnt
(into result [(assoc m :did-change? should-change)])))))))
Generic question. Assume I have a reasonably complex xml file and I want to edit it in clojure (i.e. parse into data, make some edits, emit back to xml). The editing consists of finding a number of nodes using some predicates and changing their content in some way, perhaps adding a new child node, changing an attribute etc. I am more or less familiar with zippers and say the xml->
function for selecting data from a document, but have failed to find a clean way of doing a multi node edit. It seems to me that xml->
does not immediately play nice with zip/edit
as you would need to essentially reduce over the to-be-edited nodes/locs located by xml->
and I haven't found a clean way to do this. Then again, I might just be missing something obvious.
I can of course treat the parsed xml structure as data and start doing update-in
etc, but that gets very chatty and I'm hoping there is a cleaner/more concise/more idiomatic way. Any help much appreciated.
Hi everyone. I'm in the middle of refactoring an older bit of code (that I wrote when first learning clojure) and I have a view instances of patterns like this:
(defn get-page-of-stuff
[access-token org topics page-size cursor]
(core/make-graphql-post
access-token
(core/get-graphql "search-query")
{:first page-size :query (get-query org topics) :after cursor}))
(defn get-all-pages
[access-token org topics page-size]
(let [page (get-page-of-stuff access-token org topics page-size nil)]
(loop [page page
result []]
(let [pageInfo (-> page :data :search :pageInfo)
has-next (pageInfo :hasNextPage)
cursor (pageInfo :endCursor)
result (concat result (get-nodes page))]
(if-not has-next
(into [] result)
(recur (get-page-of-stuff access-token org topics page-size cursor)
(get-nodes page)))))))
I seem to remember that this loop/recur thing is quite low-level and there might be a better, more functional approach. Basically, I get a page of results and a pageInfo
object that has a hasNextPage
property. If true, I get the next page, if not, I'm done. How would someone with more of a clue than me do this?@eamonn.sullivan see the function attached to this ticket https://clojure.atlassian.net/browse/CLJ-2555 for a useful way to do this
What am I missing to get a secure (as-in CSRF) POST input form (using reitit / luminus?) #+FILE: guestbook/routes/home.clj
(defn chat-page [request]
(layout/render request "chat.html"
{:messages (db/get-all-messages)}))
(defn save-message [message]
(db/create-message! message)
(response/found "/chat"))
(defn home-routes []
[""
{:middleware [middleware/wrap-csrf
middleware/wrap-formats]}
["/" {:get home-page}]
["/about" {:get about-page}]
["/chat"
{:get chat-page}]
["/chat/:content"
{:post save-message}]
])
#+FILE: guestbook/resources/html/chat.html
<form action="/chat" method="POST">
{% csrf-field %}
<textarea id="content" rows="3"></textarea>
<button>submit</button>
</form>
<ul>
{% for message in messages %}
<li> {{ message }} </li>
{% endfor %}
</ul>
#+FILE: guestbook/resources/sql/queries.sql
-- :name get-all-messages :? :*
-- :doc retrieves all messages records
SELECT * FROM chat
-- :name create-message! :! :n
-- :doc creates a new message record
INSERT INTO chat
(content)
VALUES (:content)
Someone can give me an explain why the both did not give the same result?
(reduce into '(("a" "b" "c") ("d" "e" "f")))
; ("c" "b" "a" "a" "b" "c")
(reduce into [["a" "b" "c"] ["a" "b" "c"]])
; ["a" "b" "c" "a" "b" "c"]
Vectors accumulate at the end, lists accumulate at the beginning. You can see this difference with conj, too
into
is basically reduce conj
into
uses conj
.
For lists
> https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/conj puts the item at the front of the list.
For vectors
> https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/conj puts the item at the end of the vector
Since no initial value is provided to reduce:
> If [an initial] val is not supplied, returns the result of applying f to the first 2 items in coll
see https://clojure.org/reference/data_structures#Lists
Thanks, for all help
Good evening. Can you recommend some good books about Clojure? I like Pragmatic Bookshelf books and I have always considered them of high quality. What do you think?
If you are okay with online books, then there are several I am working on at https://practicalli.github.io/
the Clojure books on Pragmatic are great; you should buy them all
I have the first edition of "Programming Clojure" but I think I am more interested in web development. The third edition looks great though, I will wait for the sale you have mentioned 🙂
definitely a lot of updates between 1st and 3rd editions. I myself learned Clojure from the 1st edition!
if you are willing to wait a bit, they will be having their yearly 40% off sale on e-books over Thanksgiving in a few weeks
Great news, thank you. I must say they're pretty hard to get in print unfortunately
Joking from the author aside, I have the following Pragmatic books on Clojure: Clojure Applied, Getting Clojure, Programming Clojure (both the 2nd Ed and the 3rd Ed), and Web Development with Clojure (3rd Ed) -- and they're all really good. I also have Programming Concurrency on the JVM and Seven Languages in Seven Weeks, which both feature some Clojure too 🙂
@rawyszo I hear good things about Living Clojure as a beginner's book (O'Reilly). I learned Clojure mostly from Joy of Clojure (Manning) and Clojure Programming (O'Reilly) but that was a long time ago.
I like Manning quite a lot so I think I will take a look at Joy of Clojure. Thanks for all the help 🙂
O'Reilly's "Clojure Cookbook" is a good, practical book too (although it's from 2014 so some of its content may be a bit dated now, and some of the libraries it discusses have been superseded by better choices).
I think most of it is now pretty dated unfortunately. I've been contemplating how to make that idea live again
I would be happy to contribute updated material for the JDBC stuff (I helped out with the original JDBC content).
Fun fact - I've a actually switched to Emacs and started learning Clojure because of Clojure for the Brave and True (the book is hilarious btw, love it)
Anyway, thank you for all the suggestions. 🙏 I also wanted to ask if there are some more general resources about dealing with the whole env/ecosystem? More specifically I'm talking about configuration, architecture, tools etc. Or maybe some useful articles about leiningen, shadow-cljs and figwheel would be great. There's always googling things but it would be nice to have some good examples :)
Hard to say in general @rawyszo. The http://clojure.org site has information about the Clojure CLI and deps.edn
which you'll see in some newer books and tutorials: https://clojure.org/guides/deps_and_cli
For architecture, Clojure Applied covers that to some degree as I recall, but you'll find folks aren't very proscriptive in Clojure, in general. There's some stuff out there about Domain-Driven Design in Clojure. The most general advice you'll get is to separate the pure functions from the side-effecting functions -- "functional core, imperative shell" is another approach you'll hear people talk about.
For Leiningen, Shadow, Figwheel, etc -- I'd say their respective websites are the definitive documentation. There are lots of channels here when you need to dig deeper on stuff: #tools-deps (for deps/CLI) #leiningen #figwheel-main #figwheel #lein-figwheel #shadow-cljs #architecture ... that should keep you busy for a while 🙂
(there are also quite a few "local" channels which can be good places to find additional resources -- #clojure-poland assuming you're from there?)
Yup :) thank you for all the answers 👍 As you said, that should keep me busy. Have a good day 🙂