Search code examples
emacselispdot-emacs

Why does Emacs complain about void-variable displayed-year in my .emacs file?


I'm trying to implement the solar terms in my .emacs so my "holidays" will display the time when the solar longitude crosses each multiple of 15 degrees. Here is the relevant snipplet.

(defun next-solar-term-date (d)
  (solar-date-next-longitude d 15))

(defconst solar-term-names
  ["moderate cold" "severe cold" "spring commerces"
   "rain water" "insects awaken" "vernal equinox"
   "Ching Ming" "corn rain" "summer commerces"
   "corn forms" "corn on ear" "summer solstice"
   "minor heat" "great heat" "autumn commerces"
   "end of heat" "white dew" "autumnal equinox"
   "cold dew" "frost" "winter commerces"
   "light snow" "heavy snow" "winter solstice"])

(setq solar-terms-holidays
      (let* ((k 0) (mylist nil))
        (dotimes (k 4);k=season
          (let* ((j 0))
            (dotimes (j 5);no equinoxes/solstices --- use solar for them
              (let* ((i (+ j (* 6 k)))
                     (month (+ 1 (/ i 2)))
                     (astronextdate (next-solar-term-date
                                     (calendar-astro-from-absolute
                                      (+ (* 15 i)
                                         (calendar-absolute-from-gregorian
                                          (list 1 1 displayed-year))))))
                     (s (aref solar-term-names i))
                     (absnextdate (calendar-absolute-from-astro
                                   astronextdate))
                     (gregnextdate (calendar-gregorian-from-absolute
                                    (floor absnextdate)))
                     (compt (* 24 (- absnextdate (floor absnextdate))))
                     (str (concat s " "
                                  (solar-time-string
                                   compt (if (dst-in-effect absnextdate)
                                             calendar-daylight-time-zone-name
                                           calendar-standard-time-zone-name))))
                     (d (extract-calendar-day gregnextdate)))
                (setq mylist (append mylist
                                     (list
                                      (list 'holiday-fixed month d str))))))))
        mylist))

However, emacs (version 23.2-r2 on Gentoo) complains about displayed-year being a void-variable at start-up, and trying to generate the calendar with M-x calendar RET doesn't help either. Any idea how I can fix that? (Certainly not with defining displayed-year in my .emacs since this definitely screws up everything else...)


Solution

  • The calculation needs to be deferred until displayed-year is available, which may be achieved by replacing the last expression in your paste with these two:

    (defun solar-term (i month)
      (let* ((astronextdate (next-solar-term-date
                             (calendar-astro-from-absolute
                              (+ (* 15 i)
                                 (calendar-absolute-from-gregorian
                                  (list 1 1 displayed-year))))))
             (s (aref solar-term-names i))
             (absnextdate (calendar-absolute-from-astro
                           astronextdate))
             (gregnextdate (calendar-gregorian-from-absolute
                            (floor absnextdate)))
             (compt (* 24 (- absnextdate (floor absnextdate))))
             (str (concat s " "
                          (solar-time-string
                           compt (if (dst-in-effect absnextdate)
                                     calendar-daylight-time-zone-name
                                   calendar-standard-time-zone-name))))
             (d (extract-calendar-day gregnextdate)))
        (holiday-fixed month d str)))
    
    (setq solar-terms-holidays
          (let* ((mylist nil))
            (dotimes (k 4)    ;k=season
              (dotimes (j 5)  ;no equinoxes/solstices --- use solar for them
                (let* ((i (+ j (* 6 k)))
                       (month (+ 1 (/ i 2))))
                  (push `(solar-term ,i ,month) mylist))))
            mylist))