Common Lisp:避免评估函数中的符号

时间:2017-08-21 12:07:24

标签: lisp common-lisp

我在Common Lisp中遇到了一个小问题。我需要编写一个函数,它将一个符号作为参数(即一个函数的名称或一个变量的名称),然后执行其他操作,然后打印该符号而不进行评估。引用在这种情况下不起作用,所以我该怎么做?例如,假设我将var定义为带3的整数defparameter,那么该函数应具有此行为:

(my-function var)
REPL: var is a symbol and its value is 3.

如何打印var?如何在REPL上查看var,或者在my-function中为输入变量指定的任何其他名称?有人能帮助我吗?

3 个答案:

答案 0 :(得分:7)

您正在寻找的功能不可能与函数一起使用,因为它们可能已被编译为参数只是在堆栈上传递而代码查看内存索引而不是变量。

您正在寻找某种元编程,这就是宏的用途:

(defmacro info (expr)
  (let ((compile-type (type-of expr)) (tmp (gensym "tmp")))
    `(let ((,tmp ,expr))
       (format t "REPL: ~s is a ~a and it's value is ~s~%" ',expr ',compile-type ,tmp)
       ,tmp)))


(info "test")
; REPL: "test" is a (simple-base-string 4) and it's value is "test"
; ==>  "test"
(info *print-circle*)
; REPL: *print-circle* is a symbol and it's value is nil
; ==> nil
(info #'+)
; REPL: #'+ is a cons and it's value is #<system-function +>
; ==> #<system-function +>
(info (+ 3 4))
; REPL: (+ 3 4) is a cons and it's value is 7
; ==> 7

答案 1 :(得分:3)

  

引用在这种情况下不起作用,我该怎么办?

怎么样? Quote在这种情况下工作。当我们调用时:

(my-function 'var)

my-function函数现在将符号var作为参数; var未被评估。

如果var是动态变量,则该函数可以使用访问者symbol-value检查或延迟其值:

(defun my-function (sym)
  (format t "value of dynamic variable ~s is ~s~%."
          sym
          (symbol-value sym)))

如果我们想将sym视为一种功能,那就更简单了:

(defun my-function (sym)
  (funcall sym 42))  ;; call function, pass 42 as argument

在Common Lisp中,可以指定符号所在的符号。符号被解析为全局环境中的函数,并使用该函数。这就是(mapcar 'fun ...)可以代替(mapcar #'fun ...)的原因。 (这些通常具有相同的效果,但是在动态重新定义函数时会出现编译语义的细微差别。)

答案 2 :(得分:1)

你不能my-function是普通的(defun - ed)函数,因为它们总是评估它们的参数。你可能想把它变成一个宏。

阅读一本好的Common Lisp书。