(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就是这样的。
代码本身没有问题。
答案 0 :(得分:2)
首先,让我回答你的问题:
begin
表单(它不是函数)只是计算它的子表达式,并返回最后一个表达式的值。
因此,如果您评估(begin 3 4 5)
,它只会返回5
。如果您评估(begin (+ 3 4) (+ 9 1))
,则会获得10
。
所以......你可能会有理由问为什么这会有用。答案是一些表达会导致所谓的“副作用”。 displayln
就是其中之一;它会导致显示一个值。
随意提出后续问题!
答案 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)))])))