【问题标题】:How are arguments passed into functions in Elisp?Elisp 中的参数是如何传递给函数的?
【发布时间】:2018-06-30 00:49:38
【问题描述】:

来自 C++ 背景,我试图弄清楚参数是如何传递给 Elisp 中的方法的。虽然我承认措辞可能会有所不同,但我想知道它是否更接近 C++ 通过引用传递或按值传递的想法?如果我改变方法本身的参数,它会改变函数调用中传入的参数吗?

【问题讨论】:

    标签: lisp parameter-passing elisp


    【解决方案1】:

    所有 Lisps(Emacs LispCommon Lisp)总是按值传递参数:

    (defparameter x 42)  ; defconst in Emacs Lisp
    (defun test (x)
      (setq x 10))
    (test x)
    ==> 10
    x
    ==> 42
    

    但是请注意,有些值实际上是指针(或者,更确切地说,是带有组件的对象),因此函数可以通过副作用修改它们的内容

    (defparameter x (list 1 2))
    (defun test (x)
      (setf (first x) 42
            (second x) 24
            x 17))
    (test x)
    ==> 17
    x
    ==> (42 24)
    

    PS1。参照。 When to use ' (or quote) in Lisp? -- “引用的参数”也会被评估:评估会去掉引用。

    PS2。参照。 add-to-list - 它接受一个符号(变量名)并修改它的值。这仅适用于全局动态变量, 用于词法变量。不是一个好主意。

    【讨论】:

      【解决方案2】:

      实际上,在 Emacs Lisp 中,没有像通过值或引用传递参数这样的事情,更不用说指针了。但是传递给函数的所有参数都将被提前评估,除了那些有' 前缀的参数。永远记住当你设置一个变量时,你总是只创建一个带有值的符号。[1]

      所以如果你想在一个函数中修改一个变量的值,你需要做的就是在那个函数中修改那个变量的符号的值。

      检查我的代码如下。

      (defvar my-val 1)
      
      (defun my-func-value (val)
        (setq val 2))
      
      (defun my-func-symbol (sym)
        ;; NOTE! using set instead of setq,
        ;; casue we want symbol "my-val" be evaluated from "sym" here
        (set sym 2))
      
      (my-func-value my-val) ; evaluate my-val before passed into function
      (message "my-val: %s" my-val) ; my-val: 1
      
      (my-func-symbol 'my-val) ; pass my-val symbol directly into function
      (message "my-val: %s" my-val) ; my-val: 2
      

      注意!如果该变量是词法绑定变量[2],则仍然可以修改符号的值,但不能修改词法环境中的值。

      代码如下:

      (let ((my-lexical-var 1))
        (my-func-symbol 'my-lexical-var)
        ;; evaluate from lexical environment
        (message "my-lexical-var: %s" my-lexical-var) ; my-lexical-var: 1
        ;; evaluate from the symbol
        (message "symbol my-lexical-var: %s" (symbol-value 'my-lexical-var))
        ; symbol my-lexical-var: 2
      

      【讨论】:

      • 所有函数参数总是被评估。 ' 不是前缀,而是阅读器宏,用于缩写 quote form,其计算结果为第二项。
      • 是的,我知道这是一个引用形式,但也像该变量的前缀。无论如何,你错过了重点。您是否查看了我上面的代码狙击,这就是我试图指出的。@sds
      • 请注意,如果变量具有 lexical 范围(这里不是这种情况),那么传递变量的符号允许您修改变量的值是不正确的set(因为词法值和符号值不是一回事)。
      猜你喜欢
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      • 2011-10-09
      • 2021-05-22
      • 2017-07-11
      相关资源
      最近更新 更多