2

如何定义 mutator elisp 函数?也就是说,如何将参数发送到可以在函数内部修改以在函数外部使用的 elisp 函数(类似于 C++ 中的非 const 引用变量或指针)?例如,假设我定义了一个函数 foo

(defun foo (a b c d)
  ;do some stuff to b, c, and d
        .
        .
        .
  )

我可能喜欢这样称呼它,比如说,如下

(defun bar (x)
  (let ((a) (b) (c) (y))
  .
  .
  .
        ;a, b and c are nil at this point
        (foo x a b c)
        (setq y (some-other-function-of a b c x and-other-variables))
  .
  .
  .
)) ... ) 
  y)

我知道我可以将某个函数的所有本地参数放入一个大的旧列表中,在函数末尾评估列表,然后从其他列表中获取这些变量设置为该函数的返回值(列表的东西),即

(setq return-list (foo read-only-x read-only-y))
(setq v_1 (car return-list))
(setq v_2 (cadr return-list))
            .
            .

但是有没有更好的方法?到目前为止,我在尝试解决这个问题时所做的只是退出函数,其中的变量与传入的方式没有什么不同

至于为什么我希望能够做到这一点,我只是尝试重构一些大型函数 F,使与某些可命名概念 c 相关的所有表达式集合都存在于它们自己的小模块 c_1、c_2、c_3、... c_n 中我可以在 F 中调用我需要在此过程中更新的任何参数。也就是说,我希望 F 看起来像:

(defun F ( ... )
  (let ((a_1) (a_2) ... )
    (c_1 a_1 ... a_m)
    (c_2 a_h ... a_i)
     .
     .
     .
    (c_n a_j ... a_k)
     .
     .
     .
 ))...))
4

2 回答 2

2

我能想到的两种方法:

  • 使“函数” foo 成为宏而不是函数(如果可能)
  • 将一个新创建的 cons(或多个)传递给函数,并通过 setcar/setcdr 替换它们的 car 和 cdr

如果函数太复杂,您也可以结合这两种方法 - 使用宏 foo 创建 a 和 b 的 cons 并使用该 cons 调用函数 foo0,然后再次解包 car 和 cdr。

如果您需要超过 2 个 args,只需使用多个 cons 作为参数。

于 2013-06-29T11:10:37.353 回答
0

只是为了向您展示如何做到这一点,但不要这样做,这是不好的风格。

(defun set-to (in-x out-y)
  (set out-y in-x))

(let (x)
  (set-to 10 'x)
  x)

有一种情况下这不起作用:

(let (in-x)
  (set-to 10 'in-x)
  in-x)

有点像这个 C++ 代码

void set_to(int x, int* y) {
    *y = x;
}

int y;
set_to(10, &y);

实际上,我希望 C++ 中没有非 const 引用,这样每个 mutator 都必须像上面那样使用指针调用。

同样,除非真的有必要,否则要这样做。改为使用或。multiple-value-bindcl-flet

于 2013-07-22T15:47:20.553 回答