Scheme中“ when”的用途是什么?

时间:2019-06-02 17:50:24

标签: scheme

我正在尝试在Scheme中使用,但是我不知道为什么列表的最后一个元素出现。#void>。

这是我的代码

(define (genlist x y)
   (when
       (< x y)
       (cons x (genlist (+ x 1) y))))

这是我的输出=>

(2 3 4 5 6 7 8 9 . #void>)

3 个答案:

答案 0 :(得分:2)

您需要使用(if (< x y) (cons ...) '())来生成适当的列表。

when(与之相对应的unless)主要用于在不使用结果的情况下产生副作用(例如打印出一些东西)。

例如(when debug-mode? (print "got here"))

答案 1 :(得分:2)

when是一个带有隐含begin的ifs。以下示例相同:

(if (any odd? lst)
    (begin
      (set! some-binding #t)
      (display "Found an odd element")))


(when (any odd? lst)
  (set! some-binding #t)
  (display "Found an odd element"))

您可以在谓词中使用unless而不是not

(if (not (any odd? lst))
    (set! some-binding #f))

(unless (any odd? lst)
  (set! some-binding #f))

彼得·诺维格(Peter Norvig)写了一本关于Lisp style的好书,他在书中谈到了这一点:

请确保您的数据抽象所要求的具体程度,但仅此而已。

  • 如果用于两分支表达式
  • 何时,除非单行声明
  • 和,或仅用于布尔值
  • 继续使用多分支语句或表达式

因此,尽管您可以使用if编写所有逻辑,但这并不是最容易阅读的代码。其他人可能会使用术语principle of least surprise。即使这本书是针对Common Lisp的,也可以在Scheme中使用其中的大部分内容。如果您想对任何Lisp方言进行编程,这是一本好书。

对于whenunless而言,这对Scheme更好,因为您不知道在谓词为#f的情况下,如果在CL中谓词求值,则可能返回什么实现。 when,因为在这种情况下注定要返回nil

在您的代码中,您试图返回某些内容,让实现选择在谓词失败时应该发生的情况,这是导致#<void>的原因。当退货时,您应该始终使用两副武装的if

(if test-expression
    then-expression
    else-expression)

请注意,没有else关键字。

答案 2 :(得分:1)

当我们需要编写不包含when部分的if时,和/或需要在else中编写多个表达式时,我们使用if。仅返回最后一个表达式的值,因此我们主要将其用于副作用。为了更好地理解它,在球拍中这样:

(when <condition>
  <exp1>
  <exp2>
  <exp3>)

等效于此:

(if <condition>
    (begin
      <exp1>
      <exp2>
      <exp3>)
    (void)) ; implementation-dependent

除了条件用unless包围之外,(not ...)的注意事项也相同。

问题的根源(以及没有if的{​​{1}}是代码味道的原因)是您的代码无法处理else时的情况。问问自己,在这种情况下您应该怎么做?简单,返回一个空列表!这是代码中缺少递归的基本情况。