11

我正在编写一个方案解释器,如果是 if 语句,例如:

(if (< 1 0) 'true)

我尝试过的任何解释器都会返回一个新的提示。但是当我编写这个代码时,我有一个 if 是否有替代表达式。如果没有打印任何内容,我可以返回什么?

(if (has-alternative if-expr)
  (eval (alternative if-expr))
  #f) ;; what do I return here?
4

7 回答 7

12

根据R6RS 规范

如果 <test> 产生 #f 并且没有指定 <alternate>,则表达式的结果是未指定的。

所以去狂野吧,返回任何你想要的东西!虽然#f 或'() 是我个人所期望的。

于 2009-03-20T06:30:29.650 回答
8

Scheme 确实可以不返回任何值:

   > (values)

在 R5RS 中,if 的单臂形式被指定为返回一个未指定的值。这意味着由您决定返回哪个值。相当多的方案选择引入称为“未指定值”的特定值并返回该值。其他人返回“不可见的值” #<void> 并且 REPL 被写入以便它不打印它。

   > (void)

一开始可能会认为,这与 (values) 相同,但请注意区别:

  > (length (list (void)))
  1

  > (length (list (values)))
  error>  context expected 1 value, received 0 values
  (Here (list ...) expected 1 value, but received nothing)

如果 #<void> 是列表的一部分,则打印:

  > (list (void))
  (#<void>)
于 2009-03-20T09:56:57.110 回答
2

许多方案(PLT、Ikarus、Chicken)都有一个 void 类型,您可以使用 (void) 生成它。

至少在 PLT 中,void 是你做的时候得到的(当 (< 1 0) #t 时)。

(PLT v4 不允许 if 没有 else 子句。)

于 2009-03-20T03:01:18.950 回答
2

当返回值未指定时,你可以返回你喜欢的;用户不能依赖该值存在、永远存在或跨实现。

于 2009-03-27T18:38:43.227 回答
1

首先,可以要求 if 有一个 else 子句,如果它让你更容易。其次,Scheme 支持从函数返回多个值,因此如果要将返回值实现为列表,则可以有一个空列表表示没有给出返回值。

(if (has-alternative if-expr)
  (eval (alternative if-expr)) ; make sure eval returns a list
  '())

这里有一个重要的区别:如果没有 else 子句,我不会返回一个空列表。空列表表示没有返回值。如果一个表达式有一个返回值(比如说它是 3),那么您将有 (3) 作为幕后 eval 的返回值。同样,从表达式返回多个值会导致 eval 返回列表具有多个元素。

最后,实际上,如果条件失败并且没有其他条件,您实际上可以返回任何内容,因为在程序中尝试捕获不返回任何内容的函数的值将是错误的。因此,捕获此错误将是程序员而不是语言的工作。

于 2009-03-19T23:04:53.807 回答
1

奇怪的人会返回'nil'||(空符号)。问题是返回一个不能返回的符号(eval (alternative if-expr))以避免混淆。

如果可以返回任何内容,(eval (alternative if-expr))并且您仍然想知道您是否选择了此替代方案,则必须在结果中包含更多信息:

(if (has-alternative if-expr)
  (cons #t (eval (alternative if-expr)))
  (cons #f #f))

因此,结果是一个 cons 单元格。如果它的车是#t,那么你评估了一些东西。如果它是#f,你没有。

于 2009-04-06T12:32:24.203 回答
0

只是有什么问题:

(if (has-alternative if-expr) (eval (alternative if-expr)))

?

于 2009-03-19T23:58:16.533 回答