首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用SETF函数扩展SETF?

如何使用SETF函数扩展SETF?
EN

Stack Overflow用户
提问于 2014-06-06 21:03:05
回答 2查看 885关注 0票数 8

在实用的通用Lisp章节http://www.gigamonkeys.com/book/object-reorientation-classes.html部分访问器函数中,我发现很难理解SETF的扩展方式。

职能:

代码语言:javascript
复制
(defun (setf customer-name) (name account)
  (setf (slot-value account 'customer-name) name))

bank-account类定义:

代码语言:javascript
复制
(defclass bank-account ()
  ((customer-name
    :initarg :customer-name
    :initform (error "Must supply a customer name."))
   (balance
    :initarg :balance
    :initform 0)
   (account-number
    :initform (incf *account-numbers*))
   account-type))

我不明白的是:

  • 在表达式(setf (customer-name my-account) "Sally Sue")中,(customer-name my-account)是否返回类bank-account的SETFable时隙值customer-name,然后SETF用于将值设置为"Sally“?
  • (setf (customer-name my-account) "Sally Sue")实际上是在调用上面的函数吗?
  • 如上所述,setf customer-name是一个函数吗?
  • 在上面的函数中,customer-name(setf customer-name)中,'customer-name在主体中指的是相同的东西吗?
  • 这一节说 第二个元素是一个符号,通常是用于访问SETF函数将要设置的位置的函数的名称。

如果是这样的话,那么为什么在函数的定义中使用slot-value函数,而这个函数可以用来访问这个位置?

EN

回答 2

Stack Overflow用户

发布于 2014-06-06 21:32:08

在许多情况下,访问和设置数据需要两件事:

  • 从数据结构中检索某物的一种方法
  • 在数据结构中设置某物的一种方法

因此,可以定义一个setter函数和一个getter函数。对于简单的情况,它们看起来也很简单。但对于复杂的情况,他们可能不会。现在,如果您知道getter的名称,那么setter的名称是什么?或者:如果你知道设置者的名字,那么getter的名字是什么?

常见的Lisp有这样的想法,您只需要知道getter的名称。

  • 这个getter叫做,比如说,GET-FOO
  • 然后,setter函数称为(SETF GET-FOO)。一直都是。
  • 可以这样调用setter函数:(setf (get-foo some-bar) new-foo)。一直都是。

所以您编写了GET-FOO函数。您还编写了(SETF GET-FOO)函数,并且Common将它注册为一个setter函数。

(SETF GET-FOO)是一个列表。它也是函数的名称。这里我们有一个例外:公共Lisp有时允许一个列表作为一个函数名。因此,并不是所有的函数名都是符号,有些实际上是列表。

(setf (customer-name my-account) "Sally Sue")实际上是调用定义的setter。my-account是一个变量,其值将绑定到setter的account变量。"Sally Sue"是一个字符串,它将绑定到setter的name变量。

作为一名开发人员,您只需了解getter:

  • getter的使用:(customer-name my-account)
  • 使用setter:(setf (customer-name my-account) "Sally Sue")SETF是一个宏,它扩展为setter函数的调用。

代码语言:javascript
复制
(defun (setf customer-name) (name account)
  (setf (slot-value account 'customer-name) name))

上面定义了一个名为(setf customer-name)的setter函数。

代码语言:javascript
复制
CL-USER 80 > (function (setf customer-name))
#<interpreted function (SETF CUSTOMER-NAME) 40A00213FC>

当函数通过SETF宏调用时,它会调用另一个setter --这一次通过槽名访问一个槽值。

票数 11
EN

Stack Overflow用户

发布于 2014-06-11 13:02:10

setf是一个非常复杂的宏,它知道如何将其第一个参数(通常看起来像函数调用)解码为" place“,然后调用设置该位置为新值所需的任何形式。将(customer-name my-account)看作是返回setf表达式中的任何内容是没有用的。setf宏将HyperSpec中定义的规则应用于其place窗体,并且作为默认情况,将转换

代码语言:javascript
复制
(setf (foo arg0 arg1 ...) new-val)

代码语言:javascript
复制
(funcall #'(setf foo) new-val arg0 arg1 ...)

在实际的Common中,文章以一种有点椭圆的方式解释了在:accessor插槽定义中指定一个defclass选项在幕后发生了什么。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24090571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档