在 Common Lisp 中测试一个变量是否包含一个函数

Testing if a Variable Contains a Function in Common Lisp

我正在编写一个通用的 lisp 程序,并且我有一个可以包含字符串或函数的变量。我想调用该函数,如果它是一个 return 以及字符串。如何测试变量是否为函数?

到目前为止的代码:

(defun string-or-function (var)
 (if (typep var 'simple-array)
   var
   (if "Function equivalent of typep goes here."


(setf temp (fn-that-does-something))
(string-or-function temp)

编辑:有效代码:

(defun string-or-function (var)
 (let ((s-or-f (type-of var)))
  (if (equal s-or-f 'function)
   (print "function")
    (if (equal (car s-or-f) 'simple-array)
     (print "string")))))

有更好的方法吗?

(eq (type-of var) 'function)

但是,请记住 Common Lisp 将变量和函数名称保存在不同的命名空间中,因此 (var 1 2 3) 和 (cons var 1) 在两个不同的地方查找。您可能无法像 (var) 那样调用 var,而是需要使用 (funcall var),具体取决于它所在的命名空间。

基本上,您可能不应该将 function-or-maybe-a-string 填充到一个变量中。

Common Lisp 有一个谓词类型系统。值具有 "principal" 类型的概念在 Lisp 中没有多大意义。 type-of 函数实际上很少使用,因为询问 "What is the type of X" 不太有意义,而询问 "Is X of type Y" 更有意义。这可以用 typep 来完成,或者在你的情况下更简洁地用 typecase 来完成,这只是类型的 case 语句。

(defun string-or-function (var)
    (typecase var
      (string (format t "string"))
      (function (format t "function"))
      (t (format t "something else"))))

还有一些其他方法:

(defun string-or-function-p (x)
  (typep x '(or string function)))

...但您也可以使用 check-type,它不是谓词而是检查,如果值不满足类型规范,它会发出可重启条件的信号:

(check-type place (or string function))

如果你碰巧经常使用这个类型,定义一个自定义类型:

(deftype string-or-fun () '(or string function))

当然,你也可以根据需要使用泛型函数(愚蠢的例子):

(defgeneric execute (object)
  (:method ((s string)) (eval (read-from-string s)))
  (:method ((f function)) (funcall f)))

但请注意 上的泛型函数调度,而不是 types,这是不同的东西。

I want to call the function if it is one and return that as well as the string.

我想你的意思是这样的:

(defun evaluate (arg)
  "Returns something from evaluating ARG in some manner.  If ARG is a string,
return it.  If ARG is a function, call it with no arguments and return its
return value(s)."
  (ctypecase arg
    (string arg)
    (function (funcall arg))))

如果您需要扩展性:

(defgeneric evaluate (arg)
  (:documentation "Returns something from evaluating ARG in some manner."))

(defmethod evaluate ((arg string))
  arg)

(defmethod evaluate ((arg function))
  (funcall arg))