AutoLisp 2021 在(应用(lambda)时出现参数太少的错误。

问题描述 投票:1回答:1

我们已经安装了最新的Autodesk 2021,我们的一个脚本(修改后的@Lee Mac)对一些输入文本进行剥离和格式化,现在失败了。这个脚本在2019年及以下版本上完美运行。我似乎无法解决为什么会有差异。

我已经将原来的 "vl-catch-all-apply "替换为 "apply",这样我就可以抓住错误。这个错误是。

Too few arguments

这发生在它击中'(lambda函数调用时。下面是调用的代码。

(defun GDD:removeinfo (rgx str)
(if
    (null
        (vl-catch-all-error-p
            (setq str
                (apply
                   '(lambda nil
                        (vlax-put-property rgx 'global     actrue)
                        (vlax-put-property rgx 'multiline  actrue)
                        (vlax-put-property rgx 'ignorecase acfalse) 
                        (foreach pair
                           '(
                                ("\032"     . "\\\\\\\\")
                                ("\n"        . "\\\\P")
                                ("$1"       . "\\\\(\\\\[ACcFfHKkLlOopQTW])|\\\\[ACcFfHKkLlOopQTW][^\\\\;]*;|\\\\[ACcFfKkHLlOopQTW]")
                                ("$1$2/$3"  . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
                                ("$1$2"     . "\\\\(\\\\S)|[\\\\](})|}")
                                ("$1"       . "[\\\\]({)|{")
                                ("\\$1$2$3" . "(\\\\[ACcFfHKkLlOoPpQSTW])|({)|(})")
                                ("\\\\"     . "\032")
                                (""     . "(?:.*\\n)*Const\\s+.*\\n")
                                        (""     . "\\w\\w\\d?\\s+\\d+\\s\\d+-\\d+-\\d+")
                                        (""     . "^\\s+\\n")
                            )
                            (vlax-put-property rgx 'pattern (cdr pair))
                            (setq str (vlax-invoke rgx 'replace str (car pair)))
                        )
                    )
                )
            )
        )
    )
    str
)
)

这个函数的调用在下面。我已经检查了 "输入",它与2019年版本的工作相同,并且使用vlisp(vscode)调试器正确填充str。我把同样的代码和输入都跑了一遍,只有2021版本失败?

(setq input (GDD:removeinfo (vlax-get-or-create-object "VBScript.RegExp") input))

我对LISP不是那么熟悉,我被卡住了。谢谢您的帮助。

lisp autodesk autolisp
1个回答
1
投票

假设 <FUN> 代表的意思。

'(lambda nil
  (vlax-put-property rgx 'global     actrue)
  (vlax-put-property rgx 'multiline  actrue)
  (vlax-put-property rgx 'ignorecase acfalse) 
  (foreach pair
   '(("\032"     . "\\\\\\\\")
     ("\n"        . "\\\\P")
     ("$1"       . "\\\\(\\\\[ACcFfHKkLlOopQTW])|\\\\[ACcFfHKkLlOopQTW][^\\\\;]*;|\\\\[ACcFfKkHLlOopQTW]")
     ("$1$2/$3"  . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
     ("$1$2"     . "\\\\(\\\\S)|[\\\\](})|}")
     ("$1"       . "[\\\\]({)|{")
     ("\\$1$2$3" . "(\\\\[ACcFfHKkLlOoPpQSTW])|({)|(})")
     ("\\\\"     . "\032")
     (""     . "(?:.*\\n)*Const\\s+.*\\n")
     (""     . "\\w\\w\\d?\\s+\\d+\\s\\d+-\\d+-\\d+")
     (""     . "^\\s+\\n"))
   (vlax-put-property rgx 'pattern (cdr pair))
   (setq str (vlax-invoke rgx 'replace str (car pair)))))

你发布的代码,重新写得更紧凑,看起来如下。

(defun GDD:removeinfo (rgx str)
  (if (null (vl-catch-all-error-p
             (setq str (apply <FUN>))))
      str))

特别是,调用 APPLY 只有一个参数。

(apply <FUN>)

APPLY 在Autolisp中,一个函数有两个参数: 一个函数和一个参数列表。

这样做的目的是

(apply f '(0 1))

...的计算方式是: (f 0 1)但可以在运行时建立参数列表。

你只给了一个参数给 apply 在你的代码中,所以你还需要传递一个参数列表.在你的情况下,这将是一个空列表。

(apply <FUN> nil)

1
投票

而不是改变 vl-catch-all-applyapply 为了查看错误,只需将错误输出为 别的 旗下 if 语句,比如说。

(if
    (null
        (vl-catch-all-error-p
            (setq str
                (vl-catch-all-apply
                    ...
                )
            )
        )
    )
    str
    (prompt (strcat "\nError: " (vl-catch-all-error-message str))) ;; Output error and return nil
)

顺便说一句,虽然这段代码比较琐碎,但我不确定我是否同意你把95%的代码挪用到我的函数上,并去掉我的标题和作者前缀。


0
投票

不管是谁写的这段代码,似乎都没有意识到这一点。progn 操作符。

所以也就是说,如果我们要对多个表达式进行评估 e1, e2,......为了它们产生的副作用,我们不必这样做。

;; wrap expressions in a dummy lambda and apply empty arg list to it
(apply (lambda () e1 e2 ...) nil)

我们可以直接写这个

(progn e1 e2 ...)

这还是给我们留下了一个奇怪的代码,看起来像这样。

(setq str (progn .... (setq str value)))

这段代码将变量 str 两次相同的值。深度嵌套的 (setq str value) 放置 value 变成 str 然后得出该值作为结果。这是最后一个表达式的 progn (原文如此)。lambda),所以该值也被返回。 然后外部的 setq 滥竽充数 str 再次。我们只需要一个或另一个。

;; set str as the side effect of the last form in the
;; progn; also yield that value.
(progn e1 e2 ...(setq str value))

;; assign value yielded from progn to str, then also
;; yield that value.
(setq str (progn e1 e2 ... value))
© www.soinside.com 2019 - 2024. All rights reserved.