Fork me on GitHub
#beginners
<
2016-07-02
>
montanonic00:07:21

I'm reading through The Joy of Clojure, and it took a long while to digest its implementation of QuickSort. I'd like to know what non-editor tools I can use to see how clojure expressions evaluate. Any recommendations?

montanonic00:07:27

I figure that there should be a way to write a macro that prints the source of each sub-expression as it evaluates, along with the results at each step (map of bound variable names to values), and indexes on the order of evaluation. I just.... don't want to write it (and also, there might be complications with that and lazy functions?)

jswart00:07:20

I have the Joy of Clojure somewhere, but it isn’t handy.

jswart00:07:33

The absolute fastest way to comprehend code in clojure @montanonic is to use the REPL.

jswart00:07:44

Type some code in, evaluate it and see what happens.

montanonic00:07:47

which is what I'm doing

montanonic00:07:11

but, I'd like to see a trace of each step in the evaluation of a function

montanonic00:07:23

with the currently bound local variables and their values

montanonic00:07:25

if that makes sense

jswart00:07:31

Hmm, we functions that utilize reduce you can use reductions.

montanonic00:07:32

so I can see how it evaluates

jswart00:07:36

But ad-hoc, I’m not as certain.

jswart00:07:43

s/we/with/

montanonic00:07:10

okay, just was wondering if there was an obvious macro for doing that in core clojure

montanonic00:07:25

and in this case, no reduce

jswart00:07:28

not really. beyond macroexpand-1, macroexpand

montanonic00:07:32

though reductions is good to know

jswart00:07:43

and clojure.walk/macroexpand-all

jswart00:07:49

that is all I know of for that “type” of thing

montanonic00:07:58

(defn sort-parts [work]
  (lazy-seq
    (loop [[part & parts] work]
      (if-let [[pivot & xs] (seq part)]
        (let [smaller? #(< % pivot)]
          (recur (list*
                   (filter smaller? xs)
                   pivot
                   (remove smaller? xs)
                   parts)))
        (when-let [[x & parts] parts]
          (cons x (sort-parts parts)))))))

(defn qsort [xs]
  (sort-parts (list xs)))

montanonic00:07:27

I've more-or-less figured out exactly how it's working. Just, for future reference, it'd be nice to give a function like that some random input, and see literally every step of it evaluate.

jswart00:07:29

is what I was going to paste,… looks the same

jswart00:07:55

Yeah, so the funny thing with that code is that 99% of the time.

jswart00:07:59

you wouldn’t really write it

jswart00:07:04

in day to day clojure

jswart00:07:09

which is what I’m paid to do

jswart00:07:21

I use map, filter and reduce

jswart00:07:39

But as far as understanding it, there are some context clues

montanonic00:07:41

Haha, totally fair point. And coming from Haskell, I totally can see how most clojure stuff wouldn't be hard to grok

jswart00:07:01

loop/recur means that: We are doing a recursive thing but b/c of the JVM we can’t use tail call recursion.

montanonic00:07:11

yeah, I grok that part

montanonic00:07:21

I think I have the whole quicksort implementation down

montanonic00:07:29

Just, I'd like to see it working step by step 🙂

jswart00:07:35

Cool, the one thing that definitely is an idiom though

jswart00:07:43

is the meaty macro, wrapped w/ a function

jswart00:07:56

But honestly I come across code like that seldom.

jswart00:07:41

I’ve met Fogus in person and he is a smart and fun person. That code is a great example, but I don’t see it often.

jswart00:07:53

So if you understand it, great! You don’t have to write everything that way though.

jswart00:07:23

Direct implementations of algorithms are always odd though.

jswart00:07:32

Unless its quicksort in Haskell and then its basically free 🙂

montanonic00:07:37

Yeah, it's more a matter of, I want a macro that I can use whenever I see something that confuses me, run it through the macro with some sample input, see how it evaluates

montanonic00:07:59

I'm going to pilfer http://stackoverflow.com/questions/2352020/debugging-in-clojure#2352491 and see if any of the recommendations suit what I'm looking for

jswart00:07:01

Yeah, you should goolge for common lisp trace and debug macros

jswart00:07:04

they did this quite a bit

jswart00:07:48

Yeah a lot of that algorithm implementation is due to the environment.

polymeris23:07:30

Is it ok to override a ->Thing record constructor if I want to add some checks and :pres?