lisp:动态范围与显式参数传递

丹尼尔·戴

我在常见的lisp中看到了两种不同的“输出”功能模式:

(defun implicit ()
  (format t "Life? Don't talk to me about life!"))

(defun explicit (stream)
  (format stream "This will all end in tears."))

(defun test-im-vs-ex-plicit ()
  (values
   (with-output-to-string (stream)
     (let ((*standard-output* stream))
       (implicit)))
   (with-output-to-string (stream)
     (explicit stream))))

使用动态范围是像在implicit不良实践中那样,还是动态范围界定被普遍接受?请注意,我假设这是用于例如DSL构建复杂的输出,例如HTML,SVG,Latex或其他任何东西,并且除了产生打印的表示形式之外,不会做任何其他事情。

除了样式外,是否还有其他重要差异,例如在性能,并发性等方面?

雷纳·乔斯维格

实际上,您可以*standard-output*直接绑定

(defun test-im-vs-ex-plicit ()
  (values
   (with-output-to-string (*standard-output*)   ; here
     (implicit))
   (with-output-to-string (stream)
     (explicit stream))))

没有真正简单的答案。我的建议:

使用流变量,这使调试更加容易。它们出现在参数列表中,并且更容易在回溯中发现。否则,您将需要在回溯中查看流变量的动态重新绑定。

a)没有通过?

(defun print-me (&optional (stream *standard-output*))
  ...)

b)一个或多个固定参数:

(defun print-me-and-you (me you &optional (stream *standard-output*))
  ...)

c)一个或多个固定参数和多个可选参数:

(defun print-me (me
                 &key
                 (style  *standard-style*)
                 (font   *standard-font*)
                 (stream *standard-output*))
  ...)

另请注意:

现在假设(implicit)有一个错误,我们得到一个break循环,一个调试repl在此中断循环中标准输出的值是多少?

CL-USER 4 > (defun test ()
              (flet ((implicit ()
                       (write-line "foo")
                       (cerror "go on" "just a break")
                       (write-line "bar")))
                (with-output-to-string (stream)
                  (let ((*standard-output* stream))
                    (implicit)))))
TEST

CL-USER 5 > (compile 'test)
TEST
NIL
NIL

CL-USER 6 > (test)

Error: just a break
  1 (continue) go on
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 7 : 1 > *standard-output*
#<SYSTEM::STRING-OUTPUT-STREAM 40E06AD80B>

CL-USER 8 : 1 > (write-line "baz")
"baz"

CL-USER 9 : 1 > :c 1
"foo
baz
bar
"

上面是您在LispWorks或SBCL中看到的内容。在这里,您可以访问真实程序的绑定,但是在调试过程中使用输出函数将对此流产生影响。

在其他实现中,*standard-output*将反弹到实际终端io-例如在Clozure CL和CLISP中。

如果您的程序没有重新绑定*standard-output*,那么在这些情况下,混乱就更少了如果我编写代码,我经常会想到在REPL环境中更有用的方法-与语言不同,后者在REPL和中断循环上的交互调试较少...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

传递参数时的显式转换

来自分类Dev

C直接/显式传递参数

来自分类Dev

传递显式空参数包

来自分类Dev

通过引用传递参数时,模板的显式实例化

来自分类Dev

如何返回我显式传递为参数的类型?

来自分类Dev

显式null参数

来自分类Dev

显式类型参数

来自分类Dev

显式类型参数

来自分类Dev

为什么隐式参数在进行隐式转换时不能显式传递?

来自分类Dev

值之间的显式范围

来自分类Dev

Scala:隐式传递一个隐式参数,显式传递另一个。是否可以?

来自分类Dev

显式传递模板参数时,函数模板参数会丢失const吗?

来自分类Dev

显式类型参数多余?

来自分类Dev

通过使用显式构造函数将相同的参数传递给每个元素来构造元组

来自分类Dev

为什么参数不能在pyplot中显式传递为x和y?

来自分类Dev

反向Pinvoke:传递数组长度而没有用于大小的显式函数参数

来自分类Dev

不使用显式范围的数组公式

来自分类Dev

如何使用显式意图传递URI?

来自分类Dev

如何使用显式意图传递URI?

来自分类Dev

Python使用隐式参数代替显式参数

来自分类Dev

显式类型参数Kotlin和RxJava

来自分类Dev

重载解析和显式模板参数

来自分类Dev

显式void指针作为函数参数

来自分类Dev

pytest:参数化测试与显式测试

来自分类Dev

显式输入解构函数参数

来自分类Dev

基于参数的显式返回类型

来自分类Dev

发送显式 CURSOR 作为过程参数

来自分类Dev

Spring MVC:将模型作为参数传递给控制器方法VS显式实例化它

来自分类Dev

如果未修改,PHP是否会优化未通过引用显式传递的数组类型的函数参数?