Fork me on GitHub

Any opinions on fully collapsed docs like this: โ€ข or just everything fully expanded without collapse option, like this: โ€ข Note that you can use the menu on the top left to navigate as well.



j abns09:05:10

+1 without collapse. Easier to scan the page when looking for something

โž• 3

Same. And Ctrl+F works only with an expanded version.

โœ… 2

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.

j abns10:05:24

Expanded. Scrolling is easier than clicking and easier to stay in the flow

j abns10:05:03

The less clicks between the user and the content the better

โž• 2

Everything expanded + Table of Contents (deep-linked items, with depth h1, h2, h3)


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.


Creating a TOC isn't a problem :)

๐Ÿ‘ 2

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


Looks pretty good! But I'd probably replace those : - with just - or just : . Otherwise, it's a bit noisy, at least for me.


oh that was a typo


Noice! It's doubling up as an Index too!


Oh, probably another typo - "SCI var that represents SCI's" should be "SCI var that represents Clojure's". Right?


And *x* becomes x.


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.


Ah, alright. :) But I think the issue with *x* is the issue with the MD format itself or quickdoc not escaping *, no?


it's an issue in the docstring, the docstring should probably use markdown syntax


at least, that's what I'm going to do going forward with this, I think


or do you have a better / alternative idea?


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*


I probably never want to use italics in docstrings, so that should probably work


Sounds like it!


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.


including earmuffed vars right?


As in:

(defn foo "something blabla `*dude*`" [])


I agree btw, that was the first thought I had too, there are cases when you just want to use the word


> including earmuffed vars right? Yep!


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!


I do the same, backtick anything that refers to "code"

๐Ÿ‘ 1

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]

๐Ÿ‘ 1

Assuming A is a mutable data structure, it'd be a very similar code, with two loops. If A is something immutable, just make it transient, sort, then make persistent.

๐Ÿ‘ 2

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 loops because you have to use the result of assoc! - you can't ignore it. Never mind, you mentioned that and I'm blind.


> 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))


Why do you not want to use loops?


i'm trying to solve with loop/recur.


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)))


This is what I meant:

(let [A (transient (shuffle (range 20)))
      n (count A)]
    (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))))


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
  (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]
(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.

๐Ÿ‘ 1
Alexis Schad14:05:04

You can use reduce:

(reduce (fn [A [i j]]
            (if (< (A i) (A j))
              (swap A i j)
          (for [i (range n)
                j (range n)]
            [i j]))

๐Ÿ‘ 3

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))
        (take i A)
        (list (get A j))
        (take (- (Math/abs (- j i)) 2)
              (drop (inc i) A))
        (list (get A i))
        (drop j 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 ๐Ÿ˜


Nah, not mine - from Alexis, with reduce and without any loops.


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. ๐Ÿ˜Š


Forgot you could assoc a vector.

Alexis Schad22:05:35

Yes I was matching initial algorithm terms but (swap A i j) is just (assoc A i (A j) j (A i))

๐Ÿ‘ 1