racket/collects/scribblings/guide/begin.scrbl
Eli Barzilay 264af9a6d0 improved scribble syntax use
svn: r8720
2008-02-19 12:22:45 +00:00

137 lines
4.1 KiB
Racket

#lang scribble/doc
@(require scribble/manual
scribble/eval
"guide-utils.ss")
@title[#:tag "begin"]{Sequencing}
Scheme programmers prefer to write programs with as few side-effects
as possible, since purely functional code is more easily tested and
composed into larger programs. Interaction with the external
environment, however, requires sequencing, such as when writing to a
display, opening a graphical window, or manipulating a file on disk.
@;------------------------------------------------------------------------
@section{Effects Before: @scheme[begin]}
@refalso["begin"]{@scheme[begin]}
A @scheme[begin] expression sequences expressions:
@specform[(begin expr ...+)]{}
The @scheme[_expr]s are evaluated in order, and the result of all but
the last @scheme[_expr] is ignored. The result from the last
@scheme[_expr] is the result of the @scheme[begin] form, and it is in
tail position with respect to the @scheme[begin] form.
@defexamples[
(define (print-triangle height)
(if (zero? height)
(void)
(begin
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height)))))
(print-triangle 4)
]
Many forms, such as @scheme[lambda] or @scheme[cond] support a
sequence of expressions even without a @scheme[begin]. Such positions are
sometimes said to have an @defterm{implicit begin}.
@defexamples[
(define (print-triangle height)
(cond
[(not (positive? height))
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height))]))
(print-triangle 4)
]
The @scheme[begin] form is special at the top level, at module level,
or as a @scheme[body] after only internal definitions. In those
positions, instead of forming an expression, the content of
@scheme[begin] is spliced into the surrounding context.
@defexamples[
(let ([curly 0])
(begin
(define moe (+ 1 curly))
(define larry (+ 1 moe)))
(list larry curly moe))
]
This splicing behavior is mainly useful for macros, as we discuss
later in @secref["macros"].
@;------------------------------------------------------------------------
@section{Effects After: @scheme[begin0]}
@refalso["begin"]{@scheme[begin0]}
A @scheme[begin0] expression has the same syntax as a @scheme[begin]
expression:
@specform[(begin0 expr ...+)]{}
The difference is that @scheme[begin0] returns the result of the first
@scheme[expr], instead of the result of the last @scheme[expr]. The
@scheme[begin0] form is useful for implementing side-effects that
happen after a computation, especially in the case where the
computation produces an unknown number of results.
@defexamples[
(define (log-times thunk)
(printf "Start: ~s\n" (current-inexact-milliseconds))
(begin0
(thunk)
(printf "End..: ~s\n" (current-inexact-milliseconds))))
(log-times (lambda () (sleep 0.1) 0))
(log-times (lambda () (values 1 2)))
]
@;------------------------------------------------------------------------
@section[#:tag "when+unless"]{Effects If...: @scheme[when] and @scheme[unless]}
@refalso["when+unless"]{@scheme[when] and @scheme[unless]}
The @scheme[when] form combines an @scheme[if]-style conditional with
sequencing for the ``then'' clause and no ``else'' clause:
@specform[(when test-expr then-expr ...)]
If @scheme[_test-expr] produces a true value, then all of the
@scheme[_then-expr]s are evaluated. Otherwise, no @scheme[_then-expr]s
are evaluated. The result is @|void-const| in any case.
The @scheme[unless] form is similar:
@specform[(unless test-expr then-expr ...)]
The difference is that the @scheme[_test-expr] result is inverted: the
@scheme[_then-expr]s are evaluated only if the @scheme[_test-expr]
result is @scheme[#f].
@defexamples[
(define (enumerate lst)
(if (null? (cdr lst))
(printf "~a.\n" (car lst))
(begin
(printf "~a, " (car lst))
(when (null? (cdr (cdr lst)))
(printf "and "))
(enumerate (cdr lst)))))
(enumerate '("Larry" "Curly" "Moe"))
]
@def+int[
(define (print-triangle height)
(unless (zero? height)
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height))))
(print-triangle 4)
]