为什么Emacs在我的.emacs文件中抱怨void变量显示年份?

时间:2010-11-29 18:15:59

标签: emacs elisp dot-emacs

我正在尝试在.emacs中实施节气,所以我的“假期”将显示太阳经度超过15度的每个倍数的时间。这是相关的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))

但是,emacs(Gentoo上的版本23.2-r2)抱怨显示年份在启动时是一个无效变量,并且尝试使用 Mx日历RET 生成日历没有帮助无论是。知道如何解决这个问题吗? (当然不是在我的.emacs中定义显示年份,因为这肯定搞砸了其他一切......)

2 个答案:

答案 0 :(得分:3)

因为您没有将符号displayed-year绑定到值。查看let*的{​​{1}}绑定中的最后一行:

astronextdate

该符号未绑定到任何值,因此您得到一个void变量错误。该变量在 (list 1 1 displayed-year)))))) 库中定义,该库具有文档:

calendar

所以,看起来你只需要添加:

;; A note on free variables:

;; The calendar passes around a few dynamically bound variables, which
;; unfortunately have rather common names.  They are meant to be
;; available for external functions, so the names can't be changed.

;; displayed-month, displayed-year: bound in calendar-generate, the
;;   central month of the 3 month calendar window

强制Emacs加载预先定义变量的包。

那说,它将被定义,但尚未受约束。您应该将代码更改为不假定静态绑定(require 'calendar) ,但应将其转换为按需计算这些代码的函数,因为solar-terms-holidays仅在日历实际运行时绑定...

所以,一个可能的解决方案是执行以下操作,按如下方式包装displayed-year以确保变量绑定,就像您期望的那样:

setq

答案 1 :(得分:1)

计算需要推迟到displayed-year可用,这可以通过用以下两个替换粘贴中的最后一个表达式来实现:

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