我对LISP很陌生,我不知道当其中一个因子为0时,如何使我的无限参数函数停止评估其余参数。我试过这个
foo = c("Animal", foo)
df = data.frame(do.call(rbind, split(foo, ceiling(seq_along(foo)/4))),
stringsAsFactors = FALSE)
colnames(df) = df[1,]
df = df[-1,]
df
# Animal A B C
#2 Dog 1 2 3
#3 Cat 4 5 6
#4 Goat 7 8 9
但我认为这不会停止增加,直到它检查所有变量。
答案 0 :(得分:0)
当谓词没有达到时,unless
表单评估为nil
:
(macroexpand-1 '(smart-multiplication 1 2 0))
; ==> nil
也许您应该使用ìf
因为您希望它变为零?
(defmacro smart-multiplication (&rest l)
(if (member 0 l)
0
`(* ,@l)))
(macroexpand-1 '(smart-multiplication 1 2 3 0))
; ==> 0
(macroexpand-1 '(smart-multiplication 1 2 3))
; ==> (* 1 2 3)
请注意,它仅适用于文字零,因为宏只知道变量作为符号,而且从来没有关于它们的值的任何信息,当你有一个零变量时,它就不会工作:
(defparameter *zero* 0)
(macroexpand-1 '(smart-multiplication 1 2 3 *zero*))
; ==> (* 1 2 3 *zero*)
基本上你不能把宏看作程序计算,因为它只是抽象代码。从而使语法被重写为Common Lisp支持的东西。例如。 unless
是一个宏:
(macroexpand-1 '(unless some-predicate
result-1
result-2))
; ==> (if (not some-predicate) (progn result-1 result-2))
答案 1 :(得分:0)
您需要在运行时检查零值。
(defmacro smart-multiplication (&rest list)
(if (null list)
1
(let ((n0sym (gensym "mult")))
`(let ((,n0sym ,(first list)))
(if (zerop ,n0sym)
0
(* ,n0sym (smart-multiplication ,@(rest list))))))))
CL-USER 42 > (smart-multiplication (print 1) (print 2) (print 3))
1
2
3
6
CL-USER 43 > (smart-multiplication (print 1) (print 0) (print 3))
1
0
0
使用Lispworks 代码漫游器完全展开生成的代码:
CL-USER 46 > (pprint (walker:walk-form
'(smart-multiplication (print 1)
(print 0)
(print 3))))
(LET ((#:|mult973| (PRINT 1)))
(IF (ZEROP #:|mult973|)
0
(* #:|mult973|
(LET ((#:|mult974| (PRINT 0)))
(IF (ZEROP #:|mult974|)
0
(* #:|mult974|
(LET ((#:|mult975| (PRINT 3)))
(IF (ZEROP #:|mult975|) 0 (* #:|mult975| 1)))))))))
<强>问题强>
现在代码仍然看起来不太好。 改进仍留作练习:
*
函数调用。提示一个简单的解决方案:生成的代码可能与此类似:
(prog ((result 1)
value)
(setf value (print 1))
(when (zerop value)
(return 0))
(setf result (* result value))
(setf value (print 0))
(when (zerop value)
(return 0))
(setf result (* result value))
(setf value (print 3))
(when (zerop value)
(return 0))
(setf result (* result value))
(return result))