【问题标题】:Lisp pass evaluated expression to macroLisp 将求值表达式传递给宏
【发布时间】:2020-05-17 19:17:28
【问题描述】:

我遇到了一个问题,我有一个宏,等熵扩展,然后调用solve-format,用'x?替换列表中的NIL,然后返回一个可以传递给求解的有效表达式。

(isentropic-expansion 295 nil 1 4.2 1.4)

返回

(-
(expt
  (/ 4.2 1)
  (/
   (- 1.4 1)
   1.4))
 (/ x\? 295))

这是然后放入求解函数的有效表达式

但如果我执行以下操作(假设我已将上述命令的输出设置为变量 expr

(solve expr 2)

宏不会用expr的值替换表达式符号,只是expr字符串,我得到

 Wrong number of arguments: (lambda nil expr), 1

我想这是因为我还没有完全理解宏!谁能解释一下这是为什么?

(defun newton-f (func x0)
    "Solve the equation FUNC(x)=0 using Newton's method.
  X0 is an initial guess."
  (let* ((tolerance 1e-6)
     (x x0)
     (dx 1e-6)
     fx fpx)
    (while (> (abs (funcall func x)) tolerance)
       (setq fx (funcall func x)
         fpx (/ (- (funcall func (+ x dx)) (funcall func (- x dx))) (* 2 dx))
         x (- x (/ fx fpx))))
    x))
(defmacro solve (expression guess)
  `(newton-f
     (lambda ,(cl-loop for item in (flatten expression)
            if (and (symbolp item) (s-ends-with? "?" (symbol-name item)))
            collect item)
       ,expression)
     ,guess))

(defun solve-format (exp)
  (cond ((null exp) 'x?)
    ((atom exp) exp)
    ((list exp) (cons (solve-format (car exp))
              (if (cdr exp)
                  (solve-format (cdr exp))
                nil)))
    (t (print "what"))))

(defmacro isentropic-expansion (t01 t02 p01 p02 gamma)
  `(solve-format '(- (expt (/ ,p02 ,p01) (/ (- ,gamma 1) ,gamma)) (/ ,t02 ,t01))))

【问题讨论】:

    标签: lisp elisp


    【解决方案1】:

    solve也是一个宏:

    (defmacro solve (expression guess) ...)
    

    由于宏不会自动评估它们的参数,当你使用这个时:

    (solve expr 2)
    

    在宏扩展过程中,expression 绑定到符号 expr,guess 绑定到数字 2。

    错误信息中的(lambda nil expr)就是这个调用:

    (lambda ,(cl-loop for item in (flatten expression)
                      if (and (symbolp item) (s-ends-with? "?" (symbol-name item)))
                      collect item)
      ,expression)
    

    【讨论】:

    • 啊-感谢您的解释。请问有没有办法评估表达式然后将其传递给宏?
    • 你能保证这个论点应该被评估吗?如果您传递的是原始表达式,而不是将该表达式作为值保存的变量符号,该怎么办?如果是“有时,但并非总是”的情况,决定的逻辑是什么?
    • 请注意,如果您总是想要评估参数,那么使用宏可能是个错误。普通函数默认评估它们的参数。
    猜你喜欢
    • 2019-11-03
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多