#lang scribble/doc @(require "common.ss" "std-grammar.ss" "prim-ops.ss" (for-label lang/htdp-intermediate)) @(define-syntax-rule (bd beg-define beg-define-struct beg-cond beg-if beg-and beg-or beg-check-expect beg-require) (begin (require (for-label lang/htdp-beginner)) (define beg-define (scheme define)) (define beg-define-struct (scheme define-struct)) (define beg-cond (scheme cond)) (define beg-if (scheme if)) (define beg-and (scheme and)) (define beg-or (scheme or)) (define beg-check-expect (scheme check-expect)) (define beg-require (scheme require)))) @(bd beg-define beg-define-struct beg-cond beg-if beg-and beg-or beg-check-expect beg-require) @title[#:style 'toc #:tag "intermediate"]{Intermediate Student} @declare-exporting[lang/htdp-intermediate] @schemegrammar*+qq[ #:literals (define define-struct lambda cond else if and or empty true false require lib planet local let let* letrec time check-expect check-within check-error) [program (code:line def-or-expr ...)] [def-or-expr definition expr library-require] [definition (define (id id id ...) expr) (define id expr) (define id (lambda (id id ...) expr)) (define-struct id (id ...))] [expr (local [definition ...] expr) (letrec ([id expr-for-let] ...) expr) (let ([id expr-for-let] ...) expr) (let* ([id expr-for-let] ...) expr) (code:line (id expr expr ...) (code:comment #, @seclink["intermediate-call"]{function call})) (code:line (prim-op expr ...) (code:comment #, @seclink["beginner-prim-call"]{primitive operation call})) (cond [expr expr] ... [expr expr]) (cond [expr expr] ... [else expr]) (if expr expr expr) (and expr expr expr ...) (or expr expr expr ...) (time expr) test-case empty (code:line id (code:comment #, @seclink["intermediate-id"]{identifier})) (code:line prim-op (code:comment #, @seclink["intermediate-prim-op"]{primitive operation})) 'id (code:line #, @elem{@schemevalfont{'}@scheme[quoted]} (code:comment #, @seclink["beginner-abbr-quote"]{quoted value})) (code:line #, @elem{@schemevalfont{`}@scheme[quasiquoted]} (code:comment #, @seclink["beginner-abbr-quasiquote"]{quasiquote})) number true false string character] [expr-for-let (lambda (id id ...) expr) expr] ] @|prim-nonterms| @prim-ops['(lib "htdp-intermediate.ss" "lang") #'here] @; ---------------------------------------------------------------------- @section[#:tag "intermediate-define"]{@scheme[define]} @deftogether[( @defform[(define (id id id ...) expr)] @defform/none[#:literals (define) (define id expr)] @defform/none[#:literals (define lambda) (define id (lambda (id id ...) expr))] )]{ Besides working in @scheme[local], definition forms are the same as Beginning's @|beg-define|.} @defidform[lambda]{ As in Beginning, @scheme[lambda] keyword can only be used with @scheme[define] in the alternative function-definition syntax.} @; ---------------------------------------------------------------------- @section[#:tag "intermediate-define-struct"]{@scheme[define-struct]} @defform[(define-struct structid (fieldid ...))]{ Besides working in @scheme[local], this form is the same as Beginning's @|beg-define-struct|.} @; ---------------------------------------------------------------------- @section{@scheme[local]} @defform[(local [definition ...] expr)]{ Groups related definitions for use in @scheme[expr]. Each @scheme[definition] is evaluated in order, and finally the body @scheme[expr] is evaluated. Only the expressions within the @scheme[local] form (including the right-hand-sides of the @scheme[definition]s and the @scheme[expr]) may refer to the names defined by the @scheme[definition]s. If a name defined in the @scheme[local] form is the same as a top-level binding, the inner one ``shadows'' the outer one. That is, inside the @scheme[local] form, any references to that name refer to the inner one. Since @scheme[local] is an expression and may occur anywhere an expression may occur, it introduces the notion of lexical scope. Expressions within the local may ``escape'' the scope of the local, but these expressions may still refer to the bindings established by the local.} @; ---------------------------------------------------------------------- @section{@scheme[letrec], @scheme[let], and @scheme[let*]} @defform[(letrec ([id expr-for-let] ...) expr)]{ Similar to @scheme[local], but essentially omitting the @scheme[define] for each definition. A @scheme[expr-for-let] can be either an expression for a constant definition or a @scheme[lambda] form for a function definition.} @defform[(let ([id expr-for-let] ...) expr)]{ Like @scheme[letrec], but the defined @scheme[id]s can be used only in the last @scheme[expr], not the @scheme[expr-for-let]s next to the @scheme[id]s.} @defform[(let* ([id expr-for-let] ...) expr)]{ Like @scheme[let], but each @scheme[id] can be used in any subsequent @scheme[expr-for-let], in addition to @scheme[expr].} @; ---------------------------------------------------------------------- @section[#:tag "intermediate-call"]{Function Calls} @defform/none[(id expr expr ...)]{ A function call in Intermediate is the same as a Beginning @seclink["beginner-call"]{function call}, except that it can also call @scheme[local]ly defined functions or functions passed as arguments. That is, @scheme[id] can be a function defined in @scheme[local] or an argument name while in a function.} @defform[(#%app id expr expr ...)]{ A function call can be written with @scheme[#%app], though it's practically never written that way.} @; ---------------------------------------------------------------------- @section{@scheme[time]} @defform[(time expr)]{ This form is used to measure the time taken to evaluate @scheme[expr]. After evaluating @scheme[expr], Scheme prints out the time taken by the evaluation (including real time, time taken by the cpu, and the time spent collecting free memory) and returns the result of the expression.} @; ---------------------------------------------------------------------- @section[#:tag "intermediate-id"]{Identifiers} @defform/none[id]{ An @scheme[id] refers to a defined constant (possibly local), defined function (possibly local), or argument within a function body. If no definition or argument matches the @scheme[id] name, an error is reported.} @; ---------------------------------------------------------------------- @section[#:tag "intermediate-prim-op"]{Primitive Operations} @defform/none[prim-op]{ The name of a primitive operation can be used as an expression. If it is passed to a function, then it can be used in a function call within the function's body.} @prim-op-defns['(lib "htdp-intermediate.ss" "lang") #'here '()] @; ---------------------------------------------------------------------- @section[#:tag "intermediate-unchanged"]{Unchanged Forms} @deftogether[( @defform[(cond [expr expr] ... [expr expr])] @defidform[else] )]{ The same as Beginning's @|beg-cond|.} @defform[(if expr expr expr)]{ The same as Beginning's @|beg-if|.} @deftogether[( @defform[(and expr expr expr ...)] @defform[(or expr expr expr ...)] )]{ The same as Beginning's @|beg-and| and @|beg-or|.} @deftogether[( @defform[(check-expect expr expr)] @defform[(check-within expr expr expr)] @defform[(check-error expr expr)] )]{ The same as Beginning's @|beg-check-expect|, etc.} @deftogether[( @defthing[empty empty?] @defthing[true boolean?] @defthing[false boolean?] )]{ Constants for the empty list, true, and false.} @defform[(require string)]{ The same as Beginning's @|beg-require|.}