【问题标题】:Specialize Generic Function (Multimethod) on Two Arguments在两个参数上专门化泛型函数(多方法)
【发布时间】:2017-01-08 05:55:48
【问题描述】:

我正在尝试在 common lisp 中构建二叉搜索树。我已经使用 CLOS 定义了二进制搜索类,如下所示:

(defclass bst ()
  ((root :type node
         :accessor tree-root
         :initform nil
         :initarg root)))

我正在尝试定义一个通用函数,它接受树对象和一个键,如果树包含键,则返回布尔值 true,如果树不包含键,则返回 nil。

现在我对泛型函数有以下定义:

(defgeneric contains ((tree bst) (key))
   (:documentation "returns boolean of whether the given tree contains a particular key)

当我将文件加载到 REPL 中时出现以下错误(我正在使用 SBCL):

Required argument is not a symbol: (TREE BST)

我是否误解了泛型函数的工作原理?我似乎无法正确定义函数。

【问题讨论】:

  • 类型签名应该去方法,而不是DEFGENERIC
  • 只是一点旁注:<...> :initarg root 应该是 <...>:initarg :root:root 应该是这里的关键字。
  • @mobiuseng 只是为了玩书呆子:) initargs 是关键字符号很常见,但这不是必需的。非关键字符号有助于避免名称冲突,内部符号有助于表明“除非你知道自己在做什么,否则不要使用它”。
  • @JoshuaTaylor 公平点。我还想了一会儿,没有什么能真正阻止使用符号作为 initarg 的,尽管我以前从未见过它。这就是为什么我把“应该”:)

标签: lisp common-lisp clos


【解决方案1】:

是的,defgeneric 定义了一个通用函数。您可以在调用defgeneric 或使用defmethod 中指定方法。

您需要以下之一:

(defgeneric contains (tree key)
   (:documentation "returns boolean of whether the given tree contains a particular key")
   (:method ((tree bst) key) ...))

或:

(defgeneric contains (tree key)
   (:documentation "returns boolean if a given tree contains a given key"))

(defmethod contains ((tree bst) key)
  ...)

【讨论】:

  • 你写“任何一个”......这是否意味着我不能混合使用这两种方法?
  • @DanielJour 你可以,但我的记忆表明重定义时发生的事情变成了实现指定的。只要您完全控制方法和类,请坚持为任何特定泛型函数定义方法的两种方法之一。否则,使用defmethod 方式。我通常只使用defmethod 而不是在defgeneric 中指定方法。
猜你喜欢
  • 2019-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多