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

and I run it by (mystery2 '((1 2) (3 4) 5 6))

Here, I am not sure what "begin" function does.

Also, when I write "displayln L" it only gives us ((1 2) (3 4) 5 6)). Shouldn't it print out decreasing values since it is a recursion?

Please, help me understand why "begin" is used here and displayln works like that.

There is no problem in the code itself.

3
Notice it calls mystery and not itself so we can't say it's recursive. It may be mutual recursive but mystery needs to call mystery2. - Sylwester

3 Answers

5
votes

The begin form is used because an if only allows for 1 expression in each branch.

A more intuitive example might be debugging. Suppose you are writing difficult code and you want to see which branch gets executed.

Original code:

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

But you are not sure which branch is getting executed so you might want to print a message whenever either branch is executed. But since Scheme only allows a single expression in each branch you can not just put them in there. You have to glue them together in a single expression, with a begin.

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

Begin takes an arbitrary number of expressions and executes each one of them but only returns the result of the last expression in the body.

3
votes

First, let me answer your question:

The begin form (it's not a function) just evaluates its subexpressions, and returns the value of the last one.

So, if you evaluate (begin 3 4 5), it will just return 5. If you evaluate (begin (+ 3 4) (+ 9 1)), you will get 10.

So... you might plausibly ask why this would be useful. The answer is that some expressions cause what are called "side effects". displayln is one of these; it causes a value to be displayed.

Let's take a step back, though. The secret sauce here is this: try things out! Racket is a language that is very friendly to experimentation; nearly all values have directly "writable" forms, and you can pull small expressions out and evaluate them to see what they produce.

Feel free to ask followup questions!

0
votes

begin wraps several expressions into a block. One of the reasons to use cond instead of if is that the consequent is automatically wrapped in a block.

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