- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在玩弄宏和 clos,在那里我创建了一个“对象”宏来创建实例
(defmacro object (class &rest args)
`(make-instance ',class ,@args))
现在这样做,我最终也有点想为 clos 创建的访问器函数做一些类似的事情。示例:
(defclass person () ((name :accessor person-name :initarg :name)))
然后创建实例
(setf p1 (object person :name "tom"))
现在要从对象中获取名称,显然我会调用 person-name,但是就像对象宏一样,我想创建一个“gets”宏来执行此操作。所以理想情况下:
(gets person name p1) which then would return the name.
接下来的问题是person和name(person-name)的绑定(bind)以及如何绑定(bind)。有没有办法在宏中将这两个参数绑定(bind)在一起?有点像:
(defmacro gets (class var object)
`(,class-,var ,object))
最佳答案
我想我可能误解了原意。起初我以为你在问如何为类定义生成访问器名称,答案的第三部分解决了这个问题。第二次阅读后,听起来您实际上想要生成一个新符号并用一些参数调用它。这也很容易,并在本答案的第二部分给出。第二部分和第三部分都取决于能够创建一个符号,该符号的名称是根据其他符号的名称构建的,这就是我们的起点。
每个符号都有一个名称(字符串),您可以使用 symbol-name 获得该名称.您可以使用 concatenate从一些旧字符串创建一个新字符串,然后使用 intern获取具有新名称的符号。
(intern (concatenate 'string
(symbol-name 'person)
"-"
(symbol-name 'name)))
;=> PERSON-NAME
(defmacro gets (class-name slot-name object)
(let ((accessor-name
(intern (concatenate 'string
(symbol-name class-name)
"-"
(symbol-name slot-name))
(symbol-package class-name))))
`(,accessor-name ,object)))
(macroexpand-1 '(gets person name some-person))
;=> (PERSON-NAME SOME-PERSON)
但是,出于多种原因,这不是很可靠。 (i) 您不知道插槽是否具有 <class-name>-<slot-name>
形式的访问器. (ii) 即使插槽确实具有 <class-name>-<slot-name>
形式的访问器,你不知道它在什么包里。在上面的代码中,我做了一个合理的假设,它和类名的包是一样的,但这根本不是必需的。例如,您可以:
(defclass a:person ()
((b:name :accessor c:person-name)))
然后这种方法根本行不通。 (iii) 这不适用于继承。如果你继承person
, 用 north-american-person
说, 那么您仍然可以调用 person-name
用north-american-person
, 但你不能调用 north-american-person-name
与任何东西。 (iv) 这似乎是在重新发明 slot-value .您已经可以通过 (slot-value object slot-name)
单独使用槽的名称来访问槽的值。 ,而且我看不出有任何理由表明您的 gets
宏不应该只是扩展到那个。在那里,您不必担心访问器的特定名称(如果它有的话),或类名的包,而只需担心插槽的实际名称。
您只需要提取符号的名称并生成具有所需名称的新符号即可。
如果你想自动生成具有 defstruct 样式名称的访问器,你可以这样做:
(defmacro define-class (name direct-superclasses slots &rest options)
(flet ((%slot (slot)
(destructuring-bind (slot-name &rest options)
(if (listp slot) slot (list slot))
`(,slot-name ,@options :accessor ,(intern (concatenate 'string
(symbol-name name)
"-"
(symbol-name slot-name)))))))
`(defclass ,name ,direct-superclasses
,(mapcar #'%slot slots)
,@options)))
您可以通过查看宏展开来检查这是否产生了您期望的代码类型:
(pprint (macroexpand-1 '(define-class person ()
((name :type string :initarg :name)
(age :type integer :initarg :age)
home))))
(DEFCLASS PERSON NIL
((NAME :TYPE STRING :INITARG :NAME :ACCESSOR PERSON-NAME)
(AGE :TYPE INTEGER :INITARG :AGE :ACCESSOR PERSON-AGE)
(HOME :ACCESSOR PERSON-HOME)))
我们可以看到它按预期工作:
(define-class person ()
((name :type string :initarg :name)
(age :type integer :initarg :age)
home))
(person-name (make-instance 'person :name "John"))
;=> "John"
(defmacro object (class &rest args)
`(make-instance ',class ,@args))
作为Rainer pointed out这不是很有用。对于大多数情况,它与
相同(defun object (class &rest args)
(apply 'make-instance class args))
除了你可以 (funcall #'object …)
和 (apply #'object …)
使用函数,但不能使用宏。
您的 gets 宏实际上并不比 slot-value 更有用。 ,它接受一个对象和一个插槽的名称。它不需要类的名称,即使类没有读取器或访问器,它也能正常工作。
format
创建符号名称我一直在用 concatenate 和 symbol-name 创建符号名称。有时您会看到人们使用格式来构造名称,例如 (format nil "~A-~A" 'person 'name)
,但这很容易出现可以更改的大写设置问题。例如,在下面,我们定义了一个函数 foo-bar,并注意到基于格式的方法失败了,但是基于连接的方法有效。
CL-USER> (defun foo-bar ()
(print 'hello))
FOO-BAR
CL-USER> (foo-bar)
HELLO
HELLO
CL-USER> (setf *print-case* :capitalize)
:Capitalize
CL-USER> (funcall (intern (concatenate 'string (symbol-name 'foo) "-" (symbol-name 'bar))))
Hello
Hello
CL-USER> (format nil "~a-~a" 'foo 'bar)
"Foo-Bar"
CL-USER> (intern (format nil "~a-~a" 'foo 'bar))
|Foo-Bar|
Nil
CL-USER> (funcall (intern (format nil "~a-~a" 'foo 'bar)))
; Evaluation aborted on #<Undefined-Function Foo-Bar {1002BF8AF1}>.
这里的问题是我们没有保留参数的符号名称的大小写。为了保留大小写,我们需要显式提取符号名称,而不是让打印函数将符号名称映射到其他字符串。为了说明问题,请考虑:
CL-USER> (setf (readtable-case *readtable*) :preserve)
PRESERVE
;; The symbol-names of foo and bar are "foo" and "bar", but
;; you're upcasing them, so you end up with the name "FOO-BAR".
CL-USER> (FORMAT NIL "~{~A~^-~}" (MAPCAR 'STRING-UPCASE '(foo bar)))
"FOO-BAR"
;; If you just concatenate their symbol-names, though, you
;; end up with "foo-bar".
CL-USER> (CONCATENATE 'STRING (SYMBOL-NAME 'foo) "-" (SYMBOL-NAME 'bar))
"foo-bar"
;; You can map symbol-name instead of string-upcase, though, and
;; then you'll get the desired result, "foo-bar"
CL-USER> (FORMAT NIL "~{~A~^-~}" (MAPCAR 'SYMBOL-NAME '(foo bar)))
"foo-bar"
关于macros - 在宏中将两个变量合并为一个函数名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24433035/
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How to nest OR statements in JavaScript? 有没有办法做到这一点:
在 JavaScript 中有没有办法让一个变量总是等于一个变量?喜欢var1 = var2但是当var2更新,也是var1 . 例子 var var1 = document.getElementBy
我正在努力理解这代表什么 var1 = var2 == var3 我的猜测是这等同于: if (var2 == var3): var1 = var2 最佳答案 赋值 var1 = var2
这个问题已经有答案了: What does the PHP error message "Notice: Use of undefined constant" mean? (2 个回答) 已关闭 8
我在临时表中有几条记录,我想从每条记录中获取一个值并将其添加到一个变量中,例如 color | caption -------------------------------- re
如何将字符串转为变量(字符串变量--> $variable)? 或者用逗号分隔的变量列表然后转换为实际变量。 我有 2 个文件: 列名文件 行文件 我需要根据字符串匹配行文件中的整行,并根据列名文件命
我有一个我无法解决的基本 php 问题,我也想了解为什么! $upperValueCB = 10; $passNodeMatrixSource = 'CB'; $topValue= '$uppe
这可能吗? php $variable = $variable1 || $variable2? 如果 $variable1 为空则使用 $variable2 是否存在类似的东西? 最佳答案 PHP 5
在 Perl 5.20 中,for 循环似乎能够修改模块作用域的变量,但不能修改父作用域中的词法变量。 #!/usr/bin/env perl use strict; use warnings; ou
为什么这不起作用: var variable; variable = variable.concat(variable2); $('#lunk').append(variable) 我无法弄清楚这一点
根据我的理解,在32位机器上,指针的sizeof是32位(4字节),而在64位机器上,它是8字节。无论它们指向什么数据类型,它们都有固定的大小。我的计算机在 64 位上运行,但是当我打印包含 * 的大
例如: int a = 10; a += 1.5; 这运行得很完美,但是 a = a+1.5; 此作业表示类型不匹配:无法从 double 转换为 int。所以我的问题是:+= 运算符 和= 运算符
您好,我写了这个 MySQL 存储过程,但我一直收到这个语法错误 #1064 - You have an error in your SQL syntax; check the manual that
我试图在我的场景中显示特定的奖牌,这取决于你的高分是基于关卡的目标。 // Get Medal Colour if levelHighscore goalScore { sc
我必须维护相当古老的 Visual C++ 源代码的大型代码库。我发现代码如下: bIsOk = !!m_ptr->isOpen(some Parameters) bIsOk的数据类型是bool,is
我有一个从 MySQL 数据库中提取的动态产品列表。在 list 上有一个立即联系 按钮,我正在使用一个 jquery Modal 脚本,它会弹出一个表单。 我的问题是尝试将产品信息变量传递给该弹出窗
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
jQuery Core Style Guidelines建议两种不同的方法来检查变量是否已定义。 全局变量:typeof variable === "undefined" 局部变量:variable
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: “Variable” Variables in Javascript? 我想肯定有一种方法可以在 JavaScrip
在语句中使用多重赋值有什么优点或缺点吗?在简单的例子中 var1 = var2 = true; 赋值是从右到左的(我相信 C# 中的所有赋值都是如此,而且可能是 Java,尽管我没有检查后者)。但是,
我是一名优秀的程序员,十分优秀!