LoL which style for Clojure

254 views
Skip to first unread message

jamieorc

unread,
Mar 22, 2013, 2:59:43 PM3/22/13
to clo...@googlegroups.com
Curious which style is preferred in Clojure and why:

(defn f1 [] 
  (let [x {:foo 1 :bar 2 :baz 3}] 
    (keys x))) 

(let [x {:foo 1 :bar 2 :baz 3}] 
  (defn f2 [] 
    (keys x)))

Cheers,

Jamie

Jim - FooBar();

unread,
Mar 22, 2013, 3:02:20 PM3/22/13
to clo...@googlegroups.com
def/defn et. al are top-level form definitions...very rarely (I'd say
never) you'd have a def/defn inside a 'let' or inside anything for that
matter...The 1st one looks good :)

Jim
> --
> --
> 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.
>
>

Laurent PETIT

unread,
Mar 22, 2013, 3:05:10 PM3/22/13
to clo...@googlegroups.com

2013/3/22 jamieorc <jami...@gmail.com>

In either case, AFAIK, the compiler will recognize {:foo 1 :bar 2 :baz 3} as constant and will only create it once when compiling.

First version is preferred.
 

jamieorc

unread,
Mar 22, 2013, 3:08:41 PM3/22/13
to clo...@googlegroups.com
Thanks, that's what I expected, especially after doing some (time... ) experiments. 

Robert Pitts

unread,
Mar 22, 2013, 4:41:43 PM3/22/13
to clo...@googlegroups.com
I've certainly seen this at least a few spots within the 4clojure codebase –

Timothy Baldridge

unread,
Mar 22, 2013, 6:00:15 PM3/22/13
to clo...@googlegroups.com
The question should probably be asked: is there a benefit in a given situation to having the let be outside the scope of the defn? I would argue that most times it is not, and putting the let outside the function clutters the code and makes it harder to see the functions defined in the namespace. If you truly need a const value, then something like this is better, IMO:

(def ^:private ^:const data {:a 1 :b 2})

(defn f1 [])
(defn f2 [])

I would say that most of the time, the "let at the top" version could be refactored into a def with no change in semantics, while at the same time gaining a bonus to readability. 




--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)

Marko Topolnik

unread,
Mar 23, 2013, 4:56:53 AM3/23/13
to clo...@googlegroups.com
What if there's some computation in there, but such that should be performed at compile time? I still prefer the outside let whenever I want to make dead sure it's not getting reallocated on each call. If there was some well-specified and easily understood guarantee (for example, like the one Java has for compile-time constants), only then I would prefer the inner let.

Thomas Heller

unread,
Mar 23, 2013, 7:16:45 AM3/23/13
to clo...@googlegroups.com
Just out of curiosity, does it have to be a function?

(def data {:foo 1 :bar 2 :baz 3})
(def data-keys (keys data))

If one item is constant the other probably is too?

Cheers,
/thomas

Ben Wolfson

unread,
Mar 23, 2013, 12:59:26 PM3/23/13
to clo...@googlegroups.com
On Sat, Mar 23, 2013 at 4:16 AM, Thomas Heller <th.h...@gmail.com> wrote:
> Just out of curiosity, does it have to be a function?
>
> (def data {:foo 1 :bar 2 :baz 3})
> (def data-keys (keys data))
>
> If one item is constant the other probably is too?

In this case, yes, but it's easy to imagine cases where neither is a constant.

--
Ben Wolfson
"Human kind has used its intelligence to vary the flavour of drinks,
which may be sweet, aromatic, fermented or spirit-based. ... Family
and social life also offer numerous other occasions to consume drinks
for pleasure." [Larousse, "Drink" entry]

Ben Smith-Mannschott

unread,
Mar 24, 2013, 5:53:28 AM3/24/13
to clo...@googlegroups.com
Way back when I started with Clojure i was doing this:

(let [constant-data (something-expensive)]
  (defn my-fn [x]
    (do-something-with x constant-data)))

But was advised instead to do this:

(def my-fn
  (let [constant-data (something-expensive)]
    (fn [x]
      (do-something-with x constant-data))))

So, there's that (third) option as well.

// ben

Matching Socks

unread,
Mar 24, 2013, 8:27:55 AM3/24/13
to clo...@googlegroups.com
Doug Hoyte's book "Let Over Lambda—50 Years of Lisp" devotes its very title to the technique of (let...(fn...)). 

Marko Topolnik

unread,
Mar 24, 2013, 9:15:07 AM3/24/13
to clo...@googlegroups.com
On Sunday, March 24, 2013 10:53:28 AM UTC+1, bsmith.occs wrote:
Way back when I started with Clojure i was doing this:

(let [constant-data (something-expensive)]
  (defn my-fn [x]
    (do-something-with x constant-data)))

But was advised instead to do this:

(def my-fn
  (let [constant-data (something-expensive)]
    (fn [x]
      (do-something-with x constant-data))))

The problem with this is that it gets messy when setting up metadata is involved. 
Reply all
Reply to author
Forward
0 new messages