- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的目标是拥有一个宏,可以使用其他地方生成的参数列表自动构建函数。我希望宏返回一个由函数及其使用的参数列表(符号列表)组成的列表。我正在使用 SBCL。
假设参数列表是由以下命令生成的:
(defun input-syms ()
(list 'in1 'in2 'in3))
;;=> (IN1 IN2 IN3)
遵循 Nested `defun` produces a repeated warning in Allegro Common Lisp 中的有用答案,我用了labels
像这样(添加列表的元素,只是为了示例):
(defmacro create-funtest ()
(let ((input-list (input-syms)))
`(labels ((fun-created ,input-list
(reduce #'+ (list ,@input-list))))
#'fun-created)))
(funcall (create-funtest) 2 2 3) ;=> 7
这似乎有效,尽管我认为可能有更简单的方法来做到这一点。 (list ,@input-list)
似乎没有必要,但将其替换为 ,input-list
不起作用。
这就是我不知所措的地方,这似乎与,input-list
到底是什么问题有关。方法。我认为这与我们操作符号有关,所以我尝试抛出 symbol-value
在那里,但无济于事。
我想要获得的内容,以不工作代码表示:
(defmacro create-funtest2 ()
(let ((input-list (input-syms)))
`(labels ((fun-created ,input-list
(reduce #'+ (list ,@input-list))))
(list #'fun-created ,input-list))))
必须返回:(#<FUNCTION ...> (IN1 IN2 IN3))
。但打电话create-funtest2
给出编译错误 The variable IN2 is unbound.
。我认为它试图评估符号,而不是按原样给我符号。
我需要能够获取用于构建函数的符号,我在之后调用函数时使用它们来知道哪个输入是什么。此符号列表也可以通过 create-funtest
进行修改宏,所以我真的需要从宏内部获取它。
感谢 Rainer Joswig 的回答。困扰我的事情实际上是将符号列表作为符号返回。我猜想 create-funtest2
的扩展代码(根据您给出的扩展)应该如下所示:
(LABELS ((FUN-CREATED (IN1 IN2 IN3)
(REDUCE #'+ (LIST IN1 IN2 IN3))))
(LIST #'FUN-CREATED (LIST 'IN1 'IN2 'IN3)))
这样宏的输出就是 (#<FUNCTION ...> (IN1 IN2 IN3))
。问题是我想评估 input-list
,但将其元素保留为符号(抱歉,我不确定我的措辞是否正确)。
谢谢你的核心转储。 create-funtest2
的工作版本是:
(defmacro create-funtest2 ()
(let ((input-list (test-input-syms)))
`(labels ((fun-created ,input-list
(reduce #'+ (list ,@input-list))))
(list #'fun-created (quote ,input-list)))))
这给出了扩展(感谢 Rainer 的代码片段):
(let ((*print-circle* t)
(*PRINT-RIGHT-MARGIN* 50))
(pprint (copy-tree (macroexpand-1 '(create-funtest2)))))
=>
(LABELS ((FUN-CREATED (IN1 IN2 IN3)
(REDUCE #'+ (LIST IN1 IN2 IN3))))
(LIST #'FUN-CREATED '(IN1 IN2 IN3)))
并通过以下方式调用:
(defparameter *fun-created2* (create-funtest2))
(funcall (car *fun-created2*) 1 2 3) ; => 6, OK
(second *fun-created2*) ; => (IN1 IN2 IN3), OK
最佳答案
当给定任意长的输入列表时,您可能想要使用 reduce
的原因是函数调用受到 CALL-ARGUMENT-LIMIT
的限制。 。然而,在这里,您使用符号列表作为函数参数,其限制为 LAMBDA-PARAMETERS-LIMIT
。此外,第二个必须大于或等于第一个。因此,如果符号列表足够短,可以用作参数列表,那么它也足够短,可以用作 +
调用中的参数。
(defun input-symbols ()
'(in1 in2 in3))
(defmacro create-funtest ()
(let ((args (input-symbols)))
`(lambda ,args (+ ,@args))))
上面,我还使用了匿名函数,但这并不重要。
使用与上面相同的方法重写的第二个版本是:
(defmacro bad-create-funtest2 ()
(let ((args (input-symbols)))
`(list (lambda ,args (+ ,@args))
,args)))
macroexpand
是什么意思?说说这个?
(macroexpand '(bad-create-funtest2))
=> (LIST (LAMBDA (IN1 IN2 IN3) (+ IN1 IN2 IN3))
(IN1 IN2 IN3))
在这里,您可以看到您正在尝试使用参数 in2
和 in3
调用 in1
。您不想评估符号列表,只需将其不评估即可传递。
(defmacro create-funtest2 ()
(let ((args (input-symbols)))
`(list (lambda ,args (+ ,@args))
(quote ,args))))
通过引用该值,您可以确保该值不会被评估。
(macroexpand '(create-funtest2))
=> (LIST (LAMBDA (IN1 IN2 IN3) (+ IN1 IN2 IN3))
'(IN1 IN2 IN3))
关于macros - 使用宏构建具有动态输入的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50965761/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!