For those who use clojure.tools.logging, there's also the handy "spy" 
function.

On Tuesday, October 15, 2013 6:41:38 PM UTC-7, dgrnbrg wrote:
>
> If this is something you do often, spyscope is a library I wrote to 
> simplify this sort of investigation. You can print an expression by writing 
> #spy/d in front of it. For more information, you can read at 
> https://github.com/dgrnbrg/spyscope
>
> On Tuesday, October 15, 2013 10:13:58 AM UTC-4, Brian Hurt wrote:
>>
>> Lifting subexpressions up into lets is actually something I do a lot- for 
>> one very important reason: it lets me insert print statements (or logging 
>> statements) showing the value of the subexpression.  So I'll do;
>>     (let [ x (subexpression) ]
>>         (main-expression))
>>
>> because it lets me do:
>>     (let [ x (subexpression) ]
>>         (println "The value of x is" x)
>>         (main-expression))
>>
>> If fact, a lot of times I'll do;
>>     (let [ x (subexpression)
>>             res (main-expression) ]
>>         res)
>>
>> because it lets me do:
>>     (let [ x (subexpression)
>>             _ (println "The value of x is" x)
>>             res (main-expression) ]
>>         (println "The value of the whole expression is" res)
>>         res)
>>
>> This is of great value in debugging.
>>
>> Brian
>>
>>
>>
>> On Tue, Oct 15, 2013 at 9:56 AM, Mikera <mike.r.an...@gmail.com> wrote:
>>
>>> I certainly prefer giving names to intermediate results with a "let" 
>>> block: having good names and breaking the computation up into logical 
>>> chunks makes the code much easier to understand and maintain when you come 
>>> back to it later.
>>>
>>> PG's example though is bad for different reasons - this is actually 
>>> mutating variables in an imperative style, which is definitely "bad style" 
>>> - both in Lisp and Clojure I think. The Clojure equivalent would be to use 
>>> atoms (or vars) and mutating them.
>>>
>>> "let" on its own is purely functional, and doesn't have this problem.
>>>
>>>
>>> On Tuesday, 15 October 2013 20:29:29 UTC+8, Daniel Higginbotham wrote:
>>>>
>>>> I've been going through On Lisp by Paul Graham and on page 33 he 
>>>> recommends against performing "intermediate" bindings. Does this advice 
>>>> hold for Clojure? Here are a couple examples: 
>>>>
>>>> ;; Common Lisp (from the book) 
>>>> (defun bad (x) 
>>>>  (let (y sqr) 
>>>>    (setq y (car x)) 
>>>>    (setq sqr (expt y 2)) 
>>>>    (list 'a sqr))) 
>>>>
>>>> (defun good (x) 
>>>>  (list 'a (expt (car x) 2))) 
>>>>
>>>> ;; Clojure 
>>>> (defn bad [x] 
>>>>  (let [y (first x) 
>>>>        sqr (expt y 2)] 
>>>>    (list 'a sqr))) 
>>>>
>>>> (defn good [x] 
>>>>  (list 'a (expt (first x) 2))) 
>>>>
>>>> Paul Graham explains: 
>>>>
>>>> "The final result is shorter than what we began with, and easier to 
>>>> understand. In the original code, we’re faced with the final expression 
>>>> (list 'a sqr), and it’s not immediately clear where the value of sqr comes 
>>>> from. Now the source of the return value is laid out for us like a road 
>>>> map. 
>>>>
>>>> The example in this section was a short one, but the technique scales 
>>>> up. Indeed, it becomes more valuable as it is applied to larger 
>>>> functions." 
>>>>
>>>> In clojure you can't do setq of course but I find myself going against 
>>>> this advice all the time, and I find that it's more important to do so 
>>>> when 
>>>> working with larger functions. I think introducing names makes code 
>>>> clearer. Here's an example from my own code: 
>>>>
>>>> (defn create-topic 
>>>>  [params] 
>>>>  (let [params (merge params (db/tempids :topic-id :post-id :watch-id)) 
>>>>        topic (remove-nils-from-map (c/mapify params mr/topic->txdata)) 
>>>>        watch (c/mapify params mr/watch->txdata) 
>>>>        post (c/mapify params mr/post->txdata)] 
>>>>    {:result (db/t [topic post watch]) 
>>>>     :tempid (:topic-id params)})) 
>>>>
>>>> To my mind, creating bindings for "topic", "watch", and "post" makes 
>>>> the code easier to understand. When you get to "(db/t [topic post watch])" 
>>>> you don't have to deal with as much visual noise to understand exactly 
>>>> what's going into the transaction. 
>>>>
>>>> So, is PG's advice any good? 
>>>>
>>>> Thanks! 
>>>> Daniel
>>>
>>>  -- 
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>
>>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to