

Clojure from the ground-up: debugging - momo-reina
https://aphyr.com/posts/319-clojure-from-the-ground-up-debugging

======
swannodette
Kyle's suggestions have a ton of value, but do note that debugging
Clojure(Script) can also be a pedestrian activity if you so desire. All the
usual mainstream bell/whistles IDE-based interactive debugging is available
today in CursiveClojure - break on all exceptions, eval in frame, etc.

Also ClojureScript has had accurate source mapping in Safari, Chrome, Firefox,
and Node.js for quite a long time now and recently moved to support targets
like iOS. It's a huge time saver even for an experienced Clojure programmer :)

~~~
macmac
And if you favour open source IDEs the Eclipse based Counterclockwise
[http://doc.ccw-ide.org/](http://doc.ccw-ide.org/) will provide the same
debugging experience for Clojure.

~~~
smrtinsert
I love ccw as a coding tool and the full editor repl is great too but I
haven't been able to get breakpoints to work on it ever. Another thing that
irks me about it lately is no real clojurescript support! That said it is
still my primary clojure tool and things like figwheel help close the gap.

------
kaffeinecoma
I'm trying so hard to love Clojure, but I keep running into examples of code
like this in the world: [http://imgur.com/79FlpTL](http://imgur.com/79FlpTL).
I don't write dense Lisp code like that, but unfortunately a lot of other
people do. And I spend far more time reading code than writing it.

~~~
swannodette
Well that code seems pretty readable to me and appears to preserve some
interesting properties of the original paper as mentioned below the source :)

As far as spending more time reading Clojure than writing it I experience this
myself - and I'm pretty sure this isn't a bad thing.

~~~
kaffeinecoma
I meant that in general, we as programmers will spend more time reading (our,
others') code than writing it. Nature of the business. Did not mean to imply
this was a bad thing.

When I consider adopting a language, part of that consideration is how well I
can read others' idiomatic code. It's so important for understanding
libraries. I'm still just having a hard time with Clojure. I know it clicks
for a lot of people though.

------
lispm
Error messages and stack traces look pretty ugly.

In Common Lisp:

    
    
        CL-USER 51 > (bake (make-instance 'pie :flavor :blackberry) 375 10.25)
    
        Error: The value 3843.75 of #:|predicate1555| is not a predicate in CONDP.
          1 (continue) Supply a new value of #:|predicate1555|.
          2 (abort) Return to level 0.
          3 Return to top loop level 0.
    

A clear error message and a way to repair it.

A stack frame:

    
    
        Call to BAKE {offset 394}
          PIE               : #<PIE 402000993B>
          TEMP              : 375
          TIME              : 10.25
          DBG::|predicate|  : 3843.75
          DBG::|expression| : #<Function < 411007995C>
          DBG::G            : 3843.75

~~~
coldtea
Which CL is that?

~~~
lispm
LispWorks, the one Rich Hickey used for quite some time... ;-)

~~~
coldtea
Yeah, I feared that. That's the paid-for one, isn't it?

------
lispm
SBCL at compile time:

    
    
        * (defun bake (pie temp time)
          "Bakes a cake for a certain amount of time, returning a cake with a new
          :tastiness level."
          (setf (tastiness pie)
                (condp (* temp time) #'<
                       (400 :burned)
                       (350 :perfect)
                       (300 :soggy))))
        ; in: DEFUN BAKE
        ;     (CONDP (* TEMP TIME)
        ;         #'<
        ;       (400 :BURNED)
        ;       (350 :PERFECT)
        ;       (300 :SOGGY))
        ; ==>
        ;   (LET ((#:PREDICATE2 (* TEMP TIME)) (#:EXPRESSION3 #'<))
        ;     (DECLARE (TYPE FUNCTION #:PREDICATE2))
        ;     (CHECK-TYPE #:PREDICATE2 FUNCTION "a predicate in CONDP")
        ;     (COND ((FUNCALL #:PREDICATE2 #:EXPRESSION3 400) :BURNED)
        ;           ((FUNCALL #:PREDICATE2 #:EXPRESSION3 350) :PERFECT)
        ;           ((FUNCALL #:PREDICATE2 #:EXPRESSION3 300) :SOGGY)))
        ;
        ; caught WARNING:
        ;   Derived type of (* TEMP TIME) is
        ;     (VALUES NUMBER &OPTIONAL),
        ;   conflicting with its asserted type
        ;     FUNCTION.
        ;   See also:
        ;     The SBCL Manual, Node "Handling of Types"
        ;
        ; compilation unit finished
        ;   caught 1 WARNING condition
    

Pretty cool...

------
Flow
Does anyone know what color theme those code boxes use?

I apologize for being so shallow :)

