在 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))
我正在编写一个通用的 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))