2015-04-01 74 views
1
(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

注意它叫“神秘”而不是它本身,所以我们不能说它是递归的。它可能是相互递归的,但“神秘”需要调用“mystery2”。 – Sylwester 2015-04-01 06:35:36

回答

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需要任意数量的表达式并执行它们中的每一个,但只返回正文中最后一个表达式的结果。

+0

感谢您的回复!然后我想知道在“displayln”中,它只打印出一个列表。它不应该打印出更多?既然是递归,我认为它应该多次调用“displayln”,这意味着多个显示? – harumomo503 2015-04-01 16:34:40

+0

如果'神秘'呼叫'神秘',当然。但是我们看不到“神秘”功能的代码。 – 2015-04-01 17:07:05

+0

对......!谢谢! – harumomo503 2015-04-01 21:50:13

2

首先,我回答你的问题:

begin形式(它不是一个函数)只评估其子表达式,并返回最后一个的值。

因此,如果您评估(begin 3 4 5),它将仅返回5。如果你评估(begin (+ 3 4) (+ 9 1)),你会得到10

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

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

随意问后续问题!

+0

哦。那么'开始'形式用于评估子表达式,但也有助于避免副作用,如'displayln'?球拍中的“副作用”意味着什么? – harumomo503 2015-04-01 04:44:41

+0

@HAruMOmo没有副作用,唯一的结果是返回的值,它只是基于参数。例如。如果你读,写,存储或检索的东西是副作用。在你的例子'displayln'中可能有打印某物到终端的副作用。 – Sylwester 2015-04-01 09:11:50

+0

谢谢你的回应! – harumomo503 2015-04-01 21:50:35

0

begin将几个表达式换成block。使用cond而不是if的原因之一是,结果会自动包装在一个块中。

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