

Leaky Clojure Macros - astine
http://theatticlight.net/posts/Leaky-Clojure-Macros/

======
fogus

        to read or debug code with them in it one 
        has to under­stand them
    

Perhaps I'm missing some subtlety to the post, but when was that last time
that you were able to take a pass on understanding while debugging?

I think what the author is looking for is better compile-time checking and
error reporting in the the with-* macros. I'm not sure how to respond to the
"understanding" points. Is the need to understand your language constructs
considered a sign of leakiness? I would say no.

~~~
astine
Author here.

It would seem "understanding" might be the wrong word. If I were to write
something like:

    
    
        (+ 'foo 1)
    

I wouldn't have to know how "+" is _implemented_ to find the bug in my code. I
would if I were to write:

    
    
        (with-open [foo some-object-that-isnt-a-stream]
          ...do stuff...)
    

however, I would have to know the expansion.

If I have to know the details of the expansion of a macro in order to use it
correctly, then it is almost by definition leaky.

In the case of "with-open," a simple type check at the beginning of the macro
expansion would solve the problem.

~~~
readymade
You don't need to know how it's implemented, you just need to know that you
have to pass an object that can be closed. You can get that simply by reading
the docs.

The exception that's thrown in your first example above certainly makes it
blatantly obvious what you did wrong, which is nice. but you still have to
know that the addition operator doesn't let you concatenate numbers and
symbols in order to use it effectively, or your program will crash once you
run it. That's on you.

------
mattdeboard
Hm I do not agree with you re: `->` and `->>`, and have had no problems with
Clojure's context-managing fns (though my experience is limited). Not sure how
they're "leaky" at all. They do require a little getting used to but once you
understand what's happening they're great.

I say that mostly as someone who is very picky about how his code looks,
especially with regard to whitespace, keeping line length under 80 columns,
and so forth. The threading macros are great for presenting code in a very
readable way.

~~~
calibraxis
Yes, and I also think that this discussion needs to mention the facilities
Clojure provides to help you with macros.

For example, with simpler macros like -> and ->>, I recommend that curious
people macroexpand them, to get a feel for what they mean. Your GUI can make
this even easier, like if I put the cursor at the beginning of the following
and hit _M-x slime-macroexpand-all_ :

    
    
      (-> my_table
          (database db/*stage-db*)
          select*
          exec)
    

I see:

    
    
      (exec (select* (database my_table *stage-db*)))
    

Or if I do _M-._ , I get to see the sourcecode. This of course is daunting to
beginners, but they can easily mess with the sourcecode, tear it apart, and
get to the level where they can just kind of scan smaller macros and get a
rough idea of how it's doing its job.

(I realize the author probably knows these things. But I definitely consider
-> and ->> to be such a readability win, and hope that people like them.)

------
arohner
Something missing from the article:

    
    
        user> (doc with-open)
        -------------------------
        clojure.core/with-open
        ([bindings & body])
        Macro
          bindings => [name init ...]
    
          Evaluates body in a try expression with names bound to the values
          of the inits, and a finally clause that calls (.close name) on each
          name in reverse order.

------
readymade
The documentation for with-open explicitly states that the expanded form calls
.close on the provided names in reverse order. I'm not sure I get how this is
a leaky abstraction. Would the author simply prefer to not have to read the
docs before using a macro?

------
moomin
Just to state the obvious. With-open respects the close pattern, not the
Closeable interface. Plenty of java resources observe the former but not the
latter e.g. jdbc Connection interfaces.

I was hoping the article would be about legitimate problems with macros. They
do exist...

------
thom
Plus also, did you guys hear that until just recently, Rails used PUT instead
of PATCH?!

