This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-05-08
Channels
- # babashka (1)
- # babashka-sci-dev (42)
- # beginners (3)
- # calva (9)
- # clj-kondo (1)
- # cljs-dev (1)
- # clojure (52)
- # clojure-europe (3)
- # clojure-spec (6)
- # clojurescript (35)
- # defnpodcast (1)
- # guix (1)
- # honeysql (3)
- # hugsql (4)
- # humbleui (1)
- # introduce-yourself (3)
- # jobs (1)
- # jobs-discuss (9)
- # lsp (57)
- # off-topic (65)
- # polylith (4)
- # portal (11)
- # releases (1)
- # remote-jobs (2)
- # shadow-cljs (19)
- # tools-deps (4)
- # vim (11)
- # xtdb (8)
Any opinions on fully collapsed docs like this: โข https://github.com/babashka/sci/blob/master/API.md or just everything fully expanded without collapse option, like this: โข https://github.com/babashka/process/blob/master/API.md Note that you can use the menu on the top left to navigate as well.
It's also possible to only collapse namespaces and not the vars. But I assume you would still prefer to have everything expanded, right?
Yep. :) Keeping it neat but also easily accessible isn't really possible with a plain MD viewer. But an external viewer might be used, like cljdoc, I suppose.
Oh, I guess that would work with a plain MD viewer as well. But you'd have to create the ToC manually and keep it up to date.
I consider a ToC to be basic hygiene in long-enough documents (anything that scrolls beyond about 2 screenfuls of a typical FHD 14" screen).
because it immediately suggests the flow of the doc, summarises key topics, and provides hints to ctrl-f terms.
I agree about the toc. I'm pretty neutral on expand vs not but definitely yearn for a toc/listing of all var names at the top when looking at these
This is how the TOC turned out: https://github.com/babashka/sci/blob/master/API.md
Looks pretty good! But I'd probably replace those : -
with just -
or just :
. Otherwise, it's a bit noisy, at least for me.
Oh, probably another typo - "SCI var that represents SCI's" should be "SCI var that represents Clojure's". Right?
yeah, those are issues in the docstrings themselves, not with quickdoc, I'll fix them eventually. The "SCI var that represent's SCI's ..." is not a typo, it is truly the interpreter's version of x, which is an analog to Clojure's x.
I realize I might not have explained properly what quickdoc is. https://github.com/borkdude/quickdoc
Ah, alright. :)
But I think the issue with *x*
is the issue with the MD format itself or quickdoc not escaping *
, no?
If that's still an open question, it feels like escaping all *
might get quite tedious due to their amount. And it would be easy to just miss a few.
Maybe a somewhat customized version of MD that doesn't interpret formatting within backticks?
Some of these preferences could be configurable. E.g automatically converting earmuffed var names to *foo*
we could even automatically markup as code any words that occur in the arglists too :P
Mm, not sure about this one - that would require paying attention to not naming the args with plain English words. I myself, even though I don't use any doc generators, prefer to just put backticks around any code, including regular mentions of args.
I agree btw, that was the first thought I had too, there are cases when you just want to use the word
That's what I'm going to do too, so for me personally there would be no need to auto-markdowning earmuffed vars
My internal text parser demands it at this point. :) Sometimes it takes noticeable effort to get through some docstring in clojure/core
just because it uses the same word for both code and non-code.
Nice!
How would you implement this algorithm in clojure?
for i = 1 to n do
for j = 1 to n do
if A[i] < A[j] then
swap A[i] and A[j]
https://twitter.com/chordbug/status/1523016806348304385Assuming A
is a mutable data structure, it'd be a very similar code, with two loop
s.
If A
is something immutable, just make it transient, sort, then make persistent.
Something like this:
(let [a (transient [3 1 2])]
(doseq [i (range (count a))]
(doseq [j (range (count a))]
(when (< (get a i)
(get a j))
(assoc! a
i (get a j)
j (get a i)))))
(persistent! a))
This solution is wrong because we should always use the return of assoc!
in the next assoc!
Why is so hard to write this algorithm in clojure?doseq
+ range
can be replaced with dotimes
. :)
Note also that you have to use
Never mind, you mentioned that and I'm blind.loop
s because you have to use the result of assoc!
- you can't ignore it.
> Why is so hard to write this algorithm in clojure?
It's not hard if you use loop
?..
Another round:
(let [*A (atom (transient (shuffle (range 20))))
size (count @*A)]
(dotimes [i size]
(dotimes [j size]
(let [a @*A]
(when (< (get a i)
(get a j))
(swap! *A assoc!
i (get a j)
j (get a i))))))
(persistent! @*A))
Something like this:
(let [A [3 1 2]
idxes (range (count A))]
(loop [[i & is] idxes
a A]
(if (seq is)
(recur is (loop [[j & js] idxes
a a]
(if (seq js)
(if (< (get a i)
(get a j))
(recur js (assoc a
j (get a i)
i (get a j)))
a)
a)))
a)))
This is what I meant:
(let [A (transient (shuffle (range 20)))
n (count A)]
(persistent!
(loop [i 0, A A]
(if (< i n)
(recur (inc i)
(loop [j 0, A A]
(if (< j n)
(let [vi (nth A i)
vj (nth A j)]
(recur (inc j)
(cond-> A (< vi vj) (assoc! i vj j vi))))
A)))
A))))
Although, at this point you can get rid of the transient step, heh. But that probably won't help the performance. On the other hand, if you care about performance even a bit, then you should 100% use some other sorting algorithm.
I'm not thinking in performance or anything like this. I'm just stumble in translate this pseudocode into clojure code.
I think that the best solution that I can do in clojure is
(defn my-sort
[A]
(let [*A (volatile! A)
n (count A)
flip (fn [a i j]
(assoc a
i (get a j)
j (get a i)))]
(dotimes [i n] ;; for i = 1 to n do
(dotimes [j n] ;; for j = 1 to n do
(when (< (get @*A i) (get @*A j)) ;; if A[i] < A[j] then
(vswap! *A flip i j)))) ;; swap A[i] and A[j]
@*A))
(my-sort (shuffle (range 3)))
;
Where my challenge is "translate pseudocode into code in the most literal way"The most direct translation would probably be this:
(let [v (shuffle (range 20))
A (long-array v)
n (count A)]
(dotimes [i n]
(dotimes [j n]
(let [vi (aget A i)
vj (aget A j)]
(when (< vi vj)
(aset A i vj)
(aset A j vi)))))
(vec A))
But it has a limit on the size of A
.You can use reduce:
(reduce (fn [A [i j]]
(if (< (A i) (A j))
(swap A i j)
A))
A
(for [i (range n)
j (range n)]
[i j]))
I ended up just banging on it mutably as some of the earlier attempts do. That seems pretty suitable in this case.
(defn swapper [A-orig]
(let [A (to-array A-orig)
n (count A-orig)]
(dotimes [i n]
(dotimes [j n]
(when (< (get A i) (get A j))
(let [i-val (aget A i)]
(aset A i (aget A j))
(aset A j i-val)))))
(seq A)))
You could definitely do in more of a pure functional way, but it'd be pretty ugly ๐ I think you'd reduce and the reducing fn would end up something like (broken, I'm sure, I'm just tossing something out there)
(fn [A [i j]]
(if (< (get A i) (get A j))
(concat
(take i A)
(list (get A j))
(take (- (Math/abs (- j i)) 2)
(drop (inc i) A))
(list (get A i))
(drop j A))
A))
But... why? A solution right above uses reduce
with a simple function. That swap
is just a single assoc
.
I'm just imagining if you wanted to do something more conventionally functional, without loops. I agree yours is better & there's no good reason for the proposal I just made, I'm just playing around ๐
Ohhhh, I see, I didn't look closely enough at that flip
fn, that's quite nice. That's doing what I was aiming at, in a far better way. ๐
Yes I was matching initial algorithm terms but (swap A i j) is just (assoc A i (A j) j (A i))