为什么Emacs会在我的.emacs文件中抱怨无效显示年份?

问题描述:

我试图在我的.emacs中实施节气,所以我的“假期”将显示太阳经度与15度的每个倍数交叉的时间。这里是相关的snipplet。为什么Emacs会在我的.emacs文件中抱怨无效显示年份?

(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的(版本23.2-R2上的Gentoo)抱怨显示,今年是启动时的空隙变,并试图生成的Mx日历RET日历也没有帮助。任何想法如何我可以解决这个问题? (当然不是在我的.emacs中定义显示年份,因为这肯定会把所有其他东西都搞砸了......)

+0

在运行此功能之前,您是否需要日历并加载它? – 2010-11-29 18:26:02

需要推迟计算直至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)) 

因为您还没有将符号displayed-year限制为某个值。看看在let*最后一行为astronextdate结合:

         (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 

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

(require 'calendar) 

强迫Emacs的加载其之前定义变量包手。

也就是说,它会被定义,但尚未绑定。你应该改变你的代码不承担静态绑定solar-terms-holidays,而应该把它变成用于计算这些需求的功能,因为当日历实际运行displayed-year只能被绑定...

所以,一个可能的解决方案是做到以下几点,你的包裹setq如下,以确保像你希望他们是变量绑定:

(save-window-excursion 
    (calendar) 
    (setq solar-terms-holidays 
     ....) 
    (calendar-exit)) 
+1

你必须做的不仅仅是'(需要'日历)`,你必须真正运行'日历'功能。 – 2010-11-29 18:33:29

+0

@GarethRees Yah,我在添加,因为你正在输入你的评论。 :)我们都在同一时间编辑了这个问题。猜猜我们是同步的。 – 2010-11-29 18:41:53