直接从列表中绑定多个值,而不绑定列表本身


12

是否可以在不通过Emacs Lisp中的临时变量的情况下直接将多个返回值分配给变量?

例如,假设我有一个函数返回两个列表的列表:

(defun test-func ()
  (setq a '(a b))
  (setq b '(c d))
  `(,a ,b))

如果我想将第一个返回值分配给list-a,将第二个返回值分配给list-b,我可以使用一个临时变量来做到这一点temp,例如:

(let* ((temp (test-func)) (list-a (car temp)) (list-b (cadr temp)))
  (message-box (prin1-to-string list-a))
  (message-box (prin1-to-string list-b)))

是否可以更简单地执行此操作?(我习惯于Perl和Python,而您不必指定临时变量)


2
您可以尝试使用cl-destructuring-bind宏。另外,您是否真的打算setq在内使用defunsetq创建一个“特殊”(全局可访问)变量,通常将其放置在函数外部(因为多次声明同一变量没有多大意义,而函数打算多次运行)。
wvxvw 2015年

@wvxvw谢谢!是的,我忘了使用let功能里面。我不打算设置任何全局变量:)
哈康Hægland

Answers:


8

Common Lisp具有特殊的功能- 多个值,而Emacs Lisp兼容性库 使用列表来模拟它们

这样你就可以做

(defun test-fun ()
  (let ((a 1) (b 2))
    (cl-values a b)))

(cl-multiple-value-bind (a b) (test-fun)
  ...)

(加载cl-libcl-为EL中的所有CL功能使用前缀)。

注意:如果您查看上面链接的SO答案,您会发现,用列表模拟MV并不是最理想的选择(另请参见下面的@Stefan的评论)。


使用multiple-value-bind而不是有什么好处cl-multiple-value-bind(只有gnu.org/software/emacs/manual/html_node/cl/Multiple-Values.html手册中记录了后者)?
哈康Hægland

3
@HåkonHægland它们是相同的功能,但您应该使用后者。该cl软件包不打算再使用了。你应该总是用cl-lib包来替代,它与定义功能cl-前缀..
Malabarba

1
我建议不要使用cl-values:这是CommonLisp的“尽力而为”的模拟,values但是它并不是真正兼容的,因为它所做的只是返回一个列表(即,这是一种谎言),而根据我的经验,人们迟早会遇到麻烦将其作为列表进行处理(即破坏抽象):更好地明确使用列表(如果您不喜欢pcase-let,则使用cl-destructuring-bind而不是cl-multiple-value-bind)。
斯特凡

4

除了依赖cl-lib兼容性包之外,Elisp的推荐方法是使用pcase

(defun test-fun
  (let ((a '(a b))
        (b '(c d)))
    `(,a ,b)))

(defun other-test-fun ()
  (pcase-let ((`(,a ,b) (test-fun)))
    (message "a = %s; b = %s" a b)))

除此之外pcase-let,这里还有pcase-dolistpcase-lambdapcase本身。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.