测试变量是否包含Common Lisp中的函数

时间:2016-01-20 17:17:39

标签: common-lisp

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

到目前为止

代码:

(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")))))

有更好的方法吗?

4 个答案:

答案 0 :(得分:7)

Common Lisp有一个预测型系统。一个值具有“主体”类型的概念在Lisp中没有那么多意义。 type-of函数实际上很少被使用,因为询问“X的类型是什么”并且更有意义地问“Y是X的类型”是没有意义的。这可以使用typep完成,或者更简洁地使用typecase,这只是类型的案例陈述。

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

答案 1 :(得分:2)

  

我想调用该函数,如果它是一个并返回该函数以及字符串。

我认为你的意思是这样的:

(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))

答案 2 :(得分:0)

以下是其他一些方法:

(check-type place (or string function))

...但是您也可以使用check-type,它不是谓词,而是一个检查,如果值不满足类型规范,则表示可重新启动的条件:

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

如果您碰巧经常使用此类型,请定义自定义类型:

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

当然,您也可以根据需要使用通用功能(愚蠢的例子):

{{1}}

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

答案 3 :(得分:-1)

(eq (type-of var) 'function)

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

基本上,你可能不应该将一个函数或者一个字符串填充到一个变量中。