2010-06-05 89 views
3

我有一个函数,它接受一个列表并替换一些元素。我已经将它构造为闭包,以便自由变量不能在函数外部修改。Emacs Lisp - mapcar不会将函数应用于所有元素?

(defun transform (elems) 
    (lexical-let ((elems elems)) 
    (lambda (seq) 
     (let (e) 
    (while (setq e (car elems)) 
     (setf (nth e seq) e) 
     (setq elems (cdr elems))) 
    seq)))) 

我在列表中调用它。

(defun tester (seq-list) 
    (let ((elems '(1 3 5))) 
    (mapcar (transform elems) seq-list))) 

(tester (list (reverse (number-sequence 1 10)) 
      '("a" "b" "c" "d" "e" "f"))) 
=> ((10 1 8 3 6 5 4 3 2 1) ("a" "b" "c" "d" "e" "f")) 

它似乎没有将该函数应用于提供给tester()的列表的第二个元素。不过,如果我明确应用此功能的单个元素,它的工作原理...

(defun tester (seq-list) 
    (let ((elems '(1 3 5))) 
    (list (funcall (transform elems) (car seq-list)) 
      (funcall (transform elems) (cadr seq-list))))) 

(tester (list (reverse (number-sequence 1 10)) 
      '("a" "b" "c" "d" "e" "f"))) 
=> ((10 1 8 3 6 5 4 3 2 1) ("a" 1 "c" 3 "e" 5)) 

如果我写了使用与上述相同的概念的简单功能,mapcar似乎工作...我能怎么做错误?

(defun transform (x) 
    (lexical-let ((x x)) 
    (lambda (y) 
     (+ x y)))) 

(defun tester (seq) 
    (let ((x 1)) 
    (mapcar (transform x) seq))) 

(tester (list 1 3))  
=> (2 4) 

由于

回答

2

的封闭变量elems被设置为封闭件的第一次调用后零;所有后续的调用只能看到零。你的第二个例子工作,因为transform的每个实例产生一个新的闭包。

这应该工作:

(defun transform (elems) 
    (lexical-let ((elems elems)) 
    (lambda (seq) 
     (dolist (e elems seq) 
     (setf (nth e seq) e))))) 
+0

dolist是太好了!我猜词法 - 不会保护自由变量免受修改...(并且我的第二个例子与第一个例子不够接近,我想我可以抓住它...)。 – hatmatrix 2010-06-05 08:23:27