球拍开始形式

时间:2015-04-01 04:13:31

标签: scheme racket

(define mystery2 
  (lambda (L)
    (if (null? L)
        L
        (begin
          (displayln L)
          (append (mystery2 (cdr L))
                  (list (car L)))))))

我按(mystery2 '((1 2) (3 4) 5 6))

运行它

在这里,我不确定“开始”功能是做什么的。

另外,当我写“displayln L”时,它只给我们((1 2) (3 4) 5 6))它不应该打印出递减值,因为它是一个递归吗?

请帮助我理解为什么在这里使用“开始”并且displayln就是这样的。

代码本身没有问题。

3 个答案:

答案 0 :(得分:2)

首先,让我回答你的问题:

begin表单(它不是函数)只是计算它的子表达式,并返回最后一个表达式的值。

因此,如果您评估(begin 3 4 5),它只会返回5。如果您评估(begin (+ 3 4) (+ 9 1)),则会获得10

所以......你可能会有理由问为什么这会有用。答案是一些表达会导致所谓的“副作用”。 displayln就是其中之一;它会导致显示一个值。

但是,让我们退后一步。这里的秘诀就是:尝试一下! Racket是一种非常友好的实验语言;几乎所有的值都有直接“可写”的形式,你可以拉出小的表达式并对它们进行评估,看看它们产生了什么。

随意提出后续问题!

答案 1 :(得分:2)

使用begin表单是因为if仅允许每个分支中有1个表达式。

更直观的示例可能是调试。假设你正在编写困难的代码,并且想要查看哪个分支被执行。

原始代码:

(if (true? some-value)
    (dostuff)
    (dostuff2))

但是您不确定哪个分支正在执行,因此您可能希望在执行任一分支时打印消息。但由于Scheme只允许在每个分支中使用单个表达式,因此不能将它们放在那里。您必须在一个表达式中将它们粘合在一起,并使用begin

(if (true? some-value)
    (begin
      (display "some-value was true")
      (dostuff))
    (begin 
      (display "some-value was false")
      (dostuff2)))

Begin接受任意数量的表达式并执行它们中的每一个,但只返回正文中最后一个表达式的结果。

答案 2 :(得分:0)

begin将多个表达式包装到block中。使用cond代替if的原因之一是结果会自动包含在一个块中。

(define mystery2 
  (lambda (L)
    (cond [(null? L)
           L] 
          [else
            (displayln L)
            (append (mystery2 (cdr L))
                    (list (car L)))])))