openlang

with-lenient-parse 记录了错误,但 SBCL 还是会进入调试器

我写了个宏,让 hosts 文件里的坏行被记录下来,加载继续往下走。完整代码如下。

(defmacro with-lenient-parse ((&key (log t)) &body body)
  `(handler-bind ((missing-field
                    (lambda (c)
                      (when ,log
                        (format *error-output* "skipping: ~A~%" c))
                      nil))
                  (bad-port
                    (lambda (c)
                      (when ,log
                        (format *error-output* "warn: ~A~%" c))
                      nil)))
     ,@body))

parse-line 有一个 skip-line 重启,但我不确定有没有东西会调用它。输入格式是 name addr [port],每行一台主机,我用 sh run.sh 运行。

文件里有 web-02(没有 addr)时,stderr 上会出现 skipping: line 2: missing addr。然后 SBCL 带着同一个 missing-field 错误进入调试器,脚本就挂了。我以为从 handler 里返回就会让 parse-line 对这一行返回 nil,对吧?看来不是。

我把 web-02 那行删了才继续往下。现在得到 warn: line 4: bad port abc,接着 privileged-p 里报类型错误,说 NIL 不是 NUMBER 类型。那个函数跟解析毫无关系。端口条件只是对 warning 子类的一次普通 signal,我写的东西里没有哪处把它当成致命的。

这是两个 bug,还是对 handler 如何挂接的同一个误解?这个宏到底向调用方承诺了什么?我是凭对终端记录的印象写的,所以没法贴完整的回溯信息。

从英语翻译查看原文

后续讨论 2

顺着彼此的依据读下去
  1. 固定链接

    我觉得是一个误解。handler-bind 的处理器直接返回只是表示放弃处理,所以这个 condition 会继续交给下一个处理器,没有处理器了就进调试器。没有任何东西会让 parse-line 返回 nil。你得在处理器里调用 restart,也就是 (invoke-restart 'skip-line)。

    bad-port 的情况也一样。signal 返回 nil,所以 privileged-p 里的 port 还是 nil。

    https://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm

    从英语翻译查看原文
  2. 固定链接

    关于重启这个修法有个小提醒(挺方便的,因为 handler 在栈展开之前就运行了)。要用 find-restart 包一层,因为 skip-line 没激活时,直接 invoke-restart 会报错。

    (lambda (c)
      (let ((r (find-restart 'skip-line c)))
        (when r (invoke-restart r))))
    从英语翻译查看原文

同一个问题的其他角度

  1. 空归约返回单位元

    对空向量做归约,APL 有答案。 每个原语都自带它的单位元。加法是 0,乘法和与是 1。⌈/⍬ 给出解释器里最小的负数。调用方不需要特殊处理,归约之前也不用检查长度。 dfn 就没有这种待遇。{⍺+⍵}/⍬ 在 Dyalog 里是 DOMAIN ER…

    回复 3最近活动 apl
  2. 我的大部分宏最后都变成了 const 和 static

    Nim 写宏太容易了,问题就出在这儿。 在动手写 macro 之前,先看看更便宜的工具。const 是在编译期求值的,用的就是跑宏的那个 VM,所以由普通 proc 构建的查找表直接写成 const table = buildTable() 就行。s…

    回复 3最近活动 nim
  3. it、_1,还有我仍在写的块参数名

    Ruby 3.4 为块参数加了 it,所以 users.map { it.name } 读起来几乎像一句话。我比较喜欢它,不太喜欢 _1,那东西总像是解析器随手丢下的。 Proc 文档里有几条规则值得知道。it 只存在于没有显式参数的块里。它是软关键…

    回复 0最近活动 ruby