This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-09-14
Channels
- # announcements (2)
- # babashka (54)
- # beginners (53)
- # biff (15)
- # catalyst (2)
- # cider (5)
- # clerk (17)
- # clj-kondo (36)
- # clj-otel (3)
- # clojure (52)
- # clojure-argentina (1)
- # clojure-brasil (1)
- # clojure-europe (35)
- # clojure-losangeles (2)
- # clojure-nl (3)
- # clojure-norway (20)
- # clojure-uk (5)
- # clojurescript (24)
- # cursive (10)
- # datahike (9)
- # datomic (15)
- # defnpodcast (8)
- # events (6)
- # funcool (2)
- # hyperfiddle (21)
- # jobs (1)
- # lsp (19)
- # malli (4)
- # matrix (1)
- # off-topic (25)
- # podcasts-discuss (1)
- # portal (13)
- # releases (1)
- # shadow-cljs (25)
- # solo-full-stack (16)
- # squint (27)
- # tools-deps (6)
- # tree-sitter (4)
i have a process that's doing some io and prints some updates to stdout. i'd like to parallelize the process and keep the printing to stdout, but avoid interleaving the printing. what's the best way to do this?
Depends on what you mean by interleaving, but generally, printing a single string to stdout is atomic
okay, so building up a printable string (stringbuilder) and then printing once will keep things together. thank you, appreciate it
Would it work for your use case to add-tap println and then use tap> instead of println? I think that will prevent interleaved prints when things run concurrently.
I use a library that requires ns datomic.client.api. I want this to be resolved as ns datomic.pro.api. Is it possible to mock a namespace require? I want to use the library without having datomic.client.api on classpath
You can create a namespace that has everything that datomic.pro.api
has.
Can be done either at run time (but you have to make sure it happens before the library that requires it is loaded) or at dev time by creating a separate file in your own sources.
Thanks. Makes totally sense and a really clean comprehensible solution. 🙂 Why was I even thinking of using mocking tools? 😄
What are the best resources for advanced macros techniques? I am reading the Macro section of Joy of Clojure for now.
@U11BV7MTK do u have anything by zach tellman in particular?
Let Over Lambda is good, but the author and writing voice are extremely “smug lisp weenie”, specifically about Common Lisp. It’s sometimes hard to read because if it, but if you can stomach it, the demonstrated macros are quite cool
https://github.com/cgrand/macrovich and https://github.com/clojure/tools.macro may be useful reads!
https://github.com/kennytilton/flutter-mx and https://github.com/kennytilton/web-mx have macros, macros that write macros, and most macros leverage lexical capture. Let me know if you have questions!
@U0PUGPSFR I guess first and foremost, I'm curious about designing the language for the problem you're trying to solve. I think this is extremely fascinating and trying to gauge different DSLs that people have invented for the particular problem at hand might be really useful, especially if that DSL is in Clojure. Perhaps less macro techniques, but more language design? Case studies on how language design reduces incidental complexity.
Ah, @U6D1FU8F2, I see, it is the language design itself of the DSL that interests you. Good focus! And I have to say, I have seen macro-based DSLs that were hard to approach, because the DSL itself turned out poorly (IMO). Not sure what to say. I get frustrated while programming (which is how I found Lisp). This applies to languages/DSLs I create, of course, so I think my language design process is just "If I do not like it, make it better." 🙂 Have you looked at Paul Graham's http://www.paulgraham.com/onlisp.html? Quite a good read on macrology, in a Common Lisp context.
@U0PUGPSFR Makes sense. I skimmed On Lisp a couple years ago, but probably worthwhile to go back to. I am mostly writing a DSL for a small team, and maybe with enough practice in DSL design, I can express more concisely and elegantly.
re the reference to "Let over Lambda"... It is a terrific work of literature, a riot actually, a life-enriching read; but it is basically not very much help on the question of Clojure macros. E.g., as I recall, "Let over lambda" rhapsodizes about special effects courtesy of Lisp-2, while Clojure is a Lisp-1.
I've been inhaling Mastering Clojure Macros all day because it's just the text I've been wishing for. I'd never written a macro before but now I'm in the deep end because I'm building a Clojure interpreter. I recommend chapter 6, Build APIs That Say Just What They Mean, in which the author gives a tour of Compojure by James Reeves. Hiccup is also amazing, a shining model of a DSL.
Tim Baldridge had some great content on Pivotshare but sadly looks like the platform is defunct :( he has some of the content on youtube though https://www.youtube.com/watch?v=HXfDK1OYpco https://www.reddit.com/r/Clojure/comments/10h5pha/tim_baldridges_clojure_tutorials/
OMG he has like 2 hours of video on the go macro
if anyone is in contact with him would be awesome to get the pivotshare videos hosted someplace else
First rule of Clojure Macro Club... don't write macros (unless they provide significant value and are worth the maintenance)
It's fun to practice, though 🙂 And practising can give you insight that can help you understand other people's code.
I have a large-ish collection of long strings.
I need to check if any elements of a large-ish set #{"foo" ,,, "bar"}
is a substring. If there are any matches return a truthy value.
Is there a simple idiomatic way to do this in clojure that isn’t O(n^2)?
(It doesn’t have to be optimal like Aho Corasick)
Collect all the elements of the set into a regex using alternation. If you have no lookahead/lookbehind and you're looking for a substring in any of the long strings then you're looking at O(m*n) where m is the number of long strings and n is the maximum length of the long strings. This is much better than directly using the set and repeatedly checking each string if it contains each target substring, as compiled regular grammars (which this subset of regex is) have linear match time.
Like so @U5NCUG8NR ?
(re-find
(->>
#{"foo" "bar" "baz" ,,,}
(clojure.string/join "|")
re-pattern)
"my long fooo string")
Yeah, although I'd recommend also throwing in a regex quote on them
Also be sure to not repeatedly call re-pattern
if you can help it, as constructing an optimal regex VSM is an O(n^2) operation, where n is the number of test strings.
That's good
But yeah, throw in a (map #(java.util.regex.Pattern/quote %))
into that thread last chain before the join
that way if your set has any special regex characters they will be matched literally instead of interpreted as a regex.
In a more general case, I would build a trie, but a regexp does something similar under the hood and is indeed a very elegant solution.
Yeah, with an alternation in this case it does (approximately) the same thing, and it doesn't require building a trie yourself or pulling in a library.
Out of curiosity, I made a barebones trie version to have a comparison. The difference in performance is ~50 times in my benchmark. So in cases where the performance is important (and the size of the dictionary is very large), trie is still a king.
(def words (->> (str/split-lines (slurp "/usr/share/dict/words"))
(random-sample 0.01)
(mapv #(str/replace (str/lower-case %) #"[^a-z]" ""))))
;;;; Regexp version
(def rx (re-pattern (str/join "|" words)))
(crit/quick-bench (re-matches rx (rand-nth words)))
;; Execution time mean : 4.813902 µs
;;;; Trie version
(defn make-trie []
(object-array (* 26 2)))
(defn fill-trie [^objects trie, ^String word, i]
(let [c (.charAt word i)
pos (* (- (int c) (int \a)) 2)]
(if (= i (- (.length word) 1))
(aset trie (inc pos) true)
(do (when (nil? (aget trie pos))
(aset trie pos (make-trie)))
(recur (aget trie pos) word (inc i))))))
(defn find-in-trie [^objects trie, ^String word, i]
(let [c (.charAt word i)
pos (* (- (int c) (int \a)) 2)
next (aget trie pos)]
(cond (= i (- (.length word) 1)) (some? (aget trie (inc pos)))
(nil? next) false
:else (recur next word (inc i)))))
(def top (make-trie))
(run! #(fill-trie top % 0) words)
(crit/quick-bench (find-in-trie top (rand-nth words) 0))
;; Execution time mean : 103.151610 ns
While I'm too sleepy to check if it would solve the problem in any way, https://github.com/noprompt/frak came to mind Very cool lib.
In javadoc I can mention other methods via “`link`” , (can’t remember the exact syntax). Do clojure docstrings have similar convention?
No, Clojure docstrings are plain text. However, if you use specific doc-generator tools, such as http://cljdoc.org, those have conventions for using Markdown in docstrings and some of them support links to functions, namespaces, etc.
cider supports references of the shape "docstring supports links to [[vars]]"
and will navigate to the [[var]]
reference i believe
In cljdoc, we call these https://github.com/cljdoc/cljdoc/blob/master/doc/userguide/for-library-authors.adoc#use-api-wikilinks-from-docstrings.
could put it in the meta like {:link #'other-fn :doc "..."}
Wikilinks are what I was looking for, thanks!