On Tue, Mar 3, 2009 at 6:40 AM, David Sletten <da...@bosatsu.net> wrote:
>
> I'd appreciate any feedback regarding my Clojure style. Any more
> natural ways to do things?

Looks good, thanks for sharing.

> (defn roman? [roman-string]
>   (and (not (empty? roman-string))
>        (re-matches
>         #"(?:M{0,3})(?:D?C{0,3}|C[DM])(?:L?X{0,3}|X[LC])(?:V?I{0,3}|I
> [VX])$"
>         roman-string)))

The normal idiom in Clojure is (seq x) instead of (not (empty? x)),
and that works fine for Strings.  Also, since you don't really need
the specific return value of the test expressions, 'when' might be a
better choice than 'and'.

> (defn roman-to-arabic-aux [roman-string]
>   (cond (empty? roman-string) 0
>         (empty? (rest roman-string)) (value (first roman-string))
>         (< (value (first roman-string)) (value (second roman-string)))
>         (- (roman-to-arabic-aux (rest roman-string))
>            (value (first roman-string)))
>         :else
>         (+ (value (first roman-string))
>            (roman-to-arabic-aux (rest roman-string)))))

To reduce the clutter here, you might consider using destructuring on
roman-string to get locals for the  first and rest parts:

user=> (let [[a & b] "fie"] [a b])
[\f (\i \e)]

You also might consider indenting the result expressions to help them
stand out more.  I like either:

(cond
  test1 (expr-fn
          arg1 arg2)
  test2 (expr-fn2
          argA argB))

or:

(cond
  test1
    (expr-fn arg1 arg2)
  test2
    (expr-fn2 argA argB))

> (def arabic-values '((1000 "M") (900 "CM") (500 "D") (400 "CD")
>                      (100 "C") (90 "XC") (50 "L") (40 "XL")
>                      (10 "X") (9 "IX") (5 "V") (4 "IV") (1 "I")))

You might consider using a vector of vectors here.  There's nothing
particularly wrong with what you've got, but I've been noticing
recently that almost every list you expressed directly in idiomatic
Clojure code is a function or macro call.  I think this is part of why
I've found Clojure code to be less difficult to read than CL.

It doesn't matter much in this case as the quote is clearly visible
and the literal numbers aren't likely to be confused with function
calls, but I thought I'd mention it anyway.

> (defn arabic-to-roman
>   ([n] (if (<= 1 n 3999)
>          (apply str (arabic-to-roman n arabic-values))
>          (format "%d cannot be converted." n)))
>   ([n num-list] (cond (empty? num-list) '()
>                       (zero? n) '()
>                       :else (let [[[arabic roman] & tail] num-list]
>                               (if (>= n arabic)
>                                 (cons roman (arabic-to-roman (- n
> arabic)
>                                                              num-list))
>                                 (arabic-to-roman n tail)))) ))

You might consider using 'reduce' instead of recursion here.
Alternatively, it's interesting to note that because of the ease with
which you're destructuring arabic-values, it would be no more
difficult if you had a single list (or vector) of alternating numbers
and strings rather than nesting them.

--Chouser

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