在 Emacs Lisp 中使用 foldr 实现地图
Implementing map using foldr in Emacs Lisp
我开始学习 Emacs Lisp,作为练习,我正在尝试使用 foldr 实现地图。代码如下:
(defun foldr (f z l)
(if (null l)
z
(funcall f (car l)
(foldr f z
(cdr l)))))
(defun map (f l)
(foldr (lambda (x z)
(cons (funcall f x) z))
nil
l))
但是,当我尝试评估时,例如,
(map (lambda (x) (+ x 1)) '(1 2 3 4 5))
在带有 eval-last-sexp 的 Emacs 中(在评估 foldr 和 map 之后),结果如下:
Debugger entered--Lisp error: (wrong-number-of-arguments (lambda (x z) (cons (funcall f x) z)) 1)
(lambda (x z) (cons (funcall f x) z))(5)
funcall((lambda (x z) (cons (funcall f x) z)) 5)
(cons (funcall f x) z)
(lambda (x z) (cons (funcall f x) z))(5 nil)
funcall((lambda (x z) (cons (funcall f x) z)) 5 nil)
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (3 4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (2 3 4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (1 2 3 4 5))
map((lambda (x) (+ x 1)) (1 2 3 4 5))
eval((map (function (lambda (x) (+ x 1))) (quote (1 2 3 4 5))) nil)
eval-last-sexp-1(nil)
#[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"](nil)
ad-Advice-eval-last-sexp(#[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"] nil)
apply(ad-Advice-eval-last-sexp #[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"] nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
我不明白为什么这不起作用,当 Haskell 中的以下超级相似实现工作正常时:
foldr f z l = if (null l)
then z
else f (head l) (foldr f z (tail l))
map f l = foldr (\ x z -> (:) (f x) z) [] l
那么为什么 Lisp 和 Haskell 程序不等价呢? Lisp 实现中问题的本质是什么,即为什么 map 不工作?
(setq lexical-binding t)
f
是传递给 foldr
.
的 lambda 形式的自由变量
使用词法绑定,您的示例工作正常:
(map (lambda (x) (+ x 1)) '(1 2 3 4 5)) ; ==> (2 3 4 5 6)
我开始学习 Emacs Lisp,作为练习,我正在尝试使用 foldr 实现地图。代码如下:
(defun foldr (f z l)
(if (null l)
z
(funcall f (car l)
(foldr f z
(cdr l)))))
(defun map (f l)
(foldr (lambda (x z)
(cons (funcall f x) z))
nil
l))
但是,当我尝试评估时,例如,
(map (lambda (x) (+ x 1)) '(1 2 3 4 5))
在带有 eval-last-sexp 的 Emacs 中(在评估 foldr 和 map 之后),结果如下:
Debugger entered--Lisp error: (wrong-number-of-arguments (lambda (x z) (cons (funcall f x) z)) 1)
(lambda (x z) (cons (funcall f x) z))(5)
funcall((lambda (x z) (cons (funcall f x) z)) 5)
(cons (funcall f x) z)
(lambda (x z) (cons (funcall f x) z))(5 nil)
funcall((lambda (x z) (cons (funcall f x) z)) 5 nil)
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (3 4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (2 3 4 5))
(funcall f (car l) (foldr f z (cdr l)))
(if (null l) z (funcall f (car l) (foldr f z (cdr l))))
foldr((lambda (x z) (cons (funcall f x) z)) nil (1 2 3 4 5))
map((lambda (x) (+ x 1)) (1 2 3 4 5))
eval((map (function (lambda (x) (+ x 1))) (quote (1 2 3 4 5))) nil)
eval-last-sexp-1(nil)
#[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"](nil)
ad-Advice-eval-last-sexp(#[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"] nil)
apply(ad-Advice-eval-last-sexp #[257 "43!7 3!\n)B1A =41A1@7" [eval-expression-debug-on-error eval-last-sexp-fake-value debug-on-error eval-last-sexp-1] 4 2471606 "P"] nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
command-execute(eval-last-sexp)
我不明白为什么这不起作用,当 Haskell 中的以下超级相似实现工作正常时:
foldr f z l = if (null l)
then z
else f (head l) (foldr f z (tail l))
map f l = foldr (\ x z -> (:) (f x) z) [] l
那么为什么 Lisp 和 Haskell 程序不等价呢? Lisp 实现中问题的本质是什么,即为什么 map 不工作?
(setq lexical-binding t)
f
是传递给 foldr
.
使用词法绑定,您的示例工作正常:
(map (lambda (x) (+ x 1)) '(1 2 3 4 5)) ; ==> (2 3 4 5 6)