It's very handy that :keywords act as functions and maps do too:

    (:start voyage) => 5
    (voyage :start) => 5

It's idiomatic Clojure, I think. I've been experimenting with a style of 
top-down TDD that puts off deciding about the "shape" of data as long as one 
can. [I hasten to add this is not a style for all problems: it's not what you'd 
use to come up with clojure.zip, for example.] Since Midje currently only lets 
you stub out vars, not keywords, using that particular style leaves you with 
code like this:

    (def start :start)
    (def end :end)
    
    (def circular? [voyage)
       (= (start voyage) (end voyage)))

"Stubbing out keywords" can be done, which would give you the more (I think) 
idiomatic:

    (def circular? [voyage)
       (= (:start voyage) (:end voyage)))

Question is: should I invest in doing it? Which depends on how much it's worth. 
Which leads to two questions:

* Is the `def start :start` alternative so offensive to your eye that it'd make 
you reluctant to try top-down TDD? (Note that the keyword-ey variant comes out 
just fine from bottom-up TDD.) That matters to me, because after a decade of 
not understanding top-down TDD, I finally did, so I have the zeal of the 
convert.

* What does it mean - to the reader - to see (:start voyage) in code as opposed 
to (start voyage)? What expectations does (start voyage) set up that (:start 
voyage) wouldn't? Midje is supposed to help with the whole 
principle-of-least-surprise thing.

** (:start voyage) could just mean  "I didn't want to bother to write an 
accessor function".

** It could mean that voyage is a composite object with a distinct piece that 
is its start, as opposed to a calculation of some sort, and that the difference 
between the two is important. I'm wondering, though, if that distinction really 
makes sense. There is, first, the hoary old encapsulation argument: that you 
use explicit getters and setters on a Point so that the caller needn't care 
whether the underlying coordinates are cartesian or polar. And especially in a 
context of pure functions, where (f constant) will always have the same value, 
whether that's a stored, calculated, or calculated-and-memoized value seems 
irrelevant.

** It could mean "there are no nasty surprises here". I vividly remember 
debugging a Smalltalk program and discovering what I'd been ignoring as a 
simple getter actually had hundreds of lines of code behind it. Using a keyword 
as a getter wouldn't have misled me so. (:start voyage) also makes it clear 
that the code is fast, whereas (start voyage) allows for anything - perhaps a 
leisurely calculation involving database queries.

++ It could mean: "Picking good names is hard. Many words in English can be 
either a noun or a verb. Does (start voyage) mean 'commence traveling' or 'make 
a property of the voyage available'? (:start voyage) eliminates the possibility 
of that confusion, saving me some mental name-picking anguish."

I'm interested in what you think when you see a keyword, and what it would mean 
if you didn't.

(Sorry for the long note, but this way I get to use some of my B.A 1981, 
English Literature, background! 
http://en.wikipedia.org/wiki/Reader-response_criticism

-----
Brian Marick, Artisanal Labrador
Contract programming in Ruby and Clojure
Occasional consulting on Agile
www.exampler.com, www.twitter.com/marick

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

Reply via email to