在 Elisp 中如何将参数传递给函数?
How are arguments passed into functions in Elisp?
我有 C++ 背景,我想弄清楚 Elisp 中如何将参数传递给方法。虽然我承认措辞可能会有所不同,但我想知道它是否更接近 C++ 中按引用传递或按值传递的想法?如果我改变方法本身的参数,它会改变函数调用中传入的参数吗?
所有 Lisps (Emacs Lisp, Common Lisp) 按值传递参数,始终:
(defparameter x 42) ; defconst in Emacs Lisp
(defun test (x)
(setq x 10))
(test x)
==> 10
x
==> 42
但是请注意,有些值实际上是 指针(或者更确切地说,是具有组件的对象),因此函数可以修改它们的 content 副作用:
(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? -- "quoted arguments" 也被评估:评估去掉引号。
PS2。比照。 add-to-list
- 它接受一个符号(变量名)并修改它的值。这仅适用于全局动态变量,不适用于词法变量。不是个好主意。
实际上,在 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
我有 C++ 背景,我想弄清楚 Elisp 中如何将参数传递给方法。虽然我承认措辞可能会有所不同,但我想知道它是否更接近 C++ 中按引用传递或按值传递的想法?如果我改变方法本身的参数,它会改变函数调用中传入的参数吗?
所有 Lisps (Emacs Lisp, Common Lisp) 按值传递参数,始终:
(defparameter x 42) ; defconst in Emacs Lisp
(defun test (x)
(setq x 10))
(test x)
==> 10
x
==> 42
但是请注意,有些值实际上是 指针(或者更确切地说,是具有组件的对象),因此函数可以修改它们的 content 副作用:
(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? -- "quoted arguments" 也被评估:评估去掉引号。
PS2。比照。 add-to-list
- 它接受一个符号(变量名)并修改它的值。这仅适用于全局动态变量,不适用于词法变量。不是个好主意。
实际上,在 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