diff --git a/collects/lang/htdp-advanced.ss b/collects/lang/htdp-advanced.ss index aa3c15e761..b030ab2f3f 100644 --- a/collects/lang/htdp-advanced.ss +++ b/collects/lang/htdp-advanced.ss @@ -60,64 +60,4 @@ (all-from-except intermediate: lang/htdp-intermediate-lambda procedures cons list* append) - - ("Reading and Printing" - (print (any -> void) - "to print the argument as a value to stdout") - (display (any -> void) - "to print the argument to stdout (without quotes on symbols and strings, etc.)") - (write (any -> void) - "to print the argument to stdout (in a traditional style that is somewhere between print and display)") - (pretty-print (any -> void) - "like write, but with standard newlines and indentation") - (printf (string any ... -> void) - "to format the rest of the arguments according to the first argument and print it to stdout") - (newline (-> void) - "to print a newline to stdout") - (read (-> sexp) "to read input from the user")) - - ("Lists" - (list? (any -> boolean) - "to determine whether some value is a list") - - ((advanced-cons cons) (X (listof X) -> (listof X)) - "to construct a list") - - ((advanced-append append) ((listof any) ... -> (listof any)) - "to create a single list from several")) - - ("Misc" - (force (delay -> any) "to find the delayed value; see also delay") - (promise? (any -> boolean) "to determine if a value is delayed") - (void (-> void) "produces a void value") - (void? (any -> boolean) "to determine if a value is void")) - - ("Posns" - (set-posn-x! (posn number -> void) "to update the x component of a posn") - (set-posn-y! (posn number -> void) "to update the x component of a posn")) - - ("Vectors" - (vector (X ... -> (vector X ...)) - "to construct a vector") - (make-vector (number X -> (vectorof X)) - "to construct a vector") - (build-vector (nat (nat -> X) -> (vectorof X)) - "to construct a vector") - (vector-ref ((vector X) nat -> X) - "to extract an element from a vector") - (vector-length ((vector X) -> nat) - "to determine the length of a vector") - (vector-set! ((vectorof X) nat X -> void) - "to update a vector") - (vector? (any -> boolean) - "to determine if a value is a vector")) - - ("Boxes" - (box (any -> box) - "to construct a box") - (unbox (box -> any) - "to extract the boxed value") - (set-box! (box any -> void) - "to update a box") - (box? (any -> boolean) - "to determine if a value is a box")))) + (all-from advanced: lang/private/advanced-funs procedures))) diff --git a/collects/lang/htdp-intermediate-lambda.ss b/collects/lang/htdp-intermediate-lambda.ss index 18476d4b65..5d80ca9202 100644 --- a/collects/lang/htdp-intermediate-lambda.ss +++ b/collects/lang/htdp-intermediate-lambda.ss @@ -8,7 +8,7 @@ ;; syntax: (provide (rename-out - [intermediate-define define] + [intermediate-lambda-define define] [intermediate-define-struct define-struct] [intermediate-lambda lambda] [advanced-app #%app] diff --git a/collects/lang/htdp-intermediate.ss b/collects/lang/htdp-intermediate.ss index 8abae6622c..0f3c00ab59 100644 --- a/collects/lang/htdp-intermediate.ss +++ b/collects/lang/htdp-intermediate.ss @@ -11,7 +11,7 @@ (provide (rename-out [intermediate-define define] [intermediate-define-struct define-struct] - [beginner-lambda lambda] + [intermediate-pre-lambda lambda] [intermediate-app #%app] [beginner-top #%top] [intermediate-local local] @@ -46,35 +46,4 @@ ;; procedures: (provide-and-document procedures - (all-from beginner: lang/private/beginner-funs procedures) - - ("Higher-Order Functions" - (map ((X ... -> Z) (listof X) ... -> (listof Z)) - "to construct a new list by applying a function to each item on one or more existing lists") - (for-each ((any ... -> any) (listof any) ... -> void) - "to apply a function to each item on one or more lists for effect only") - (filter ((X -> boolean) (listof X) -> (listof X)) - "to construct a list from all those items on a list for which the predicate holds") - ((intermediate-foldr foldr) ((X Y -> Y) Y (listof X) -> Y) - "(foldr f base (list x-1 ... x-n)) = (f x-1 ... (f x-n base))") - ((intermediate-foldl foldl) ((X Y -> Y) Y (listof X) -> Y) - "(foldl f base (list x-1 ... x-n)) = (f x-n ... (f x-1 base))") - (build-list (nat (nat -> X) -> (listof X)) - "(build-list n f) = (list (f 0) ... (f (- n 1)))") - ((intermediate-build-string build-string) (nat (nat -> char) -> string) - "(build-string n f) = (string (f 0) ... (f (- n 1)))") - ((intermediate-quicksort quicksort) ((listof X) (X X -> boolean) -> (listof X)) - "to construct a list from all items on a list in an order according to a predicate") - (andmap ((X -> boolean) (listof X) -> boolean) - "(andmap p (list x-1 ... x-n)) = (and (p x-1) (and ... (p x-n)))") - (ormap ((X -> boolean) (listof X) -> boolean) - "(ormap p (list x-1 ... x-n)) = (or (p x-1) (or ... (p x-n)))") - - (memf ((X -> boolean) (listof X) -> (union false (listof X))) - "to determine whether the first argument produces true for some value in the second argument") - (apply ((X-1 ... X-N -> Y) X-1 ... X-i (list X-i+1 ... X-N) -> Y) - "to apply a function using items from a list as the arguments") - (compose ((Y-1 -> Z) ... (Y-N -> Y-N-1) (X-1 ... X-N -> Y-N) -> (X-1 ... X-N -> Z)) - "to compose a sequence of procedures into a single procedure") - (procedure? (any -> boolean) - "to determine if a value is a procedure")))) + (all-from beginner: lang/private/intermediate-funs procedures))) diff --git a/collects/lang/private/advanced-funs.ss b/collects/lang/private/advanced-funs.ss new file mode 100644 index 0000000000..fda99c5d42 --- /dev/null +++ b/collects/lang/private/advanced-funs.ss @@ -0,0 +1,79 @@ +(module advanced-funs scheme/base + (require "teachprims.ss" + mzlib/etc + mzlib/list + mzlib/pretty + syntax/docprovide + scheme/promise + "../posn.ss" + (for-syntax scheme/base)) + + (define-syntax (freshen-export stx) + (syntax-case stx () + [(_ new-name orig-name) + #'(define-syntax new-name (make-rename-transformer #'orig-name))])) + + (provide-and-document/wrap + procedures + freshen-export + + ("Reading and Printing" + (print (any -> void) + "to print the argument as a value to stdout") + (display (any -> void) + "to print the argument to stdout (without quotes on symbols and strings, etc.)") + (write (any -> void) + "to print the argument to stdout (in a traditional style that is somewhere between print and display)") + (pretty-print (any -> void) + "like write, but with standard newlines and indentation") + (printf (string any ... -> void) + "to format the rest of the arguments according to the first argument and print it to stdout") + (newline (-> void) + "to print a newline to stdout") + (read (-> sexp) "to read input from the user")) + + ("Lists" + (list? (any -> boolean) + "to determine whether some value is a list") + + ((advanced-cons cons) (X (listof X) -> (listof X)) + "to construct a list") + + ((advanced-append append) ((listof any) ... -> (listof any)) + "to create a single list from several")) + + ("Misc" + (force (delay -> any) "to find the delayed value; see also delay") + (promise? (any -> boolean) "to determine if a value is delayed") + (void (-> void) "produces a void value") + (void? (any -> boolean) "to determine if a value is void")) + + ("Posns" + (set-posn-x! (posn number -> void) "to update the x component of a posn") + (set-posn-y! (posn number -> void) "to update the x component of a posn")) + + ("Vectors" + (vector (X ... -> (vector X ...)) + "to construct a vector") + (make-vector (number X -> (vectorof X)) + "to construct a vector") + (build-vector (nat (nat -> X) -> (vectorof X)) + "to construct a vector") + (vector-ref ((vector X) nat -> X) + "to extract an element from a vector") + (vector-length ((vector X) -> nat) + "to determine the length of a vector") + (vector-set! ((vectorof X) nat X -> void) + "to update a vector") + (vector? (any -> boolean) + "to determine if a value is a vector")) + + ("Boxes" + (box (any -> box) + "to construct a box") + (unbox (box -> any) + "to extract the boxed value") + (set-box! (box any -> void) + "to update a box") + (box? (any -> boolean) + "to determine if a value is a box")))) diff --git a/collects/lang/private/beginner-funs.ss b/collects/lang/private/beginner-funs.ss index 43f66e7e8e..762de76abd 100644 --- a/collects/lang/private/beginner-funs.ss +++ b/collects/lang/private/beginner-funs.ss @@ -273,9 +273,6 @@ (list (any ... -> (listof any)) "to construct a list of its arguments") - (list (any ... (listof any) -> (listof any)) - "to construct a list of its arguments, building on the last argument") - ((beginner-list* list*) (any ... (listof any) -> (listof any)) "to construct a list by adding multiple items to a list") diff --git a/collects/lang/private/intermediate-funs.ss b/collects/lang/private/intermediate-funs.ss new file mode 100644 index 0000000000..58df768bf8 --- /dev/null +++ b/collects/lang/private/intermediate-funs.ss @@ -0,0 +1,47 @@ +(module intermediate-funs scheme/base + (require "teachprims.ss" + mzlib/etc + mzlib/list + syntax/docprovide + (for-syntax scheme/base)) + + (define-syntax (freshen-export stx) + (syntax-case stx () + [(_ new-name orig-name) + #'(define-syntax new-name (make-rename-transformer #'orig-name))])) + + (provide-and-document/wrap + procedures + freshen-export + (all-from beginner: lang/private/beginner-funs procedures) + + ("Higher-Order Functions" + (map ((X ... -> Z) (listof X) ... -> (listof Z)) + "to construct a new list by applying a function to each item on one or more existing lists") + (for-each ((any ... -> any) (listof any) ... -> void) + "to apply a function to each item on one or more lists for effect only") + (filter ((X -> boolean) (listof X) -> (listof X)) + "to construct a list from all those items on a list for which the predicate holds") + ((intermediate-foldr foldr) ((X Y -> Y) Y (listof X) -> Y) + "(foldr f base (list x-1 ... x-n)) = (f x-1 ... (f x-n base))") + ((intermediate-foldl foldl) ((X Y -> Y) Y (listof X) -> Y) + "(foldl f base (list x-1 ... x-n)) = (f x-n ... (f x-1 base))") + (build-list (nat (nat -> X) -> (listof X)) + "(build-list n f) = (list (f 0) ... (f (- n 1)))") + ((intermediate-build-string build-string) (nat (nat -> char) -> string) + "(build-string n f) = (string (f 0) ... (f (- n 1)))") + ((intermediate-quicksort quicksort) ((listof X) (X X -> boolean) -> (listof X)) + "to construct a list from all items on a list in an order according to a predicate") + (andmap ((X -> boolean) (listof X) -> boolean) + "(andmap p (list x-1 ... x-n)) = (and (p x-1) (and ... (p x-n)))") + (ormap ((X -> boolean) (listof X) -> boolean) + "(ormap p (list x-1 ... x-n)) = (or (p x-1) (or ... (p x-n)))") + + (memf ((X -> boolean) (listof X) -> (union false (listof X))) + "to determine whether the first argument produces true for some value in the second argument") + (apply ((X-1 ... X-N -> Y) X-1 ... X-i (list X-i+1 ... X-N) -> Y) + "to apply a function using items from a list as the arguments") + (compose ((Y-1 -> Z) ... (Y-N -> Y-N-1) (X-1 ... X-N -> Y-N) -> (X-1 ... X-N -> Z)) + "to compose a sequence of procedures into a single procedure") + (procedure? (any -> boolean) + "to determine if a value is a procedure")))) \ No newline at end of file diff --git a/collects/lang/private/teach.ss b/collects/lang/private/teach.ss index 9526acc629..d8345684f3 100644 --- a/collects/lang/private/teach.ss +++ b/collects/lang/private/teach.ss @@ -143,12 +143,12 @@ intermediate-define intermediate-define-struct + intermediate-pre-lambda intermediate-local intermediate-letrec intermediate-let intermediate-let* intermediate-recur - intermediate-lambda intermediate-app intermediate-quote intermediate-quasiquote @@ -156,6 +156,9 @@ intermediate-unquote-splicing intermediate-time + intermediate-lambda-define + intermediate-lambda + advanced-define advanced-lambda advanced-app @@ -408,7 +411,7 @@ ;; define (beginner) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (define (define/proc first-order? assign? stx) + (define (define/proc first-order? assign? stx lambda-stx) (define (wrap-func-definition name argc k) (wrap-func-definitions first-order? @@ -440,7 +443,8 @@ (identifier/non-kw? (syntax name)) (let ([lam (syntax expr)]) (check-defined-lambda lam) - (syntax-case (syntax expr) (beginner-lambda) + (syntax-case* (syntax expr) (beginner-lambda) (lambda (a b) + (module-identifier=? a lambda-stx)) ;; Well-formed lambda def: [(beginner-lambda arg-seq lexpr ...) (begin @@ -573,10 +577,14 @@ (bad-use-error 'define stx)])) (define (beginner-define/proc stx) - (define/proc #t #f stx)) + (define/proc #t #f stx #'beginner-lambda)) (define (intermediate-define/proc stx) - (define/proc #f #f stx)) + (define/proc #f #f stx #'intermediate-pre-lambda)) + + (define (intermediate-lambda-define/proc stx) + ;; no special treatment of intermediate-lambda: + (define/proc #f #f stx #'beginner-lambda)) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; lambda (beginner; only works with define) @@ -593,10 +601,12 @@ [_else (bad-use-error 'lambda stx)])) + (define (intermediate-pre-lambda/proc stx) + (beginner-lambda/proc stx)) (define (check-defined-lambda lam) - (syntax-case lam (beginner-lambda) - [(beginner-lambda arg-seq lexpr ...) + (syntax-case lam (intermediate-pre-lambda) + [(intermediate-pre-lambda arg-seq lexpr ...) (syntax-case (syntax arg-seq) () [(arg ...) #t][_else #f]) (let ([args (syntax->list (syntax arg-seq))]) (for-each (lambda (arg) @@ -628,7 +638,7 @@ args) 'ok)] ;; Bad lambda because bad args: - [(beginner-lambda args . _) + [(intermediate-pre-lambda args . _) (teach-syntax-error 'lambda lam @@ -636,7 +646,7 @@ "expected a sequence of function arguments after `lambda', but found ~a" (something-else (syntax args)))] ;; Bad lambda, no args: - [(beginner-lambda) + [(intermediate-pre-lambda) (teach-syntax-error 'lambda lam @@ -1507,20 +1517,20 @@ 'comes-from-let*))] [_else (bad-let-form 'let* stx stx)])))) - ;; Helper function: allows `beginner-lambda' instead + ;; Helper function: allows `intermediate-pre-lambda' instead ;; of rejecting it: (define (allow-local-lambda stx) - (syntax-case stx (beginner-lambda) - [(beginner-lambda . rest) + (syntax-case stx (intermediate-pre-lambda) + [(intermediate-pre-lambda . rest) (begin (check-defined-lambda stx) ;; pattern-match again to pull out the formals: (syntax-case stx () [(_ formals . rest) (quasisyntax/loc stx (lambda formals #,(stepper-syntax-property - #`make-lambda-generative - 'stepper-skip-completely - #t) + #`make-lambda-generative + 'stepper-skip-completely + #t) . rest))]))] [_else stx])) diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss index e9c8ae138a..a014bc0927 100644 --- a/collects/scribble/manual.ss +++ b/collects/scribble/manual.ss @@ -222,6 +222,7 @@ (provide schemeblock SCHEMEBLOCK schemeblock/form schemeblock0 SCHEMEBLOCK0 schemeblock0/form + schemeblockelem schemeinput schememod scheme SCHEME scheme/form schemeresult schemeid schememodname @@ -442,7 +443,9 @@ (provide declare-exporting deftogether - defproc defproc* defstruct defthing defthing* defparam defparam* defboolparam + defproc defproc* defstruct + defthing defthing* defthing/proc + defparam defparam* defboolparam defform defform* defform/subs defform*/subs defform/none defidform specform specform/subs @@ -762,6 +765,10 @@ (syntax-rules () [(_ id) (*var 'id)])) + (define (defthing/proc id contract descs) + (*defthing (list id) (list (syntax-e id)) #f (list contract) + (lambda () descs))) + (define (into-blockquote s) (cond [(splice? s) diff --git a/collects/scribblings/htdp-langs/advanced.scrbl b/collects/scribblings/htdp-langs/advanced.scrbl new file mode 100644 index 0000000000..8753c79c82 --- /dev/null +++ b/collects/scribblings/htdp-langs/advanced.scrbl @@ -0,0 +1,263 @@ +#lang scribble/doc +@(require "common.ss" + "std-grammar.ss" + "prim-ops.ss" + (for-label lang/htdp-advanced)) + +@(define-syntax-rule (bd intm-define intm-define-struct intm-lambda intm-let) + (begin + (require (for-label lang/htdp-intermediate-lambda)) + (define intm-define (scheme define)) + (define intm-define-struct (scheme define-struct)) + (define intm-lambda (scheme lambda)) + (define intm-let (scheme let)))) +@(bd intm-define intm-define-struct intm-lambda intm-let) + + +@title[#:style 'toc]{Advanced Student} + +@schemegrammar*+qq[ +#:literals (define define-struct lambda cond else if and or empty true false require lib planet + local let let* letrec time begin begin0 set! delay shared recur when case unless) +[program def-or-expr] +[def-or-expr definition + expr + library-require] +[definition (define (id id id ...) expr) + (define id expr) + (define-struct id (id ...))] +[expr (begin expr expr ...) + (begin0 expr expr ...) + (set! id expr) + (delay expr) + (lambda (id id ...) expr) + (local [definition ...] expr) + (letrec ([id expr] ...) expr) + (shared ([id expr] ...) expr) + (let ([id expr] ...) expr) + (let id ([id expr] ...) expr) + (let* ([id expr] ...) expr) + (recur id ([id expr] ...) expr) + (code:line (expr expr expr ...) (code:comment #, @seclink["intermediate-lambda-call"]{function call})) + (cond [expr expr] ... [expr expr]) + (cond [expr expr] ... [else expr]) + (case expr [(choice choice ...) expr] ... + [(choice choice ...) expr]) + (case expr [(choice choice ...) expr] ... + [else expr]) + (if expr expr expr) + (when expr expr) + (unless expr expr) + (and expr expr expr ...) + (or expr expr expr ...) + (time expr) + empty + (code:line id (code:comment #, @seclink["intermediate-id"]{identifier})) + (code:line prim-op (code:comment #, @seclink["intermediate-lambda-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] +[choice (code:line id (code:comment #, @t{treated as a symbol})) + number] +] + +@|prim-nonterms| + +@prim-ops['(lib "htdp-advanced.ss" "lang") #'here] + +@; ---------------------------------------------------------------------- + +@section[#:tag "advanced-define"]{@scheme[define]} + +@deftogether[( +@defform[(define (id id ...) expr)] +@defform/none[#:literals (define) + (define id expr)] +)]{ + +The same as Intermediate with Lambda's @|intm-define|, except that a +function is allowed to accept zero arguments.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "advanced-define-struct"]{@scheme[define-struct]} + +@defform[(define-struct structid (fieldid ...))]{ + +The same as Intermediate's @|intm-define-struct|, but defines an +additional set of operations: + +@itemize{ + + @item{@schemeidfont{make-}@scheme[structid] : takes a number of + arguments equal to the number of fields in the structure type, + and creates a new instance of the structure type.} + + @item{@schemeidfont{set-}@scheme[structid]@schemeidfont{-}@scheme[fieldid]@schemeidfont{!} + : takes an instance of the structure and a value, and changes + the instance's field to the given value.} + +}} + +@; ---------------------------------------------------------------------- + +@section[#:tag "advanced-lambda"]{@scheme[lambda]} + +@defform[(lambda (id ...) expr)]{ + +The same as Intermediate with Lambda's @|intm-lambda|, except that a +function is allowed to accept zero arguments.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[begin]} + +@defform[(begin expr expr ...)]{ + +Evaluates the @scheme[expr]s in order from left to right. The value of +the @scheme[begin] expression is the value of the last @scheme[expr].} + +@; ---------------------------------------------------------------------- + +@section{@scheme[begin0]} + +@defform[(begin0 expr expr ...)]{ + +Evaluates the @scheme[expr]s in order from left to right. The value of +the @scheme[begin] expression is the value of the first @scheme[expr].} + +@; ---------------------------------------------------------------------- + +@section{@scheme[set!]} + +@defform[(set! id expr)]{ + +Evaluates @scheme[expr], and then changes the definition @scheme[id] +to have @scheme[expr]'s value. The @scheme[id] must be defined or +bound by @scheme[letrec], @scheme[let], or @scheme[let*].} + +@; ---------------------------------------------------------------------- + +@section{@scheme[delay]} + +@defform[(delay expr)]{ + +Produces a ``promise'' to evaluate @scheme[expr]. The @scheme[expr] is +not evaluated until the promise is forced through the @scheme[force] +operator; when the promise is forced, the result is recorded, so that +any further @scheme[force] of the promise always produces the +remembered value.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[shared]} + +@defform[(shared ([id expr] ...) expr)]{ + +Like @scheme[letrec], but when an @scheme[expr] next to an @scheme[id] +is a @scheme[cons], @scheme[list], @scheme[vector], quasiquoted +expression, or @schemeidfont{make-}@scheme[_structid] from a +@scheme[define-struct], the @scheme[expr] can refer directly to any +@scheme[id], not just @scheme[id]s defined earlier. Thus, +@scheme[shared] can be used to create cyclic data structures.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "advanced-let"]{@scheme[let]} + +@defform*[[(let ([id expr] ...) expr) + (let id ([id expr] ...) expr)]]{ + +The first form of @scheme[let] is the same as Intermediate's +@|intm-let|. + +The second form is equivalent to a @scheme[recur] form.} + + +@; ---------------------------------------------------------------------- + +@section{@scheme[recur]} + +@defform[(recur id ([id expr] ...) expr)]{ + +A short-hand recursion construct. The first @scheme[id] corresponds to +the name of the recursive function. The parenthesized @scheme[id]s are +the function's arguments, and each corresponding @scheme[expr] is a +value supplied for that argument in an initial starting call of the +function. The last @scheme[expr] is the body of the function. + +More precisely, a @scheme[recur] form + +@schemeblock[ +(recur func-id ([arg-id arg-expr] (unsyntax @schemeidfont{...})) + body-expr) +] + +is equivalent to + +@schemeblock[ +((local [(define (func-id arg-id (unsyntax @schemeidfont{...})) + body-expr)] + func-id) + arg-expr (unsyntax @schemeidfont{...})) +]} + +@; ---------------------------------------------------------------------- + +@section{@scheme[case]} + +@defform[(case expr [(choice ...) expr] ... [(choice ...) expr])]{ + +A @scheme[case] form contains one or more ``lines'' that are +surrounded by parentheses or square brackets. Each line contains a +sequence of choices---numbers and names for symbols---and an answer +@scheme[expr]. The initial @scheme[expr] is evaluated, and the +resulting value is compared to the choices in each line, where the +lines are considered in order. The first line that contains a matching +choice provides an answer @scheme[expr] whose value is the result of +the whole @scheme[case] expression. If none of the lines contains a +matching choice, it is an error.} + +@defform/none[#:literals (cond else) + (cond expr [(choice ...) expr] ... [else expr])]{ + +This form of @scheme[case] is similar to the prior one, except that +the final @scheme[else] clause is always taken if no prior line +contains a choice matching the value of the initial @scheme[expr]. In +other words, so there is no possibility to ``fall off them end'' of +the @scheme[case] form.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[when] and @scheme[unless]} + +@defform[(when expr expr)]{ + +The first @scheme[expr] (known as the ``test'' expression) is +evaluated. If it evaluates to @scheme[true], the result of the +@scheme[when] expression is the result of evaluating the second +@scheme[expr], otherwise the result is @scheme[(void)] and the second +@scheme[expr] is not evaluated. If the result of evaluating the test +@scheme[expr] is neither @scheme[true] nor @scheme[false], it is an +error.} + +@defform[(unless expr expr)]{ + +Like @scheme[when], but the second @scheme[expr] is evaluated when the +first @scheme[expr] produces @scheme[false] instead of @scheme[true].} + +@; ---------------------------------------- + +@section[#:tag "advanced-prim-ops"]{Primitive Operations} + +The following primitives extend the set available though +@seclink["intermediate-prim-op"]{Intermediate}. + +@prim-op-defns['(lib "htdp-advanced.ss" "lang") + #'here + '((lib "htdp-beginner.ss" "lang") (lib "htdp-intermediate.ss" "lang"))] diff --git a/collects/scribblings/htdp-langs/beginner-abbr.scrbl b/collects/scribblings/htdp-langs/beginner-abbr.scrbl new file mode 100644 index 0000000000..accdc7b25a --- /dev/null +++ b/collects/scribblings/htdp-langs/beginner-abbr.scrbl @@ -0,0 +1,104 @@ +#lang scribble/doc +@(require "common.ss" + "std-grammar.ss" + "prim-ops.ss" + (for-label lang/htdp-beginner-abbr)) + +@title[#:style 'toc]{Beginner Student with List Abbreviations} + +@schemegrammar*+qq[ +#:literals (define define-struct lambda cond else if and or empty true false require lib planet) +[program 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 (code:line (id expr expr ...) (code:comment #, @seclink["beginner-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 ...) + empty + 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] +] + +@|prim-nonterms| + +@prim-ops['(lib "htdp-beginner-abbr.ss" "lang") #'here] + +@; ---------------------------------------- + +@section[#:tag "beginner-abbr-quote"]{Quote} + +@deftogether[( +@defform/none[(unsyntax @elem{@schemevalfont{'}@scheme[quoted]})] +@defform[(quote quoted)] +)]{ + +Creates symbols and abbreviates nested lists. + +Normally, this form is written with a @litchar{'}, like +@scheme['(apple banana)], but it can also be written with @scheme[quote], like +@scheme[((unsyntax @scheme[quote]) (apple banana))].} + +@; ---------------------------------------- + +@section[#:tag "beginner-abbr-quasiquote"]{Quasiquote} + +@deftogether[( +@defform/none[(unsyntax @elem{@schemevalfont{`}@scheme[quasiquoted]})] +@defform[(quasiquote quasiquoted)] +)]{ + +Creates symbols and abbreviates nested lists, but also allows escaping +to expression ``unquotes.'' + +Normally, this form is written with a backquote, @litchar{`}, like +@scheme[`(apple ,(+ 1 2))], but it can also be written with +@scheme[quasiquote], like @scheme[((unsyntax @scheme[quasiquote]) +(apple ,(+ 1 2)))].} + + +@deftogether[( +@defform/none[(unsyntax @elem{@schemevalfont{,}@scheme[quasiquoted]})] +@defform[(unquote expr)] +)]{ + +Under a single quasiquote, @schemefont{,}@scheme[expr] escapes from +the quote to include an evaluated expression whose result is inserted +into the abbreviated list. + +Under multiple quasiquotes, @schemefont{,}@scheme[expr] is really +@schemefont{,}@scheme[quasiquoted], decrementing the quasiquote count +by one for @scheme[quasiquoted]. + +Normally, an unquote is written with @litchar{,}, but it can also be +written with @scheme[unquote].} + + +@deftogether[( +@defform/none[(unsyntax @elem{@schemevalfont[",@"]@scheme[quasiquoted]})] +@defform[(unquote-splicing expr)] +)]{ + +Under a single quasiquote, @schemefont[",@"]@scheme[expr] escapes from +the quote to include an evaluated expression whose result is a list to +splice into the abbreviated list. + +Under multiple quasiquotes, a splicing unquote is like an unquote; +that is, it decrements the quasiquote count by one. + +Normally, a splicing unquote is written with @litchar{,}, but it can +also be written with @scheme[unquote-splicing].} diff --git a/collects/scribblings/htdp-langs/beginner.scrbl b/collects/scribblings/htdp-langs/beginner.scrbl new file mode 100644 index 0000000000..aa31e6b229 --- /dev/null +++ b/collects/scribblings/htdp-langs/beginner.scrbl @@ -0,0 +1,324 @@ +#lang scribble/doc +@(require "common.ss" + "std-grammar.ss" + "prim-ops.ss" + (for-label lang/htdp-beginner)) + +@(define-syntax-rule (bd intm-case) + (begin + (require (for-label lang/htdp-advanced)) + (define intm-case (scheme case)))) +@(bd adv-case) + + +@title[#:style 'toc]{Beginner Student} + +@schemegrammar*+library[ +#:literals (define define-struct lambda cond else if and or empty true false require lib planet) +[program 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 (code:line (id expr expr ...) (code:comment #, @seclink["beginner-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 ...) + empty + id + (code:line id (code:comment #, @seclink["beginner-id"]{identifier})) + (code:line #, @elem{@schemevalfont{'}@scheme[id]} (code:comment #, @seclink["beginner-quote"]{symbol})) + number + true + false + string + character] +] + +@|prim-nonterms| + +@prim-ops['(lib "htdp-beginner.ss" "lang") #'here] + +@; ---------------------------------------------------------------------- + +@section{@scheme[define]} + +@defform[(define (id id id ...) expr)]{ + +Defines a function. The first @scheme[id] inside the parentheses is +the name of the function. All remaining @scheme[id]s are the names of +the function's arguments. The @scheme[expr] is the body of the +function, evaluated whenever the function is called. The name of the +function cannot be that of a primitive or another definition.} + +@defform/none[#:literals (define) + (define id expr)]{ + +Defines a constant @scheme[id] as a synonym for the value produced by +@scheme[expr]. The defined name cannot be that of a primitive or +another definition, and @scheme[id] itself must not appear in +@scheme[expr].} + + +@defform/none[#:literals (define lambda) + (define id (lambda (id id ...) expr))]{ + +An alternate form for defining functions. The first @scheme[id] is the +name of the function. The @scheme[id]s in parentheses are the names of +the function's arguments, and the @scheme[expr] is the body of the +function, which evaluated whenever the function is called. The name +of the function cannot be that of a primitive or another definition.} + +@defidform[lambda]{ + +The @scheme[lambda] keyword can only be used with @scheme[define] in +the alternative function-definition syntax.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[define-struct]} + +@defform[(define-struct structid (fieldid ...))]{ + +Define a new type of structure. The structure's fields are named by +the @scheme[fieldid]s in parentheses. After evaluation of a +define-struct form, a set of new primitives is available for creation, +extraction, and type-like queries: + +@itemize{ + + @item{@schemeidfont{make-}@scheme[structid] : takes a number of + arguments equal to the number of fields in the structure type, + and creates a new instance of the structure type.} + + @item{@scheme[structid]@schemeidfont{-}@scheme[fieldid] : takes an + instance of the structure and returns the field named by + @scheme[structid].} + + @item{@scheme[structid]@schemeidfont{?} : takes any value, and returns + @scheme[true] if the value is an instance of the structure type.} + + @item{@scheme[structid] : an identifier representing the structure + type, but never used directly.} + +} + +The created names must not be the same as a primitive or another defined name.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "beginner-call"]{Function Calls} + +@defform/none[(id expr expr ...)]{ + +Calls a function. The @scheme[id] must refer to a defined function, +and the @scheme[expr]s are evaluated from left to right to produce the +values that are passed as arguments to the function. The result of the +function call is the result of evaluating the function's body with +every instance of an argument name replaced by the value passed for +that argument. The number of argument @scheme[expr]s must be the same +as the number of arguments expected by the function.} + +@defform[(#%app id expr expr ...)]{ + +A function call can be written with @scheme[#%app], though it's +practically never written that way.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "beginner-prim-call"]{Primitive Calls} + +@defform/none[(prim-op expr ...)]{ + +Like a @seclink["beginner-call"]{function call}, but for a primitive +operation. The @scheme[expr]s are evaluated from left to right, and +passed as arguments to the primitive operation named by +@scheme[prim-op]. A @scheme[define-struct] form creates new +primitives.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[cond]} + +@defform[(cond [expr expr] ... [expr expr])]{ + +A @scheme[cond] form contains one or more ``lines'' that are +surrounded by parentheses or square brackets. Each line contains two +@scheme[expr]s: a question @scheme[expr] and an answer +@scheme[expr]. + +The lines are considered in order. To evaluate a line, first evaluate +the question @scheme[expr]. If the result is @scheme[true], then the +result of the whole @scheme[cond] expression is the result of +evaluating the answer @scheme[expr] of the same line. If the result of +evaluating the question @scheme[expr] is @scheme[false], the line is +discarded and evaluation proceeds with the next line. + +If the result of a question @scheme[expr] is neither @scheme[true] nor +@scheme[false], it is an error. If none of the question @scheme[expr]s +evaluates to @scheme[true], it is also an error.} + +@defform/none[#:literals (cond else) + (cond [expr expr] ... [else expr])]{ + +This form of @scheme[cond] is similar to the prior one, except that +the final @scheme[else] clause is always taken if no prior line's test +expression evaluates to @scheme[true]. In other words, @scheme[else] +acts like @scheme[true], so there is no possibility to ``fall off them +end'' of the @scheme[cond] form.} + +@defidform[else]{ + +The @scheme[else] keyword can be used only with @scheme[cond], or in +Advanced language, with @|adv-case|.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[if]} + +@defform[(if expr expr expr)]{ + +The first @scheme[expr] (known as the ``test'' @scheme[expr]) is +evaluated. If it evaluates to @scheme[true], the result of the +@scheme[if] expression is the result of evaluating the second +@scheme[expr] (often called the ``then'' @scheme[expr]). If the text +@scheme[expr] evaluates to @scheme[false], the result of the +@scheme[if] expression is the result of evaluating the third +@scheme[expr]expression (known as the ``else'' @scheme[expr]). If the +result of evaluating the test @scheme[expr] is neither @scheme[true] +nor @scheme[false], it is an error.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[and]} + +@defform[(and expr expr expr ...)]{ + +The @scheme[expr]s are evaluated from left to right. If the first +@scheme[expr] evaluates to @scheme[false], the @scheme[and] expression +immediately evaluates to @scheme[false]. If the first @scheme[expr] +evaluates to @scheme[true], the next expression is considered. If all +@scheme[expr]s evaluate to @scheme[true], the @scheme[and] expression +evaluates to @scheme[true]. If any of the expressions evaluate to a +value other than @scheme[true] or @scheme[false], it is an error.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[or]} + +@defform[(or expr expr expr ...)]{ + +The @scheme[expr]s are evaluated from left to right. If the first +@scheme[expr] evaluates to @scheme[true], the @scheme[or] expression +immediately evaluates to @scheme[true]. If the first @scheme[expr] +evaluates to @scheme[false], the next expression is considered. If all +@scheme[expr]s evaluate to @scheme[false], the @scheme[or] expression +evaluates to @scheme[false]. If any of the expressions evaluate to a +value other than @scheme[true] or @scheme[false], it is an error.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[empty]} + +@defthing[empty empty?]{ + +The empty list.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "beginner-id"]{Identifiers} + +@defform/none[id]{ + +An @scheme[id] refers to a defined constant or argument within a +function body. If no definition or argument matches the @scheme[id] +name, an error is reported. Similarly, if @scheme[id] matches the name +of a defined function or primitive operation, an error is reported.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "beginner-quote"]{Symbols} + +@deftogether[( +@defform/none[(unsyntax @elem{@schemevalfont{'}@scheme[id]})] +@defform[(quote id)] +)]{ + +A quoted @scheme[id] is a symbol. A symbol is a constant, like +@scheme[0] and @scheme[empty]. + +Normally, a symbol is written with a @litchar{'}, like +@scheme['apple], but it can also be written with @scheme[quote], like +@scheme[((unsyntax @scheme[quote]) apple)]. + +The @scheme[id] for a symbol is a sequence of characters not including +a space or one of the following:} + +@t{@hspace[2] @litchar{"} @litchar{,} @litchar{'} @litchar{`} +@litchar{(} @litchar{)} @litchar{[} @litchar{]} +@litchar["{"] @litchar["}"] @litchar{|} @litchar{;} +@litchar{#}} + + +@; ---------------------------------------------------------------------- + +@section{@scheme[true] and @scheme[false]} + +@defthing[true boolean?]{ + +The true value.} + +@defthing[false boolean?]{ + +The false value.} + +@; ---------------------------------------------------------------------- + +@section{@scheme[require]} + +@defform[(require string)]{ + +Makes the definitions of the module specified by @scheme[string] +available in the current module (i.e., current file), where @scheme[string] +refers to a file relative to the enclosing file. + +The @scheme[string] is constrained in several ways to avoid problems +with different path conventions on different platforms: a @litchar{/} +is a directory separator, @litchar{.} always means the current +directory, @litchar{..} always means the parent directory, path +elements can use only @litchar{a} through @litchar{z} (uppercase or +lowercase), @litchar{0} through @litchar{9}, @litchar{-}, @litchar{_}, +and @litchar{.}, and the string cannot be empty or contain a leading +or trailing @litchar{/}.} + + +@defform/none[#:literals (require lib) + (require (lib string string ...))]{ + +Accesses a file in an installed library, making its definitions +available in the current module (i.e., current file). The first +@scheme[string] names the library file, and the remaining +@scheme[string]s name the collection (and sub-collection, and so on) +where the file is installed. Each string is constrained in the same +way as for the @scheme[(require string)] form.} + + +@defform/none[#:literals (require planet) + (require (planet string (string string number number)))]{ + + +Accesses a library that is distributed on the internet via the PLaneT +server, making it definitions available in the current module (i.e., +current file).} + +@; ---------------------------------------- + +@section[#:tag "beginner-prim-ops"]{Primitive Operations} + +@prim-op-defns['(lib "htdp-beginner.ss" "lang") #'here '()] diff --git a/collects/scribblings/htdp-langs/common.ss b/collects/scribblings/htdp-langs/common.ss new file mode 100644 index 0000000000..01d3919e49 --- /dev/null +++ b/collects/scribblings/htdp-langs/common.ss @@ -0,0 +1,5 @@ +#lang scheme/base + +(require scribble/manual) + +(provide (all-from-out scribble/manual)) diff --git a/collects/scribblings/htdp-langs/htdp-langs.scrbl b/collects/scribblings/htdp-langs/htdp-langs.scrbl new file mode 100644 index 0000000000..7bd53fba72 --- /dev/null +++ b/collects/scribblings/htdp-langs/htdp-langs.scrbl @@ -0,0 +1,18 @@ +#lang scribble/doc +@(require "common.ss") + +@title{Languages for @italic{How to Design Programs}} + +@table-of-contents[] + +@;------------------------------------------------------------------------ + +@include-section["beginner.scrbl"] +@include-section["beginner-abbr.scrbl"] +@include-section["intermediate.scrbl"] +@include-section["intermediate-lambda.scrbl"] +@include-section["advanced.scrbl"] + +@;------------------------------------------------------------------------ + +@index-section[] diff --git a/collects/scribblings/htdp-langs/info.ss b/collects/scribblings/htdp-langs/info.ss new file mode 100644 index 0000000000..01ae30e288 --- /dev/null +++ b/collects/scribblings/htdp-langs/info.ss @@ -0,0 +1,4 @@ +(module info setup/infotab + (define name "Scribblings: HtDP Languages") + (define scribblings '(("htdp-langs.scrbl" (multi-page main-doc))))) + diff --git a/collects/scribblings/htdp-langs/intermediate-lambda.scrbl b/collects/scribblings/htdp-langs/intermediate-lambda.scrbl new file mode 100644 index 0000000000..bb881b0f4c --- /dev/null +++ b/collects/scribblings/htdp-langs/intermediate-lambda.scrbl @@ -0,0 +1,99 @@ +#lang scribble/doc +@(require "common.ss" + "std-grammar.ss" + "prim-ops.ss" + (for-label lang/htdp-intermediate-lambda)) + +@(define-syntax-rule (bd intm-define) + (begin + (require (for-label lang/htdp-intermediate)) + (define intm-define (scheme define)))) +@(bd intm-define) + + +@title[#:style 'toc]{Intermediate Student with Lambda} + +@schemegrammar*+qq[ +#:literals (define define-struct lambda cond else if and or empty true false require lib planet + local let let* letrec time) +[program def-or-expr] +[def-or-expr definition + expr + library-require] +[definition (define (id id id ...) expr) + (define id expr) + (define-struct id (id ...))] +[expr (lambda (id id ...) expr) + (local [definition ...] expr) + (letrec ([id expr] ...) expr) + (let ([id expr] ...) expr) + (let* ([id expr] ...) expr) + (code:line (expr expr expr ...) (code:comment #, @seclink["intermediate-lambda-call"]{function 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) + empty + (code:line id (code:comment #, @seclink["intermediate-id"]{identifier})) + (code:line prim-op (code:comment #, @seclink["intermediate-lambda-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] +] + +@|prim-nonterms| + +@prim-ops['(lib "htdp-intermediate-lambda.ss" "lang") #'here] + +@; ---------------------------------------------------------------------- + +@section[#:tag "intermediate-lambda-define"]{@scheme[define]} + +@deftogether[( +@defform[(define (id id id ...) expr)] +@defform/none[#:literals (define) + (define id expr)] +)]{ + +The same as Intermediate's @|intm-define|. No special case is needed +for @scheme[lambda], since a @scheme[lambda] form is an expression.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "intermediate-lambda"]{@scheme[lambda]} + +@defform[(lambda (id id ...) expr)]{ + +Creates a function that takes as many arguments as given @scheme[id]s, +and whose body is @scheme[expr].} + +@; ---------------------------------------------------------------------- + +@section[#:tag "intermediate-lambda-call"]{Function Calls} + +@defform/none[(expr expr expr ...)]{ + +Like a Beginner @seclink["beginner-call"]{function call}, except that +the function position can be an arbitrary expression---perhaps a +@scheme[lambda] expression or a @scheme[_prim-op].} + +@defform[(#%app id expr expr ...)]{ + +A function call can be written with @scheme[#%app], though it's +practically never written that way.} + +@; ---------------------------------------------------------------------- + +@section[#:tag "intermediate-lambda-prim-op"]{Primitive Operation Names} + +@defform/none[prim-op]{ + +The name of a primitive operation can be used as an expression. It +produces a function version of the operation.} diff --git a/collects/scribblings/htdp-langs/intermediate.scrbl b/collects/scribblings/htdp-langs/intermediate.scrbl new file mode 100644 index 0000000000..2a9c6c8588 --- /dev/null +++ b/collects/scribblings/htdp-langs/intermediate.scrbl @@ -0,0 +1,184 @@ +#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) + (begin + (require (for-label lang/htdp-beginner)) + (define beg-define (scheme define)) + (define beg-define-struct (scheme define-struct)))) +@(bd beg-define beg-define-struct) + + +@title[#:style 'toc]{Intermediate Student} + +@schemegrammar*+qq[ +#:literals (define define-struct lambda cond else if and or empty true false require lib planet + local let let* letrec time) +[program 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) + 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 Beginner's @|beg-define|.} + +@defidform[lambda]{ + +As in Beginner, @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 Beginner'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 Beginner +@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 + '((lib "htdp-beginner.ss" "lang"))] diff --git a/collects/scribblings/htdp-langs/prim-ops.ss b/collects/scribblings/htdp-langs/prim-ops.ss new file mode 100644 index 0000000000..f639857a78 --- /dev/null +++ b/collects/scribblings/htdp-langs/prim-ops.ss @@ -0,0 +1,113 @@ +#reader(lib "scribble/reader.ss") +#lang scheme/base +(require "common.ss" + scribble/decode + scribble/struct + scribble/scheme + scheme/list + scheme/pretty + syntax/docprovide) + +(provide prim-ops + prim-op-defns) + +(define (maybe-make-table l t) + (if (paragraph? t) + (make-paragraph + (append l (cons " " + (paragraph-content t)))) + (make-table + "prototype" + (list (list (make-flow (list (make-paragraph l))) + (make-flow (list t))))))) + + +(define (typeset-type type) + (let-values ([(in out) (make-pipe)]) + (parameterize ([pretty-print-columns 50]) + (pretty-print type out)) + (port-count-lines! in) + (read-syntax #f in))) + +(define (sort-category category) + (sort + (cadr category) + (lambda (x y) + (string<=? (symbol->string (car x)) + (symbol->string (car y)))))) + + +(define (make-proto func ctx-stx) + (maybe-make-table + (list + (hspace 2) + (to-element (datum->syntax ctx-stx (car func))) + (hspace 1) + ":" + (hspace 1)) + (to-paragraph + (typeset-type (cadr func))))) + +(define (prim-ops lib ctx-stx) + (let ([ops (map (lambda (cat) + (cons (car cat) + (list (cdr cat)))) + (lookup-documentation lib 'procedures))]) + (make-table + #f + (cons + (list + (make-flow + (list + (make-paragraph + (list "A " (scheme _prim-op) " is one of:"))))) + (apply + append + (map (lambda (category) + (cons + (list (make-flow + (list + (make-paragraph (list (hspace 1) + (bold (car category))))))) + (map (lambda (func) + (list + (make-flow + (list + (make-proto func ctx-stx))))) + (sort-category category)))) + ops)))))) + + +(define (prim-op-defns lib ctx-stx not-in) + (make-splice + (let ([ops (map (lambda (cat) + (cons (car cat) + (list (cdr cat)))) + (lookup-documentation lib 'procedures))] + [not-in-ns (map (lambda (not-in-mod) + (let ([ns (make-base-namespace)]) + (parameterize ([current-namespace ns]) + (namespace-require `(for-label ,not-in-mod))) + ns)) + not-in)]) + (apply + append + (map (lambda (category) + (filter values + (map + (lambda (func) + (let ([id (datum->syntax ctx-stx (car func))]) + (and (not (ormap + (lambda (ns) + (free-label-identifier=? + id + (parameterize ([current-namespace ns]) + (namespace-syntax-introduce (datum->syntax #f (car func)))))) + not-in-ns)) + (let ([desc-strs (cddr func)]) + (defthing/proc + id + (to-paragraph (typeset-type (cadr func))) + (cons "Purpose: " desc-strs)))))) + (sort-category category)))) + ops))))) diff --git a/collects/scribblings/htdp-langs/std-grammar.ss b/collects/scribblings/htdp-langs/std-grammar.ss new file mode 100644 index 0000000000..1a0dbeedde --- /dev/null +++ b/collects/scribblings/htdp-langs/std-grammar.ss @@ -0,0 +1,71 @@ +#reader(lib "scribble/reader.ss") +#lang scheme/base +(require "common.ss" + scribble/decode + (for-label lang/htdp-beginner-abbr)) + +(provide prim-nonterms + schemegrammar*+library + schemegrammar*+qq) + +(define ex-str "This is a string with \" inside") + +(define-syntax-rule (schemegrammar*+library form ...) + (schemegrammar* + form ... + (... + [libray-require #, @scheme[(require string)] + #, @scheme[(require (lib string string ...))] + #, @scheme[(require (planet string package))]]) + (... + [package #, @scheme[(string string number number)]]))) + +(define-syntax-rule (schemegrammar*+qq form ...) + (schemegrammar*+library + form ... + (... + [quoted id + number + string + character + #, @scheme[(quoted ...)] + #, @elem{@schemevalfont{'}@scheme[quoted]} + #, @elem{@schemevalfont{`}@scheme[quoted]} + #, @elem{@schemefont{,}@scheme[quoted]} + #, @elem{@schemefont[",@"]@scheme[quoted]}]) + (... + [quasiquoted id + number + string + character + #, @scheme[(quasiquoted ...)] + #, @elem{@schemevalfont{'}@scheme[quasiquoted]} + #, @elem{@schemevalfont{`}@scheme[quasiquoted]} + #, @elem{@schemefont{,}@scheme[expr]} + #, @elem{@schemefont[",@"]@scheme[expr]}]))) + +(define prim-nonterms + (make-splice + (list + +@t{An @scheme[_id] is a sequence of characters not including a +space or one of the following:} + +@t{@hspace[2] @litchar{"} @litchar{,} @litchar{'} @litchar{`} +@litchar{(} @litchar{)} @litchar{[} @litchar{]} +@litchar["{"] @litchar["}"] @litchar{|} @litchar{;} +@litchar{#}} + +@t{A @scheme[_number] is a number such as @scheme[123], @scheme[3/2], or +@scheme[5.5].} + +@t{A @scheme[_string] is enclosed by a pair of @litchar{"}. Unlike +symbols, strings may be split into characters and manipulated by a +variety of primitive functions. For example, @scheme["abcdef"], +@scheme["This is a string"], and @scheme[#,ex-str] are all strings.} + +@t{A @scheme[_character] begins with @litchar{#\} and has the +name of the character. For example, @scheme[#\a], @scheme[#\b], +and @scheme[#\space] are characters.} + +))) diff --git a/collects/scribblings/scribble/style.scrbl b/collects/scribblings/scribble/style.scrbl index ca76033b0b..ff3cf4f5a5 100644 --- a/collects/scribblings/scribble/style.scrbl +++ b/collects/scribblings/scribble/style.scrbl @@ -19,6 +19,14 @@ typeset a library or language name is called @scheme[schememodname]). Do not call an identifier (i.e., a syntactic element) a ``variable'' or a ``symbol.'' +Avoid cut-and-paste for descriptive text. If two functions are +similar, consider documenting them together with +@scheme[deftogether]. To abstract a description, consider using +explicit prose abstraction, such as ``@scheme[x] is like @scheme[@y], +except that ...,'' instead of abstracting the source and instantiating +it multiple times; often, a prose abstraction is clearer to the reader +than a hidden abstraction in the document implementation. + Use @schemeidfont{id} or a name that ends @schemeidfont{-id} in @scheme[defform] to mean an identifier, not @schemeidfont{identifier}, @schemeidfont{variable}, @schemeidfont{name}, or @@ -69,10 +77,13 @@ specific sequence of characters. Refrain from referring to documentation ``above'' or ``below,'' and instead have a hyperlink point to the right place. -Use American style for quotation marks and punctuation at the end of -quotation marks (i.e., a sentence-terminating period goes inside the -quotation marks). Of course, this rule does not apply for quotation -marks that are part of code. +In prose, use @litchar{``} and @litchar{''} quotation marks instead of +@litchar{"}. Use @litchar{---} for an em-dash, and do not include +spaces on either side, though it will typeset as an en-dash and spaces +in HTML output. Use American style for quotation marks and punctuation +at the end of quotation marks (i.e., a sentence-terminating period +goes inside the quotation marks). Of course, this rule does not apply +for quotation marks that are part of code. Do not use a citation reference (as created by @scheme[cite]) as a -noun. Use it as an annotation. +noun; use it as an annotation.