Mutator elisp功能

时间:2013-06-29 10:46:48

标签: elisp

如何定义mutator elisp函数?也就是说,如何将参数发送到elisp函数,该函数可以在函数内部修改以便在函数外部使用(类似于非const引用变量或C ++中的指针)?例如,假设我有一个函数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_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)
     .
     .
     .
 ))...))

2 个答案:

答案 0 :(得分:2)

我能想到的两种方式:

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

如果函数太复杂,你也可以结合两种方法 - 有一个宏foo创建一个a和b的缺点,并用该缺点调用函数foo0,然后再解压缩汽车和cdr。

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

答案 1 :(得分: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