1
votes

I'm trying to translate the Common Lisp code in the original "Calendrical Calculations" paper by Derhowitz and Reingold to Clojure. In this paper there is a macro named sum which is given in Common Lisp as

(defmacro sum (expression index initial condition)
;; sum expession for index = initial and successive integers,
;; as long as condition holds.
 (let* ((temp (gensym)))
   `(do ((,temp 0 (+ ,temp ,expression))
         (,index ,initial (i+ ,index))) 
        ((not ,condition) ,temp))))

and which I've translated to Clojure as

(defmacro sum [expression index initial condition]
  ; sum expession for index = initial and successive integers,
  ; as long as condition holds.
  (let [temp (gensym)]
    `(do ((~temp 0 (+ ~temp ~expression))
          (~index ~initial (inc ~index))) 
         ((not ~condition) ~temp))))

However, when I use the above in a function (for example, the following)

(defn absolute-from-gregorian [date]
  ;; Absolute date equivalent to the Gregorian date.
  (let [month (extract-month date) 
        year  (extract-year date)]
    ; Return
    (+ (extract-day date)           ;; Days so far this month.
       (sum                         ;; Days in prior months this year.
         (last-day-of-gregorian-month m year) m 1 (< m month))
       (* 365 (dec year))           ;; Days in prior years.
       (quotient (dec year) 4)      ;; Julian leap days in prior years...
       (-                           ;; ... minus prior century years...
         (quotient (dec year) 100))
       (quotient                    ;; ...plus prior years divisible...
         (dec year) 400))))         ;; ... by 400.

I get an error similar to the following:

CompilerException java.lang.RuntimeException: Unable to resolve
  symbol: G__53 in this context, compiling:(NO_SOURCE_PATH:165:8) 

I'm almost completely unfamiliar with the Lisp/Clojure macro system, but from what I can determine it's saying that the gensym invocation in the let block has created a symbol (in this case G__53) which is being invoked, but which doesn't exist. That makes sense, but I suspect it's not the intent of the original code - however, I don't know much about Common Lisp and thus I'm not able to figure out A) what the original CL code is trying to do here, and B) how to produce a Clojure equivalent to this.

For what it's worth - the Clojure version of the other functions used in absolute-from-gregorian are:

(defn quotient [m n]
  (int (Math/floor (/ m n))))

(defn extract-month [date]
  (first date))

(defn extract-day [date]
  (second date))

(defn extract-year [date]
  (second (rest date)))

Any and all pointers as to how to make this work greatly appreciated.

2

2 Answers

3
votes

This can be expressed with a loop construct in Clojure:

(defmacro sum [expression index initial condition]
  ; sum expession for index = initial and successive integers,
  ; as long as condition holds.
  `(loop [~index ~initial temp# 0]
     (if ~condition 
       (recur (inc ~index) (+ temp# ~expression))
       temp#)))

Example:

(sum (* x x) x 1 (<= x 3)) ;; => 14

Note also that it may be sufficient to use Clojure's standard constructs instead of custom macros. As an example, the line in the code with the calendar calculations can be rewritten as:

(reduce + (map #(last-day-of-gregorian-month % year) (range 1 month)))
4
votes

do in common lisp doesn't act anything like do in clojure. You'll have to look up what do actually does (it's a looping construct in common lisp, and a grouping construct in clojure), and figure out how to accomplish the same thing.