The documentation for htdp-lang now uses the new vocabulary.

This commit is contained in:
Guillaume Marceau 2011-07-02 22:08:10 -04:00
parent 6eea5b1793
commit 01b9bde7fa
13 changed files with 1215 additions and 1446 deletions

View File

@ -1,10 +1,8 @@
#lang racket #lang racket
(define-syntax (test stx) #'(begin)) ;; TODO: convert my test into DrRacket's test framework (define-syntax (test stx) #'(begin)) ;; TODO: convert my test into DrRacket's test framework
(require #;gmarceau/test (require ; gmarceau/test
parser-tools/lex parser-tools/lex
(prefix-in : parser-tools/lex-sre) (prefix-in : parser-tools/lex-sre)
(rename-in srfi/26 [cut //]) (rename-in srfi/26 [cut //])
(only-in srfi/1 break) (only-in srfi/1 break)
@ -38,6 +36,7 @@
;; additional-highligts can specify their color ;; additional-highligts can specify their color
(define additional-highlights/c (listof (or/c srcloc-syntax/c (list/c srcloc-syntax/c symbol?)))) (define additional-highlights/c (listof (or/c srcloc-syntax/c (list/c srcloc-syntax/c symbol?))))
(define color/c (or/c #f symbol?))
;; colored-error-message : Exceptions that support highlighting contain a colored-error-message ;; colored-error-message : Exceptions that support highlighting contain a colored-error-message
;; in addition to a string. The string message is automatically generated from ;; in addition to a string. The string message is automatically generated from
@ -54,10 +53,11 @@
[struct colored-msg-fragment ([locs srcloc-syntax/c] [struct colored-msg-fragment ([locs srcloc-syntax/c]
[frags (listof (or/c msg-fragment:str? msg-fragment:v?))] [frags (listof (or/c msg-fragment:str? msg-fragment:v?))]
[important boolean?] [important boolean?]
[color (or/c #f symbol?)])]) [color color/c])])
;; prop:exn:colored-message : The property of exceptions that contain colored-message information. ;; prop:exn:colored-message : The property of exceptions that contain colored-message information.
;; The property's value is a function that when given an exception, returns the colored-error-message. ;; The property's value is a function that when given an exception, returns the colored-error-message.
(provide prop:exn:colored-message exn:colored-message? exn:colored-message-accessor)
(define-values (prop:exn:colored-message (define-values (prop:exn:colored-message
exn:colored-message? exn:colored-message?
exn:colored-message-accessor) exn:colored-message-accessor)
@ -70,8 +70,8 @@
;; get-error-message/color : When given an exception, if that exception contains coloring information, ;; get-error-message/color : When given an exception, if that exception contains coloring information,
;; returns it, otherwise, returns a colored-error-message that capture the information provided by ;; returns it, otherwise, returns a colored-error-message that capture the information provided by
;; by field message and the srclocs property (if any) of the exception. ;; by field message and the srclocs property (if any) of the exception.
(provide/contract [get-error-messages/color (exn? . -> . colored-error-message?)]) (provide/contract [get-error-message/color (exn? . -> . colored-error-message?)])
(define (get-error-messages/color exn) (define (get-error-message/color exn)
(cond [(exn:colored-message? exn) ((exn:colored-message-accessor exn) exn)] (cond [(exn:colored-message? exn) ((exn:colored-message-accessor exn) exn)]
[(exn:srclocs? exn) [(exn:srclocs? exn)
(colored-error-message (list (msg-fragment:str (exn-message exn))) (colored-error-message (list (msg-fragment:str (exn-message exn)))
@ -79,6 +79,17 @@
[else [else
(colored-error-message (list (msg-fragment:str (exn-message exn))) empty)])) (colored-error-message (list (msg-fragment:str (exn-message exn))) empty)]))
(provide/contract [get-error-colored-srclocs (exn? . -> . (listof (list/c srcloc-syntax/c color/c)))])
(define (get-error-colored-srclocs exn)
(define (promote srcloc) (if (list? srcloc) srcloc (list srcloc #f)))
(define msg (get-error-message/color exn))
(map promote
(append
(append*
(filter-map (// match <> [(colored-msg-fragment locs _ _ c)
(map (// list <> c) (if (list? locs) locs (list locs)))] [_ #f])
(colored-error-message-fragments msg)))
(colored-error-message-additional-highlights msg))))
(define lex (lexer (define lex (lexer
[(eof) empty] [(eof) empty]
@ -263,21 +274,23 @@
;; in the fmt. additional-highlights specifies srclocs that should be highlighted, in addition ;; in the fmt. additional-highlights specifies srclocs that should be highlighted, in addition
;; to the highlights used to explicate the correspondance between the text and the piece of codes. ;; to the highlights used to explicate the correspondance between the text and the piece of codes.
(define (raise-colored-syntax-error fmt #:additional-highlights [additional-highlights empty] . args) (define (raise-colored-syntax-error fmt #:additional-highlights [additional-highlights empty] . args)
(define formatted (apply colored-format fmt #:additional-highlights empty args)) (define formatted (apply colored-format fmt #:additional-highlights additional-highlights args))
(raise (exn:fail:colored:syntax (uncolor-message formatted) (raise (exn:fail:colored:syntax (uncolor-message formatted)
(current-continuation-marks) (current-continuation-marks)
(important-srclocs formatted) (important-srclocs formatted)
formatted))) formatted)))
(define (catch-the-error thunk) (with-handlers ([void (lambda (e) e)]) (thunk)))
(test 'raise-colored-syntax-error (test 'raise-colored-syntax-error
(check-exn-msg exn:fail:colored:syntax? #rx"only one part" (check-exn-msg exn:fail:colored:syntax? #rx"only one part"
(lambda () (raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~" (lambda () (raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~"
#'stx #'question))) #'stx #'question)))
(check-match (with-handlers ([void (lambda (e) (get-error-messages/color e))])
(raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~" (check-match (get-error-message/color (catch-the-error (lambda () (raise-colored-syntax-error "~|cond|~: expected a clause with a question and answer, but found a clause with only ~|one part|~"
#'stx #'question)) #'stx #'question))))
(colored-error-message (list (colored-msg-fragment (colored-error-message (list (colored-msg-fragment
(? syntax?) (? syntax?)
(list (msg-fragment:str "cond")) #f #f) (list (msg-fragment:str "cond")) #f #f)
(msg-fragment:str ": expected a clause with a question and answer, but found a clause with only ") (msg-fragment:str ": expected a clause with a question and answer, but found a clause with only ")
(colored-msg-fragment (? syntax?) (list (msg-fragment:str "one part")) #f #f)) (colored-msg-fragment (? syntax?) (list (msg-fragment:str "one part")) #f #f))
@ -285,5 +298,35 @@
(test 'get-error-messages/color (test 'get-error-messages/color
(check-equal? (get-error-messages/color (exn:fail:colored:syntax "ah!" (current-continuation-marks) (list #'here) (colored-error-message 1 2))) (check-equal? (get-error-message/color (exn:fail:colored:syntax "ah!" (current-continuation-marks) (list #'here) (colored-error-message 1 2)))
(colored-error-message 1 2))) (colored-error-message 1 2))
(check-match (important-srclocs (colored-format "~|1|~" (list #'first #t) #:additional-highlights '(a b)))
(list (app syntax-e 'first) a b))
(check-match (get-error-colored-srclocs (catch-the-error (lambda () (raise-colored-syntax-error "~|1|~ ~||~" (list #'first #t) (list #'second 'red) #:additional-highlights (list #'a #'b)))))
(list (list (app syntax-e 'first) #f) (list (app syntax-e 'second) 'red) (list (app syntax-e 'a) #f) (list (app syntax-e 'b) #f))))
#|
(provide insert-colored-message)
(define (insert-colored-message msg repl clickback)
(send repl begin-edit-sequence)
(define port (send repl get-err-port))
(let loop ([fragments (colored-error-message-fragments msg)])
(for ([f fragments])
(match f
[(msg-fragment:str str) (display str port)]
[(msg-fragment:v v) (write v port)]
[(colored-msg-fragment locs frags imp col)
(define start (send repl get-insertion-point))
(for-each loop frags)
(define end (send repl get-insertion-point))
(send repl higlight-range start end col #t)
(send repl set-clickback start end (lambda () (clickback f)))])))
(send repl highlight-errors (get-message-colored-srclocs msg))
;; need to flush here so that error annotations inserted in next line
;; don't get erased if this output were to happen after the insertion
(flush-output (send repl get-err-port))
(send repl end-edit-sequence))
|#

View File

@ -1034,7 +1034,6 @@
;; (string (union TST exn) -> void) -> string exn -> void ;; (string (union TST exn) -> void) -> string exn -> void
;; adds in the bug icon, if there are contexts to display ;; adds in the bug icon, if there are contexts to display
(define (teaching-languages-error-display-handler msg exn) (define (teaching-languages-error-display-handler msg exn)
(if (exn? exn) (if (exn? exn)
(display (exn-message exn) (current-error-port)) (display (exn-message exn) (current-error-port))
(fprintf (current-error-port) "uncaught exception: ~e" exn)) (fprintf (current-error-port) "uncaught exception: ~e" exn))

View File

@ -21,166 +21,166 @@
(random (case-> (random (case->
(integer -> integer) (integer -> integer)
(-> (and/c real inexact? (>/c 0) (</c 1)))) (-> (and/c real inexact? (>/c 0) (</c 1))))
"to generate a random natural number less than some given integer, or to generate a random inexact number between 0.0 and 1.0 exclusive")) "Generates a random natural number less than some given integer, or to generate a random inexact number between 0.0 and 1.0 exclusive"))
("Reading and Printing" ("Reading and Printing"
(with-input-from-file (string (-> any) -> any) (with-input-from-file (string (-> any) -> any)
"to open the named input file and to extract all input from there") "Opens the named input file and to extract all input from there")
(with-output-to-file (string (-> any) -> any) (with-output-to-file (string (-> any) -> any)
"to open the named output file and to put all output there") "Opens the named output file and to put all output there")
(with-input-from-string (string (-> any) -> any) (with-input-from-string (string (-> any) -> any)
"to turn the given string into input for read* operations") "Turns the given string into input for read* operations")
(with-output-to-string (string (-> any) -> any) (with-output-to-string (string (-> any) -> any)
"to produce a string from all write/display/print operations") "Produces a string from all write/display/print operations")
(print (any -> void) (print (any -> void)
"to print the argument as a value to stdout") "Prints the argument as a value to stdout")
(display (any -> void) (display (any -> void)
"to print the argument to stdout (without quotes on symbols and strings, etc.)") "Prints the argument to stdout (without quotes on symbols and strings, etc.)")
(write (any -> void) (write (any -> void)
"to print the argument to stdout (in a traditional style that is somewhere between print and display)") "Prints the argument to stdout (in a traditional style that is somewhere between print and display)")
((pp pretty-print) (any -> void) ((pp pretty-print) (any -> void)
"like write, but with standard newlines and indentation") "like write, but with standard newlines and indentation")
(printf (string any ... -> void) (printf (string any ... -> void)
"to format the rest of the arguments according to the first argument and print it to stdout") "Formats the rest of the arguments according to the first argument and print it to stdout")
(newline (-> void) (newline (-> void)
"to print a newline to stdout") "Prints a newline to stdout")
(read (-> sexp) "to read input from the user")) (read (-> sexp) "Reads input from the user"))
("Lists" ("Lists"
(list? (any -> boolean) (list? (any -> boolean)
"to determine whether some value is a list") "Determines whether some value is a list")
((advanced-list* list*) (any ... (listof any) -> (listof any)) ((advanced-list* list*) (any ... (listof any) -> (listof any))
"to construct a list by adding multiple items to a list") "Constructs a list by adding multiple items to a list")
((advanced-cons cons) (X (listof X) -> (listof X)) ((advanced-cons cons) (X (listof X) -> (listof X))
"to construct a list") "Constructs a list")
((advanced-append append) ((listof any) ... -> (listof any)) ((advanced-append append) ((listof any) ... -> (listof any))
"to create a single list from several") "Creates a single list from several")
(assoc (assoc
(any (listof any) -> (listof any) or false) (any (listof any) -> (listof any) or false)
"to produce the first element on the list whose first is equal? to v; otherwise it produces false")) "Produces the first element on the list whose first is equal? to v; otherwise it produces false"))
("Misc" ("Misc"
(gensym (-> symbol?) (gensym (-> symbol?)
"to generate a new symbol, different from all symbols in the program") "Generates a new symbol, different from all symbols in the program")
(sleep (-> positive-number void) (sleep (-> positive-number void)
"to cause the program to sleep for the given number of seconds") "Causes the program to sleep for the given number of seconds")
(current-milliseconds (-> exact-integer) (current-milliseconds (-> exact-integer)
"to return the current “time” in fixnum milliseconds (possibly negative)") "Returns the current “time” in fixnum milliseconds (possibly negative)")
(force (delay -> any) "to find the delayed value; see also delay") (force (delay -> any) "Finds the delayed value; see also delay")
(promise? (any -> boolean) "to determine if a value is delayed") (promise? (any -> boolean) "Determines if a value is delayed")
(void (-> void) "produces a void value") (void (-> void) "Produces a void value")
(void? (any -> boolean) "to determine if a value is void")) (void? (any -> boolean) "Determines if a value is void"))
("Posns" ("Posns"
(set-posn-x! (posn number -> void) "to update the x component of a posn") (set-posn-x! (posn number -> void) "Updates the x component of a posn")
(set-posn-y! (posn number -> void) "to update the x component of a posn")) (set-posn-y! (posn number -> void) "Updates the x component of a posn"))
("Vectors" ("Vectors"
(vector (X ... -> (vector X ...)) (vector (X ... -> (vector X ...))
"to construct a vector") "Constructs a vector")
(make-vector (number X -> (vectorof X)) (make-vector (number X -> (vectorof X))
"to construct a vector") "Constructs a vector")
(build-vector (nat (nat -> X) -> (vectorof X)) (build-vector (nat (nat -> X) -> (vectorof X))
"to construct a vector") "Constructs a vector")
(vector-ref ((vector X) nat -> X) (vector-ref ((vector X) nat -> X)
"to extract an element from a vector") "Extracts an element from a vector")
(vector-length ((vector X) -> nat) (vector-length ((vector X) -> nat)
"to determine the length of a vector") "Determines the length of a vector")
(vector-set! ((vectorof X) nat X -> void) (vector-set! ((vectorof X) nat X -> void)
"to update a vector") "Updates a vector")
(vector? (any -> boolean) (vector? (any -> boolean)
"to determine if a value is a vector")) "Determines if a value is a vector"))
("Boxes" ("Boxes"
(box (any -> box) (box (any -> box)
"to construct a box") "Constructs a box")
(unbox (box -> any) (unbox (box -> any)
"to extract the boxed value") "Extracts the boxed value")
(set-box! (box any -> void) (set-box! (box any -> void)
"to update a box") "Updates a box")
(box? (any -> boolean) (box? (any -> boolean)
"to determine if a value is a box")) "Determines if a value is a box"))
("Hash Tables" ("Hash Tables"
((advanced-make-hash make-hash) ((advanced-make-hash make-hash)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct a mutable hash table from an optional list of mappings that uses equal? for comparisions") "Constructs a mutable hash table from an optional list of mappings that uses equal? for comparisions")
((advanced-make-hasheq make-hasheq) ((advanced-make-hasheq make-hasheq)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct a mutable hash table from an optional list of mappings that uses eq? for comparisions") "Constructs a mutable hash table from an optional list of mappings that uses eq? for comparisions")
((advanced-make-hasheqv make-hasheqv) ((advanced-make-hasheqv make-hasheqv)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct a mutable hash table from an optional list of mappings that uses eqv? for comparisions") "Constructs a mutable hash table from an optional list of mappings that uses eqv? for comparisions")
((advanced-make-immutable-hash make-immutable-hash) ((advanced-make-immutable-hash make-immutable-hash)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct an immutable hash table from an optional list of mappings that uses equal? for comparisions") "Constructs an immutable hash table from an optional list of mappings that uses equal? for comparisions")
((advanced-make-immutable-hasheq make-immutable-hasheq) ((advanced-make-immutable-hasheq make-immutable-hasheq)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct an immutable hash table from an optional list of mappings that uses eq? for comparisions") "Constructs an immutable hash table from an optional list of mappings that uses eq? for comparisions")
((advanced-make-immutable-hasheqv make-immutable-hasheqv) ((advanced-make-immutable-hasheqv make-immutable-hasheqv)
(case-> (case->
(-> (hash X Y)) (-> (hash X Y))
((listof (list X Y)) -> (hash X Y))) ((listof (list X Y)) -> (hash X Y)))
"to construct an immutable hash table from an optional list of mappings that uses eqv? for comparisions") "Constructs an immutable hash table from an optional list of mappings that uses eqv? for comparisions")
(hash-set! ((hash X Y) X Y -> void) (hash-set! ((hash X Y) X Y -> void)
"to update a mutable hash table with a new mapping") "Updates a mutable hash table with a new mapping")
(hash-set ((hash X Y) X Y -> (hash X Y)) (hash-set ((hash X Y) X Y -> (hash X Y))
"to construct an immutable hash table with one new mapping from an existing immutable hash table") "Constructs an immutable hash table with one new mapping from an existing immutable hash table")
(hash-ref (case-> (hash-ref (case->
((hash X Y) X -> Y) ((hash X Y) X -> Y)
((hash X Y) X Y -> Y) ((hash X Y) X Y -> Y)
((hash X Y) X (-> Y) -> Y)) ((hash X Y) X (-> Y) -> Y))
"to extract the value associated with a key from a hash table; the three argument case allows a default value or default value computation") "Extracts the value associated with a key from a hash table; the three argument case allows a default value or default value computation")
(hash-ref! (case-> (hash-ref! (case->
((hash X Y) X Y -> Y) ((hash X Y) X Y -> Y)
((hash X Y) X (-> Y) -> Y)) ((hash X Y) X (-> Y) -> Y))
"to extract the value associated with a key from a mutable hash table; if the key does not have an mapping, the third argument is used as the value (or used to compute the value) and is added to the hash table associated with the key") "Extracts the value associated with a key from a mutable hash table; if the key does not have an mapping, the third argument is used as the value (or used to compute the value) and is added to the hash table associated with the key")
(hash-update! (case-> (hash-update! (case->
((hash X Y) X (Y -> Y) -> void) ((hash X Y) X (Y -> Y) -> void)
((hash X Y) X (Y -> Y) Y -> void) ((hash X Y) X (Y -> Y) Y -> void)
((hash X Y) X (Y -> Y) (-> Y) -> void)) ((hash X Y) X (Y -> Y) (-> Y) -> void))
"to compose hash-ref and hash-set! to update an existing mapping; the third argument is used to compute the new mapping value; the fourth argument is used as the third argument to hash-ref") "Composes hash-ref and hash-set! to update an existing mapping; the third argument is used to compute the new mapping value; the fourth argument is used as the third argument to hash-ref")
(hash-update (case-> (hash-update (case->
((hash X Y) X (Y -> Y) -> (hash X Y)) ((hash X Y) X (Y -> Y) -> (hash X Y))
((hash X Y) X (Y -> Y) Y -> (hash X Y)) ((hash X Y) X (Y -> Y) Y -> (hash X Y))
((hash X Y) X (Y -> Y) (-> Y) -> (hash X Y))) ((hash X Y) X (Y -> Y) (-> Y) -> (hash X Y)))
"to compose hash-ref and hash-set to update an existing mapping; the third argument is used to compute the new mapping value; the fourth argument is used as the third argument to hash-ref") "Composes hash-ref and hash-set to update an existing mapping; the third argument is used to compute the new mapping value; the fourth argument is used as the third argument to hash-ref")
(hash-has-key? ((hash X Y) X -> boolean) (hash-has-key? ((hash X Y) X -> boolean)
"to determine if a key is associated with a value in a hash table") "Determines if a key is associated with a value in a hash table")
(hash-remove! ((hash X Y) X -> void) (hash-remove! ((hash X Y) X -> void)
"to remove an mapping from a mutable hash table") "Removes an mapping from a mutable hash table")
(hash-remove ((hash X Y) X -> (hash X Y)) (hash-remove ((hash X Y) X -> (hash X Y))
"to construct an immutable hash table with one less mapping than an existing immutable hash table") "Constructs an immutable hash table with one less mapping than an existing immutable hash table")
(hash-map ((hash X Y) (X Y -> A) -> (listof A)) (hash-map ((hash X Y) (X Y -> A) -> (listof A))
"to construct a new list by applying a function to each mapping of a hash table") "Constructs a new list by applying a function to each mapping of a hash table")
(hash-for-each ((hash X Y) (X Y -> any) -> void) (hash-for-each ((hash X Y) (X Y -> any) -> void)
"to apply a function to each mapping of a hash table for effect only") "Applies a function to each mapping of a hash table for effect only")
(hash-count (hash -> integer) (hash-count (hash -> integer)
"to determine the number of keys mapped by a hash table") "Determines the number of keys mapped by a hash table")
(hash-copy (hash -> hash) (hash-copy (hash -> hash)
"to copy a hash table") "Copies a hash table")
(hash? (any -> boolean) (hash? (any -> boolean)
"to determine if a value is a hash table") "Determines if a value is a hash table")
(hash-equal? (hash -> boolean) (hash-equal? (hash -> boolean)
"to determine if a hash table uses equal? for comparisions") "Determines if a hash table uses equal? for comparisions")
(hash-eq? (hash -> boolean) (hash-eq? (hash -> boolean)
"to determine if a hash table uses eq? for comparisions") "Determines if a hash table uses eq? for comparisions")
(hash-eqv? (hash -> boolean) (hash-eqv? (hash -> boolean)
"to determine if a hash table uses eqv? for comparisions")))) "Determines if a hash table uses eqv? for comparisions"))))

View File

@ -2,9 +2,9 @@
(require mzlib/etc mzlib/list mzlib/math syntax/docprovide) (require mzlib/etc mzlib/list mzlib/math syntax/docprovide)
;; Implements the procedures: ;; Implements the procedures:
(require "teachprims.rkt" (require "teachprims.ss"
"../posn.rkt" "../posn.ss"
"../imageeq.rkt") "../imageeq.ss")
;; procedures with documentation: ;; procedures with documentation:
(provide-and-document (provide-and-document
@ -12,485 +12,485 @@
("Numbers: Integers, Rationals, Reals, Complex, Exacts, Inexacts" ("Numbers: Integers, Rationals, Reals, Complex, Exacts, Inexacts"
(number? (any -> boolean) (number? (any -> boolean)
"to determine whether some value is a number") "Determines whether some value is a number")
(= (number number number ... -> boolean) (= (number number number ... -> boolean)
"to compare numbers for equality") "Compares numbers for equality")
(< (real real real ... -> boolean) (< (real real real ... -> boolean)
"to compare real numbers for less-than") "Compares real numbers for less-than")
(> (real real real ... -> boolean) (> (real real real ... -> boolean)
"to compare real numbers for greater-than") "Compares real numbers for greater-than")
(<= (real real real ... -> boolean) (<= (real real real ... -> boolean)
"to compare real numbers for less-than or equality") "Compares real numbers for less-than or equality")
(>= (real real ... -> boolean) (>= (real real ... -> boolean)
"to compare real numbers for greater-than or equality") "Compares real numbers for greater-than or equality")
((beginner-+ +) (number number number ... -> number) ((beginner-+ +) (number number number ... -> number)
"to compute the sum of the input numbers") "Evaluates the sum of the input numbers")
(- (number number ... -> number) (- (number number ... -> number)
"to subtract the second (and following) number(s) from the first; negate the number if there is only one argument") "subtracts the second (and following) number(s) from the first; negate the number if there is only one argument")
((beginner-* *) (number number number ... -> number) ((beginner-* *) (number number number ... -> number)
"to compute the product of all of the input numbers") "Evaluates the product of all of the input numbers")
((beginner-/ /) (number number number ... -> number) ((beginner-/ /) (number number number ... -> number)
"to divide the first by the second (and all following) number(s); try (/ 3 4) and (/ 3 2 2)" "Divides the first by the second (and all following) number(s); try (/ 3 4) and (/ 3 2 2)"
" only the first number can be zero.") " only the first number can be zero.")
(max (real real ... -> real) (max (real real ... -> real)
"to determine the largest number") "Determines the largest number")
(min (real real ... -> real) (min (real real ... -> real)
"to determine the smallest number") "Determines the smallest number")
(quotient (integer integer -> integer) (quotient (integer integer -> integer)
"to divide the first integer (exact or inexact) into the second; try (quotient 3 4) and (quotient 4 3)") "Divides the first integer (exact or inexact) into the second; try (quotient 3 4) and (quotient 4 3)")
(remainder (integer integer -> integer) (remainder (integer integer -> integer)
"to determine the remainder of dividing the first by the second integer (exact or inexact)") "Determines the remainder of dividing the first by the second integer (exact or inexact)")
(modulo (integer integer -> integer) (modulo (integer integer -> integer)
"to find the remainder of the division of the first number by the second; try (modulo 4 3) (modulo 4 -3)") "Finds the remainder of the division of the first number by the second; try (modulo 4 3) (modulo 4 -3)")
((beginner-sqr sqr) (number -> number) ((beginner-sqr sqr) (number -> number)
"to compute the square of a number") "Evaluates the square of a number")
(sqrt (number -> number) (sqrt (number -> number)
"to compute the square root of a number") "Evaluates the square root of a number")
(integer-sqrt (number -> integer) (integer-sqrt (number -> integer)
"to compute the integer (exact or inexact) square root of a number") "Evaluates the integer (exact or inexact) square root of a number")
(expt (number number -> number) (expt (number number -> number)
"to compute the power of the first to the second number") "Evaluates the power of the first to the second number")
(abs (real -> real) (abs (real -> real)
"to compute the absolute value of a real number") "Evaluates the absolute value of a real number")
(sgn (real -> (union 1 #i1.0 0 #i0.0 -1 #i-1.0)) (sgn (real -> (union 1 #i1.0 0 #i0.0 -1 #i-1.0))
"to compute the sign of a real number") "Evaluates the sign of a real number")
;; fancy numeric ;; fancy numeric
(exp (number -> number) (exp (number -> number)
"to compute e raised to a number") "Evaluates e raised to a number")
(log (number -> number) (log (number -> number)
"to compute the base-e logarithm of a number") "Evaluates the base-e logarithm of a number")
;; trigonometry ;; trigonometry
(sin (number -> number) (sin (number -> number)
"to compute the sine of a number (radians)") "Evaluates the sine of a number (radians)")
(cos (number -> number) (cos (number -> number)
"to compute the cosine of a number (radians)") "Evaluates the cosine of a number (radians)")
(tan (number -> number) (tan (number -> number)
"to compute the tangent of a number (radians)") "Evaluates the tangent of a number (radians)")
(asin (number -> number) (asin (number -> number)
"to compute the arcsine (inverse of sin) of a number") "Evaluates the arcsine (inverse of sin) of a number")
(acos (number -> number) (acos (number -> number)
"to compute the arccosine (inverse of cos) of a number") "Evaluates the arccosine (inverse of cos) of a number")
(atan (number -> number) (atan (number -> number)
"to compute the arctan (inverse of tan) of a number") "Evaluates the arctan (inverse of tan) of a number")
(sinh (number -> number) (sinh (number -> number)
"to compute the hyperbolic sine of a number") "Evaluates the hyperbolic sine of a number")
(cosh (number -> number) (cosh (number -> number)
"to compute the hyperbolic cosine of a number") "Evaluates the hyperbolic cosine of a number")
(exact? (number -> boolean) (exact? (number -> boolean)
"to determine whether some number is exact") "Determines whether some number is exact")
(integer? (any -> boolean) (integer? (any -> boolean)
"to determine whether some value is an integer (exact or inexact)") "Determines whether some value is an integer (exact or inexact)")
(zero? (number -> boolean) (zero? (number -> boolean)
"to determine if some value is zero or not") "Determines if some value is zero or not")
(positive? (number -> boolean) (positive? (number -> boolean)
"to determine if some value is strictly larger than zero") "Determines if some value is strictly larger than zero")
(negative? (number -> boolean) (negative? (number -> boolean)
"to determine if some value is strictly smaller than zero") "Determines if some value is strictly smaller than zero")
(odd? (integer -> boolean) (odd? (integer -> boolean)
"to determine if some integer (exact or inexact) is odd or not") "Determines if some integer (exact or inexact) is odd or not")
(even? (integer -> boolean) (even? (integer -> boolean)
"to determine if some integer (exact or inexact) is even or not") "Determines if some integer (exact or inexact) is even or not")
(add1 (number -> number) (add1 (number -> number)
"to compute a number one larger than a given number") "Evaluates a number one larger than a given number")
(sub1 (number -> number) (sub1 (number -> number)
"to compute a number one smaller than a given number") "Evaluates a number one smaller than a given number")
(lcm (integer integer ... -> integer) (lcm (integer integer ... -> integer)
"to compute the least common multiple of two integers (exact or inexact)") "Evaluates the least common multiple of two integers (exact or inexact)")
(gcd (integer integer ... -> integer) (gcd (integer integer ... -> integer)
"to compute the greatest common divisior of two integers (exact or inexact)") "Evaluates the greatest common divisior of two integers (exact or inexact)")
(rational? (any -> boolean) (rational? (any -> boolean)
"to determine whether some value is a rational number") "Determines whether some value is a rational number")
(numerator (rat -> integer) (numerator (rat -> integer)
"to compute the numerator of a rational") "Evaluates the numerator of a rational")
(denominator (rat -> integer) (denominator (rat -> integer)
"to compute the denominator of a rational") "Evaluates the denominator of a rational")
(inexact? (number -> boolean) (inexact? (number -> boolean)
"to determine whether some number is inexact") "Determines whether some number is inexact")
(real? (any -> boolean) (real? (any -> boolean)
"to determine whether some value is a real number") "Determines whether some value is a real number")
(floor (real -> integer) (floor (real -> integer)
"to determine the closest integer (exact or inexact) below a real number") "Determines the closest integer (exact or inexact) below a real number")
(ceiling (real -> integer) (ceiling (real -> integer)
"to determine the closest integer (exact or inexact) above a real number") "Determines the closest integer (exact or inexact) above a real number")
(round (real -> integer) (round (real -> integer)
"to round a real number to an integer (rounds to even to break ties)") "Rounds a real number to an integer (rounds to even to break ties)")
(complex? (any -> boolean) (complex? (any -> boolean)
"to determine whether some value is complex") "Determines whether some value is complex")
(make-polar (real real -> number) (make-polar (real real -> number)
"to create a complex from a magnitude and angle") "Creates a complex from a magnitude and angle")
(make-rectangular (real real -> number) (make-rectangular (real real -> number)
"to create a complex from a real and an imaginary part") "Creates a complex from a real and an imaginary part")
(real-part (number -> real) (real-part (number -> real)
"to extract the real part from a complex number") "Extracts the real part from a complex number")
(imag-part (number -> real) (imag-part (number -> real)
"to extract the imaginary part from a complex number") "Extracts the imaginary part from a complex number")
(magnitude (number -> real) (magnitude (number -> real)
"to determine the magnitude of a complex number") "Determines the magnitude of a complex number")
(angle (number -> real) (angle (number -> real)
"to extract the angle from a complex number") "Extracts the angle from a complex number")
(conjugate (number -> number) (conjugate (number -> number)
"to compute the conjugate of a complex number") "Evaluates the conjugate of a complex number")
(exact->inexact (number -> number) (exact->inexact (number -> number)
"to convert an exact number to an inexact one") "Converts an exact number to an inexact one")
(inexact->exact (number -> number) (inexact->exact (number -> number)
"to approximate an inexact number by an exact one") "Approximates an inexact number by an exact one")
; "Odds and ends" ; "Odds and ends"
(number->string (number -> string) (number->string (number -> string)
"to convert a number to a string") "Converts a number to a string")
(integer->char (integer -> char) (integer->char (integer -> char)
"to lookup the character that corresponds to the given integer (exact only!) in the ASCII table (if any)") "Lookups the character that corresponds to the given integer (exact only!) in the ASCII table (if any)")
((beginner-random random) (integer -> integer) ((beginner-random random) (integer -> integer)
"to generate a random natural number less than some given integer (exact only!)") "Generates a random natural number less than some given integer (exact only!)")
(current-seconds (-> integer) (current-seconds (-> integer)
"to compute the current time in seconds elapsed" "Evaluates the current time in seconds elapsed"
" (since a platform-specific starting date)") " (since a platform-specific starting date)")
(e real (e real
"Euler's number") "Euler's number")
(pi real (pi real
"the ratio of a circle's circumference to its diameter")) "The ratio of a circle's circumference to its diameter"))
("Booleans" ("Booleans"
(boolean? (any -> boolean) (boolean? (any -> boolean)
"to determine whether some value is a boolean") "Determines whether some value is a boolean")
(boolean=? (boolean boolean -> boolean) (boolean=? (boolean boolean -> boolean)
"to determine whether two booleans are equal") "Determines whether two booleans are equal")
(false? (any -> boolean) (false? (any -> boolean)
"to determine whether a value is false") "Determines whether a value is false")
((beginner-not not) (boolean -> boolean) ((beginner-not not) (boolean -> boolean)
"to compute the negation of a boolean value")) "Evaluates the negation of a boolean value"))
("Symbols" ("Symbols"
(symbol? (any -> boolean) (symbol? (any -> boolean)
"to determine whether some value is a symbol") "Determines whether some value is a symbol")
(symbol=? (symbol symbol -> boolean) (symbol=? (symbol symbol -> boolean)
"to determine whether two symbols are equal") "Determines whether two symbols are equal")
(symbol->string (symbol -> string) (symbol->string (symbol -> string)
"to convert a symbol to a string") ) "Converts a symbol to a string") )
("Lists" ("Lists"
(cons? (any -> boolean) (cons? (any -> boolean)
"to determine whether some value is a constructed list") "Determines whether some value is a constructed list")
#; #;
(pair? (any -> boolean) (pair? (any -> boolean)
"to determine whether some value is a constructed list") "Determines whether some value is a constructed list")
(empty? (any -> boolean) (empty? (any -> boolean)
"to determine whether some value is the empty list") "Determines whether some value is the empty list")
(null? (any -> boolean) (null? (any -> boolean)
"to determine whether some value is the empty list") "Determines whether some value is the empty list")
((beginner-cons cons) (X (listof X) -> (listof X)) ((beginner-cons cons) (X (listof X) -> (listof X))
"to construct a list") "Constructs a list")
(null empty (null empty
"the empty list") "The empty list")
((beginner-first first) ( (cons Y (listof X)) -> Y ) ((beginner-first first) ( (cons Y (listof X)) -> Y )
"to select the first item of a non-empty list") "Selects the first item of a non-empty list")
((beginner-car car) ( (cons Y (listof X)) -> Y ) ((beginner-car car) ( (cons Y (listof X)) -> Y )
"to select the first item of a non-empty list") "Selects the first item of a non-empty list")
((beginner-rest rest) ((cons Y (listof X)) -> (listof X)) ((beginner-rest rest) ((cons Y (listof X)) -> (listof X))
"to select the rest of a non-empty list") "Selects the rest of a non-empty list")
((beginner-cdr cdr) ((cons Y (listof X)) -> (listof X)) ((beginner-cdr cdr) ((cons Y (listof X)) -> (listof X))
"to select the rest of a non-empty list") "Selects the rest of a non-empty list")
(second ( (cons Z (cons Y (listof X))) -> Y ) (second ( (cons Z (cons Y (listof X))) -> Y )
"to select the second item of a non-empty list") "Selects the second item of a non-empty list")
(cadr ( (cons Z (cons Y (listof X))) -> Y ) (cadr ( (cons Z (cons Y (listof X))) -> Y )
"to select the second item of a non-empty list") "Selects the second item of a non-empty list")
(cdar ( (cons (cons Z (listof Y)) (listof X)) -> (listof Y) ) (cdar ( (cons (cons Z (listof Y)) (listof X)) -> (listof Y) )
"to select the rest of a non-empty list in a list") "Selects the rest of a non-empty list in a list")
(caar ( (cons (cons Z (listof Y)) (listof X)) -> Z ) (caar ( (cons (cons Z (listof Y)) (listof X)) -> Z )
"to select the first item of the first list in a list") "Selects the first item of the first list in a list")
(cddr ( (cons Z (cons Y (listof X))) -> (listof X) ) (cddr ( (cons Z (cons Y (listof X))) -> (listof X) )
"to select the rest of the rest of a list") "Selects the rest of the rest of a list")
(third ( (cons W (cons Z (cons Y (listof X)))) -> Y ) (third ( (cons W (cons Z (cons Y (listof X)))) -> Y )
"to select the third item of a non-empty list") "Selects the third item of a non-empty list")
(caddr ( (cons W (cons Z (cons Y (listof X)))) -> Y ) (caddr ( (cons W (cons Z (cons Y (listof X)))) -> Y )
"to select the third item of a non-empty list") "Selects the third item of a non-empty list")
(caadr ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> (listof Z) ) (caadr ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> (listof Z) )
"to select the rest of the first list in the first list of a list") "Selects the rest of the first list in the first list of a list")
(caaar ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> W ) (caaar ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> W )
"to select the first item of the first list in the first list of a list") "Selects the first item of the first list in the first list of a list")
(cdaar ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> (listof Z) ) (cdaar ( (cons (cons (cons W (listof Z)) (listof Y)) (listof X)) -> (listof Z) )
"to select the rest of the first list in the first list of a list") "Selects the rest of the first list in the first list of a list")
(cdadr ( (cons W (cons (cons Z (listof Y)) (listof X))) -> (listof Y) ) (cdadr ( (cons W (cons (cons Z (listof Y)) (listof X))) -> (listof Y) )
"to select the rest of the first list in the rest of a list") "Selects the rest of the first list in the rest of a list")
(cadar ( (cons (cons W (cons Z (listof Y))) (listof X)) -> Z ) (cadar ( (cons (cons W (cons Z (listof Y))) (listof X)) -> Z )
"to select the second item of the first list of a list") "Selects the second item of the first list of a list")
(cddar ( (cons (cons W (cons Z (listof Y))) (listof X)) -> (listof Y) ) (cddar ( (cons (cons W (cons Z (listof Y))) (listof X)) -> (listof Y) )
"to select the rest of the rest of the first list of a list") "Selects the rest of the rest of the first list of a list")
(cdddr ( (cons W (cons Z (cons Y (listof X)))) -> (listof X) ) (cdddr ( (cons W (cons Z (cons Y (listof X)))) -> (listof X) )
"to select the rest of the rest of the rest of a list") "Selects the rest of the rest of the rest of a list")
(fourth ( (listof Y) -> Y ) ; domain: (cons V (cons W (cons Z (cons Y (listof X))))) (fourth ( (listof Y) -> Y ) ; domain: (cons V (cons W (cons Z (cons Y (listof X)))))
"to select the fourth item of a non-empty list") "Selects the fourth item of a non-empty list")
(cadddr ( (listof Y) -> Y ) ; domain: (cons V (cons W (cons Z (cons Y (listof X))))) (cadddr ( (listof Y) -> Y ) ; domain: (cons V (cons W (cons Z (cons Y (listof X)))))
"to select the fourth item of a non-empty list") "Selects the fourth item of a non-empty list")
(fifth ( (listof Y) -> Y ) ; domain: (cons U (cons V (cons W (cons Z (cons Y (listof X)))))) (fifth ( (listof Y) -> Y ) ; domain: (cons U (cons V (cons W (cons Z (cons Y (listof X))))))
"to select the fifth item of a non-empty list") "Selects the fifth item of a non-empty list")
(sixth ( (listof Y) -> Y ) ; domain: (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X))))))) (sixth ( (listof Y) -> Y ) ; domain: (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X)))))))
"to select the sixth item of a non-empty list") "Selects the sixth item of a non-empty list")
(seventh ( (listof Y) -> Y ) ; domain: (cons S (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X)))))))) (seventh ( (listof Y) -> Y ) ; domain: (cons S (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X))))))))
"to select the seventh item of a non-empty list") "Selects the seventh item of a non-empty list")
(eighth ( (listof Y) -> Y ) ; domain: (cons R (cons S (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X))))))))) (eighth ( (listof Y) -> Y ) ; domain: (cons R (cons S (cons T (cons U (cons V (cons W (cons Z (cons Y (listof X)))))))))
"to select the eighth item of a non-empty list") "Selects the eighth item of a non-empty list")
(list-ref ((listof X) natural-number -> X ) (list-ref ((listof X) natural-number -> X )
"to extract the indexed item from the list") "Extracts the indexed item from the list")
(list (any ... -> (listof any)) "to construct a list of its arguments") (list (any ... -> (listof any)) "constructs a list of its arguments")
(make-list (natural-number any -> (listof any)) "(make-list k x) constructs a list of k copies of x") (make-list (natural-number any -> (listof any)) "(make-list k x) constructs a list of k copies of x")
((beginner-list* list*) (any ... (listof any) -> (listof any)) ((beginner-list* list*) (any ... (listof any) -> (listof any))
"to construct a list by adding multiple items to a list") "Constructs a list by adding multiple items to a list")
((beginner-append append) ((listof any) (listof any) (listof any) ... -> (listof any)) ((beginner-append append) ((listof any) (listof any) (listof any) ... -> (listof any))
"to create a single list from several, by juxtaposition of the items") "Creates a single list from several, by juxtaposition of the items")
(length ((listof any) -> number) (length ((listof any) -> number)
"to compute the number of items on a list") "Evaluates the number of items on a list")
(memq (any (listof any) -> (union false list)) (memq (any (listof any) -> (union false list))
"to determine whether some value is on some list" "Determines whether some value is on some list"
" if so, it produces the suffix of the list that starts with x" " if so, it produces the suffix of the list that starts with x"
" if not, it produces false." " if not, it produces false."
" (It compares values with the eq? predicate.)") " (It compares values with the eq? predicate.)")
(memv (any (listof any) -> (union false list)) (memv (any (listof any) -> (union false list))
"to determine whether some value is on the list" "Determines whether some value is on the list"
" if so, it produces the suffix of the list that starts with x" " if so, it produces the suffix of the list that starts with x"
" if not, it produces false." " if not, it produces false."
" (it compares values with the eqv? predicate.)") " (it compares values with the eqv? predicate.)")
((beginner-member? member?) (any (listof any) -> boolean) ((beginner-member? member?) (any (listof any) -> boolean)
"to determine whether some value is on the list" "Determines whether some value is on the list"
" (comparing values with equal?)") " (comparing values with equal?)")
((beginner-member member) (any (listof any) -> boolean) ((beginner-member member) (any (listof any) -> boolean)
"to determine whether some value is on the list" "Determines whether some value is on the list"
" (comparing values with equal?)") " (comparing values with equal?)")
((beginner-remove remove) (any (listof any) -> (listof any)) ((beginner-remove remove) (any (listof any) -> (listof any))
"to construct a list like the given one with the first occurrence of the given item removed" "Constructs a list like the given one with the first occurrence of the given item removed"
" (comparing values with equal?)") " (comparing values with equal?)")
(reverse ((listof any) -> list) (reverse ((listof any) -> list)
"to create a reversed version of a list") "Creates a reversed version of a list")
(assq (X (listof (cons X Y)) -> (union false (cons X Y))) (assq (X (listof (cons X Y)) -> (union false (cons X Y)))
"to determine whether some item is the first item of a pair" "Determines whether some item is the first item of a pair"
" in a list of pairs")) " in a list of pairs"))
("Posns" ("Posns"
(posn signature "signature for posns") (posn signature "signature for posns")
(make-posn (number number -> posn) "to construct a posn") (make-posn (number number -> posn) "constructs a posn")
(posn? (anything -> boolean) "to determine if its input is a posn") (posn? (anything -> boolean) "determines if its input is a posn")
(posn-x (posn -> number) "to extract the x component of a posn") (posn-x (posn -> number) "extracts the x component of a posn")
(posn-y (posn -> number) "to extract the y component of a posn")) (posn-y (posn -> number) "extracts the y component of a posn"))
("Characters" ("Characters"
(char? (any -> boolean) (char? (any -> boolean)
"to determine whether a value is a character") "Determines whether a value is a character")
(char=? (char char char ... -> boolean) (char=? (char char char ... -> boolean)
"to determine whether two characters are equal") "Determines whether two characters are equal")
(char<? (char char char ... -> boolean) (char<? (char char char ... -> boolean)
"to determine whether a character precedes another") "Determines whether a character precedes another")
(char>? (char char char ... -> boolean) (char>? (char char char ... -> boolean)
"to determine whether a character succeeds another") "Determines whether a character succeeds another")
(char<=? (char char char ... -> boolean) (char<=? (char char char ... -> boolean)
"to determine whether a character precedes another" "Determines whether a character precedes another"
" (or is equal to it)") " (or is equal to it)")
(char>=? (char char char ... -> boolean) (char>=? (char char char ... -> boolean)
"to determine whether a character succeeds another" "Determines whether a character succeeds another"
" (or is equal to it)") " (or is equal to it)")
(char-ci=? (char char char ... -> boolean) (char-ci=? (char char char ... -> boolean)
"to determine whether two characters are equal" "Determines whether two characters are equal"
" in a case-insensitive manner") " in a case-insensitive manner")
(char-ci<? (char char char ... -> boolean) (char-ci<? (char char char ... -> boolean)
"to determine whether a character precedes another" "Determines whether a character precedes another"
" in a case-insensitive manner") " in a case-insensitive manner")
(char-ci>? (char char char ... -> boolean) (char-ci>? (char char char ... -> boolean)
"to determine whether a character succeeds another" "Determines whether a character succeeds another"
" in a case-insensitive manner") " in a case-insensitive manner")
(char-ci<=? (char char char ... -> boolean) (char-ci<=? (char char char ... -> boolean)
"to determine whether a character precedes another" "Determines whether a character precedes another"
" (or is equal to it) in a case-insensitive manner") " (or is equal to it) in a case-insensitive manner")
(char-ci>=? (char char char ... -> boolean) (char-ci>=? (char char char ... -> boolean)
"to determine whether a character succeeds another" "Determines whether a character succeeds another"
" (or is equal to it) in a case-insensitive manner") " (or is equal to it) in a case-insensitive manner")
(char-numeric? (char -> boolean) (char-numeric? (char -> boolean)
"to determine whether a character represents a digit") "Determines whether a character represents a digit")
(char-alphabetic? (char -> boolean) (char-alphabetic? (char -> boolean)
"to determine whether a character represents" "Determines whether a character represents"
" an alphabetic character") " an alphabetic character")
(char-whitespace? (char -> boolean) (char-whitespace? (char -> boolean)
"to determine whether a character represents space") "Determines whether a character represents space")
(char-upper-case? (char -> boolean) (char-upper-case? (char -> boolean)
"to determine whether a character is an" "Determines whether a character is an"
" upper-case character") " upper-case character")
(char-lower-case? (char -> boolean) (char-lower-case? (char -> boolean)
"to determine whether a character is a" "Determines whether a character is a"
" lower-case character") " lower-case character")
(char-upcase (char -> char) (char-upcase (char -> char)
"to determine the equivalent upper-case character") "Determines the equivalent upper-case character")
(char-downcase (char -> char) (char-downcase (char -> char)
"to determine the equivalent lower-case character") "Determines the equivalent lower-case character")
(char->integer (char -> integer) (char->integer (char -> integer)
"to lookup the number that corresponds to the" "Lookups the number that corresponds to the"
" given character in the ASCII table (if any)")) " given character in the ASCII table (if any)"))
("Strings" ("Strings"
(string? (any -> boolean) (string? (any -> boolean)
"to determine whether a value is a string") "Determines whether a value is a string")
(string-length (string -> nat) (string-length (string -> nat)
"to determine the length of a string") "Determines the length of a string")
((beginner-string-ith string-ith) (string nat -> string) ((beginner-string-ith string-ith) (string nat -> string)
"to extract the ith 1-letter substring from the given one") "Extracts the ith 1-letter substring from the given one")
((beginner-replicate replicate) (nat string -> string) ((beginner-replicate replicate) (nat string -> string)
"to replicate the given string") "Replicates the given string")
((beginner-int->string int->string) (integer -> string) ((beginner-int->string int->string) (integer -> string)
"to convert an integer in [0,55295] or [57344 1114111] to a 1-letter string") "Converts an integer in [0,55295] or [57344 1114111] to a 1-letter string")
((beginner-string->int string->int) (string -> integer) ((beginner-string->int string->int) (string -> integer)
"to convert a 1-letter string to an integer in [0,55295] or [57344, 1114111]") "Converts a 1-letter string to an integer in [0,55295] or [57344, 1114111]")
((beginner-explode explode) (string -> (listof string)) ((beginner-explode explode) (string -> (listof string))
"to translate a string into a list of 1-letter strings") "Translates a string into a list of 1-letter strings")
((beginner-implode implode) ((listof string) -> string) ((beginner-implode implode) ((listof string) -> string)
"to concatenate the list of 1-letter strings into one string") "Concatenates the list of 1-letter strings into one string")
((beginner-string-numeric? string-numeric?) (string -> boolean) ((beginner-string-numeric? string-numeric?) (string -> boolean)
"to determine whether all 'letters' in the string are numeric") "Determines whether all 'letters' in the string are numeric")
((beginner-string-alphabetic? string-alphabetic?) (string -> boolean) ((beginner-string-alphabetic? string-alphabetic?) (string -> boolean)
"to determine whether all 'letters' in the string are alphabetic") "Determines whether all 'letters' in the string are alphabetic")
((beginner-string-whitespace? string-whitespace?) (string -> boolean) ((beginner-string-whitespace? string-whitespace?) (string -> boolean)
"to determine whether all 'letters' in the string are white space") "Determines whether all 'letters' in the string are white space")
((beginner-string-upper-case? string-upper-case?) (string -> boolean) ((beginner-string-upper-case? string-upper-case?) (string -> boolean)
"to determine whether all 'letters' in the string are upper case") "Determines whether all 'letters' in the string are upper case")
((beginner-string-lower-case? string-lower-case?) (string -> boolean) ((beginner-string-lower-case? string-lower-case?) (string -> boolean)
"to determine whether all 'letters' in the string are lower case") "Determines whether all 'letters' in the string are lower case")
(string (char ... -> string) (string (char ... -> string)
"(string c1 c2 ...) builds a string") "(string c1 c2 ...) builds a string")
(make-string (nat char -> string) (make-string (nat char -> string)
"to produce a string of given length" "Produces a string of given length"
" from a single given character") " from a single given character")
(string-ref (string nat -> char) (string-ref (string nat -> char)
"to extract the i-the character from a string") "Extracts the i-the character from a string")
(substring (string nat nat -> string) (substring (string nat nat -> string)
"to extract the substring starting at a 0-based index" "Extracts the substring starting at a 0-based index"
" up to the second 0-based index (exclusive)") " up to the second 0-based index (exclusive)")
(string-copy (string -> string) (string-copy (string -> string)
"to copy a string") "Copies a string")
(string-append (string ... -> string) (string-append (string ... -> string)
"to juxtapose the characters of several strings") "Juxtaposes the characters of several strings")
(string=? (string string string ... -> boolean) (string=? (string string string ... -> boolean)
"to compare two strings character-wise") "Compares two strings character-wise")
(string<? (string string string ... -> boolean) (string<? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" precedes another") " precedes another")
(string>? (string string string ... -> boolean) (string>? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" succeeds another") " succeeds another")
(string<=? (string string string ... -> boolean) (string<=? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" precedes another (or is equal to it)") " precedes another (or is equal to it)")
(string>=? (string string string ... -> boolean) (string>=? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" succeeds another (or is equal to it)") " succeeds another (or is equal to it)")
(string-ci=? (string string string ... -> boolean) (string-ci=? (string string string ... -> boolean)
"to compare two strings character-wise" "Compares two strings character-wise"
" in a case-insensitive manner") " in a case-insensitive manner")
(string-ci<? (string string string ... -> boolean) (string-ci<? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" precedes another in a case-insensitive manner") " precedes another in a case-insensitive manner")
(string-ci>? (string string string ... -> boolean) (string-ci>? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" succeeds another in a case-insensitive manner") " succeeds another in a case-insensitive manner")
(string-ci<=? (string string string ... -> boolean) (string-ci<=? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" precedes another (or is equal to it)" " precedes another (or is equal to it)"
" in a case-insensitive manner") " in a case-insensitive manner")
(string-ci>=? (string string string ... -> boolean) (string-ci>=? (string string string ... -> boolean)
"to determine whether one string alphabetically" "Determines whether one string alphabetically"
" succeeds another (or is equal to it)" " succeeds another (or is equal to it)"
" in a case-insensitive manner") " in a case-insensitive manner")
(string->symbol (string -> symbol) (string->symbol (string -> symbol)
"to convert a string into a symbol") "Converts a string into a symbol")
(string->number (string -> (union number false)) (string->number (string -> (union number false))
"to convert a string into a number," "Converts a string into a number,"
" produce false if impossible") " produce false if impossible")
(string->list (string -> (listof char)) (string->list (string -> (listof char))
"to convert a string into a list of characters") "Converts a string into a list of characters")
(list->string ((listof char) -> string) (list->string ((listof char) -> string)
"to convert a s list of characters into a string") "Converts a s list of characters into a string")
(format (string any ... -> string) (format (string any ... -> string)
"to format a string, possibly embedding values")) "Formats a string, possibly embedding values"))
("Images" ("Images"
(image? (any -> boolean) (image? (any -> boolean)
"to determine whether a value is an image") "Determines whether a value is an image")
(image=? (image image -> boolean) (image=? (image image -> boolean)
"to determine whether two images are equal")) "Determines whether two images are equal"))
("Misc" ("Misc"
(identity (any -> any) (identity (any -> any)
"to return the argument unchanged") "Returns the argument unchanged")
((beginner-error error) (any ... -> void) "to signal an error, combining the given values into an error message.\n\nIf any of the values' printed representations is too long, it is truncated and ``...'' is put into the string. If the first value is a symbol, it is treated specially; it is suffixed with a colon and a space (the intention is that the symbol is the name of the function signalling the error).") ((beginner-error error) (any ... -> void) "signals an error, combining the given values into an error message.\n\nIf any of the values' printed representations is too long, it is truncated and ``...'' is put into the string. If the first value is a symbol, it is treated specially; it is suffixed with a colon and a space (the intention is that the symbol is the name of the function signalling the error).")
((beginner-struct? struct?) (any -> boolean) ((beginner-struct? struct?) (any -> boolean)
"to determine whether some value is a structure") "Determines whether some value is a structure")
((beginner-equal? equal?) (any any -> boolean) ((beginner-equal? equal?) (any any -> boolean)
"to determine whether two values are structurally equal" "Determines whether two values are structurally equal"
" where basic values are compared with the eqv? predicate") " where basic values are compared with the eqv? predicate")
(eq? (any any -> boolean) (eq? (any any -> boolean)
"to determine whether two values are equivalent from the" "Determines whether two values are equivalent from the"
" computer's perspective (intensional)") " computer's perspective (intensional)")
(eqv? (any any -> boolean) (eqv? (any any -> boolean)
"to determine whether two values are equivalent from the" "Determines whether two values are equivalent from the"
" perspective of all functions that can be applied to it (extensional)") " perspective of all functions that can be applied to it (extensional)")
((beginner-=~ =~) (number number non-negative-real -> boolean) ((beginner-=~ =~) (number number non-negative-real -> boolean)
"to check whether two numbers are within some amount (the third argument) of either other") "Checks whether two numbers are within some amount (the third argument) of either other")
((beginner-equal~? equal~?) (any any non-negative-real -> boolean) ((beginner-equal~? equal~?) (any any non-negative-real -> boolean)
"to compare like equal? on the first two arguments, except using =~ in the case of numbers") "Compares like equal? on the first two arguments, except using =~ in the case of numbers")
(eof eof (eof eof
"the end-of-file value") "The end-of-file value")
(eof-object? (any -> boolean) (eof-object? (any -> boolean)
"to determine whether some value is the end-of-file value") "Determines whether some value is the end-of-file value")
((beginner-exit exit) ( -> void) ((beginner-exit exit) ( -> void)
"to exit the running program")))) "Exits the running program"))))

View File

@ -11,23 +11,23 @@
("Numbers (relaxed conditions)" ("Numbers (relaxed conditions)"
(+ (number ... -> number) "to add all given numbers") (+ (number ... -> number) "Adds all given numbers")
(* (number ... -> number) "to multiply all given numbers") (* (number ... -> number) "Multiplys all given numbers")
(- (number ... -> number) "to subtract from the first all remaining numbers") (- (number ... -> number) "Subtracts from the first all remaining numbers")
(/ (number ... -> number) "to divide the first by all remaining numbers") (/ (number ... -> number) "Divides the first by all remaining numbers")
) )
("Lists" ("Lists"
((intermediate-append append) ((listof any) ... -> (listof any)) ((intermediate-append append) ((listof any) ... -> (listof any))
"to create a single list from several, by juxtaposition of the items")) "Creates a single list from several, by juxtaposition of the items"))
("Higher-Order Functions" ("Higher-Order Functions"
(map ((X ... -> Z) (listof X) ... -> (listof Z)) (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") "Constructs a new list by applying a function to each item on one or more existing lists")
(for-each ((any ... -> any) (listof any) ... -> void) (for-each ((any ... -> any) (listof any) ... -> void)
"to apply a function to each item on one or more lists for effect only") "Applies a function to each item on one or more lists for effect only")
((intermediate-filter filter) ((X -> boolean) (listof X) -> (listof X)) ((intermediate-filter filter) ((X -> boolean) (listof X) -> (listof X))
"to construct a list from all those items on a list for which the predicate holds") "Constructs a list from all those items on a list for which the predicate holds")
((intermediate-foldr foldr) ((X Y -> Y) Y (listof X) -> Y) ((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))") "(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) ((intermediate-foldl foldl) ((X Y -> Y) Y (listof X) -> Y)
@ -37,25 +37,25 @@
((intermediate-build-string build-string) (nat (nat -> char) -> string) ((intermediate-build-string build-string) (nat (nat -> char) -> string)
"(build-string n f) = (string (f 0) ... (f (- n 1)))") "(build-string n f) = (string (f 0) ... (f (- n 1)))")
((intermediate-quicksort quicksort) ((listof X) (X X -> boolean) -> (listof X)) ((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") "Constructs a list from all items on a list in an order according to a predicate")
((intermediate-sort sort) ((listof X) (X X -> boolean) -> (listof X)) ((intermediate-sort sort) ((listof X) (X X -> boolean) -> (listof X))
"to construct a list from all items on a list in an order according to a predicate") "Constructs a list from all items on a list in an order according to a predicate")
((intermediate-andmap andmap) ((X -> boolean) (listof X) -> boolean) ((intermediate-andmap andmap) ((X -> boolean) (listof X) -> boolean)
"(andmap p (list x-1 ... x-n)) = (and (p x-1) ... (p x-n))") "(andmap p (list x-1 ... x-n)) = (and (p x-1) ... (p x-n))")
((intermediate-ormap ormap) ((X -> boolean) (listof X) -> boolean) ((intermediate-ormap ormap) ((X -> boolean) (listof X) -> boolean)
"(ormap p (list x-1 ... x-n)) = (or (p x-1) ... (p x-n))") "(ormap p (list x-1 ... x-n)) = (or (p x-1) ... (p x-n))")
(argmin ((X -> real) (listof X) -> X) (argmin ((X -> real) (listof X) -> X)
"to find the (first) element of the list that minimizes the output of the function") "Finds the (first) element of the list that minimizes the output of the function")
(argmax ((X -> real) (listof X) -> X) (argmax ((X -> real) (listof X) -> X)
"to find the (first) element of the list that maximizes the output of the function") "Finds the (first) element of the list that maximizes the output of the function")
(memf ((X -> any) (listof X) -> (union false (listof X))) (memf ((X -> any) (listof X) -> (union false (listof X)))
"to determine whether the first argument produces a non-false value for any item in the second argument") "Determines whether the first argument produces a non-false value for any item in the second argument")
(apply ((X-1 ... X-N -> Y) X-1 ... X-i (list X-i+1 ... X-N) -> Y) (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") "Applies 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)) (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") "Composes a sequence of procedures into a single procedure")
(procedure? (any -> boolean) (procedure? (any -> boolean)
"to determine if a value is a procedure")))) "Determines if a value is a procedure"))))

View File

@ -2,102 +2,63 @@
@(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt" @(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt"
(for-label lang/htdp-advanced)) (for-label lang/htdp-advanced))
@(define-syntax-rule (bdl intm-define intm-lambda)
(begin
(require (for-label lang/htdp-intermediate-lambda))
(define intm-define @racket[define])
(define intm-lambda @racket[lambda])))
@(bdl intm-define intm-lambda)
@(define-syntax-rule (bd intm-define-struct intm-local intm-letrec intm-let intm-let* intm-time)
(begin
(require (for-label lang/htdp-intermediate))
(define intm-define @racket[define])
(define intm-define-struct @racket[define-struct])
(define intm-local @racket[local])
(define intm-letrec @racket[letrec])
(define intm-let @racket[let])
(define intm-let* @racket[let*])
(define intm-time @racket[time])))
@(bd intm-define-struct intm-local intm-letrec intm-let intm-let* intm-time)
@(define-syntax-rule (bbd 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 @racket[define])
(define beg-define-struct @racket[define-struct])
(define beg-cond @racket[cond])
(define beg-if @racket[if])
(define beg-and @racket[and])
(define beg-or @racket[or])
(define beg-check-expect @racket[check-expect])
(define beg-require @racket[require])))
@(bbd beg-define beg-define-struct beg-cond beg-if beg-and beg-or beg-check-expect beg-require)
@title[#:style 'toc #:tag "advanced"]{Advanced Student} @title[#:style 'toc #:tag "advanced"]{Advanced Student}
@declare-exporting[lang/htdp-advanced] @declare-exporting[lang/htdp-advanced]
@racketgrammar*+qq[ @racketgrammar*+qq[
#:literals (define define-struct define-datatype lambda λ cond else if and or empty true false require lib planet #:literals (define define-struct define-datatype lambda λ cond else if and or require lib planet
local let let* letrec time begin begin0 set! delay shared recur when case match unless local let let* letrec time begin begin0 set! delay shared recur when case match unless
; match ; match
_ cons list list* struct vector box _ cons list list* struct vector box
check-expect check-within check-error) check-expect check-within check-member-of check-range check-error)
(check-expect check-within check-error require) (check-expect check-within check-error check-member-of check-range require)
[program (code:line def-or-expr ...)] [program (code:line def-or-expr ...)]
[def-or-expr definition [def-or-expr definition
expr expression
test-case test-case
library-require] library-require]
[definition (define (id id id ...) expr) [definition (define (name variable ...) expression)
(define id expr) (define name expression)
(define-struct id (id ...)) (define-struct name (name ...))
(define-datatype id (id id ...) ...)] (define-datatype name (name name ...) ...)]
[expr (begin expr expr ...) [expression (begin expression expression ...)
(begin0 expr expr ...) (begin0 expression expression ...)
(set! id expr) (set! variable expression)
(delay expr) (delay expression)
(lambda (id ...) expr) (lambda (variable ...) expression)
(λ (id ...) expr) (λ (variable ...) expression)
(local [definition ...] expr) (local [definition ...] expression)
(letrec ([id expr] ...) expr) (letrec ([name expression] ...) expression)
(shared ([id expr] ...) expr) (shared ([name expression] ...) expression)
(let ([id expr] ...) expr) (let ([name expression] ...) expression)
(let id ([id expr] ...) expr) (let name ([name expression] ...) expression)
(let* ([id expr] ...) expr) (let* ([name expression] ...) expression)
(recur id ([id expr] ...) expr) (recur name ([name expression] ...) expression)
(code:line (expr expr ...) (code:comment @#,seclink["advanced-call"]{function call})) (code:line (expression expression ...))
(cond [expr expr] ... [expr expr]) (cond [expression expression] ... [expression expression])
(cond [expr expr] ... [else expr]) (cond [expression expression] ... [else expression])
(case expr [(choice choice ...) expr] ... (case expression [(choice choice ...) expression] ...
[(choice choice ...) expr]) [(choice choice ...) expression])
(case expr [(choice choice ...) expr] ... (case expression [(choice choice ...) expression] ...
[else expr]) [else expression])
(match expr [pattern expr] ...) (match expression [pattern expression] ...)
(if expr expr expr) (if expression expression expression)
(when expr expr) (when expression expression)
(unless expr expr) (unless expression expression)
(and expr expr expr ...) (and expression expression expression ...)
(or expr expr expr ...) (or expression expression expression ...)
(time expr) (time expression)
empty (code:line name)
(code:line id (code:comment @#,seclink["intermediate-id"]{identifier})) (code:line @#,elem{@racketvalfont{'}@racket[_quoted]})
(code:line prim-op (code:comment @#,seclink["advanced-prim-ops"]{primitive operation})) (code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]})
(code:line @#,elem{@racketvalfont{'}@racket[_quoted]} (code:comment @#,seclink["beginner-abbr-quote"]{quoted value}))
(code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]} (code:comment @#,seclink["beginner-abbr-quasiquote"]{quasiquote}))
number number
true
false
string string
character] character]
[choice (code:line id (code:comment @#,t{treated as a symbol})) [choice (code:line name)
number] number]
[pattern _ [pattern _
empty name
id
number number
true true
false false
@ -111,7 +72,7 @@
(struct id (pattern ...)) (struct id (pattern ...))
(vector pattern ...) (vector pattern ...)
(box pattern)] (box pattern)]
[quasiquoted-pattern id [quasiquoted-pattern name
number number
string string
character character
@ -122,310 +83,239 @@
@#,elem{@racketfont[",@"]@racket[_pattern]}] @#,elem{@racketfont[",@"]@racket[_pattern]}]
] ]
@|prim-nonterms|
@prim-ops['(lib "htdp-advanced.rkt" "lang") #'here] @prim-nonterms[("advanced") define define-struct]
@prim-variables[("advanced") empty true false]
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "advanced-syntax"]{Syntax for Advanced}
@section[#:tag "advanced-define"]{@racket[define]} In Advanced, @racket[define] and @racket[lambda] can define functions of zero
arguments, and (naturally) function calls can invoke functions of zero arguments.
@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 @defform[(lambda (variable ...) expression)]{
function is allowed to accept zero arguments.}
@; ---------------------------------------------------------------------- Creates a function that takes as many arguments as given @racket[variables]s,
and whose body is @racket[expression].}
@section[#:tag "advanced-define-struct"]{@racket[define-struct]} @defform[(λ (variable ...) expression)]{
@defform[(define-struct structid (fieldid ...))]{ The Greek letter @racket[λ] is a synonym for @racket[lambda].}
The same as Intermediate's @|intm-define-struct|, but defines an
additional set of operations:
@defform/none[(expression expression ...)]{
Calls the function that results from evaluating the first
@racket[expression]. The value of the call is the value of function's body when
every instance of @racket[name]'s variables are replaced by the values of the
corresponding @racket[expression]s.
The function being called must come from either a definition appearing before the
function call, or from a @racket[lambda] expression. The number of argument
@racket[expression]s must be the same as the number of arguments expected by
the function.}
In Advanced, @racket[define-struct] introduces one additional function:
@itemize[ @itemize[
@item{@racketidfont{set-}@racket[structid]@racketidfont{-}@racket[fieldid]@racketidfont{!} @item{@racketidfont{set-}@racket[structure-name]@racketidfont{-}@racket[field-name]@racketidfont{!}
: takes an instance of the structure and a value, and changes : takes an instance of the structure and a value, and changes
the instance's field to the given value.} the instance's field to the given value.}
]} ]}
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "advanced-define-datatype"]{@racket[define-datatype]}
@defform[(define-datatype datatypeid [variantid fieldid ...] ...)]{ @defform[(define-datatype dataype-name [variant-name field-name ...] ...)]{
A short-hand for defining a group of related structures. The following @racket[define-datatype]:
A short-hand for defining a group of related structures. A @racket[define-datatype] form
@racketblock[ @racketblock[
(define-datatype datatypeid (define-datatype datatype-name
[variantid fieldid (unsyntax @racketidfont{...})] [variant-name field-name (unsyntax @racketidfont{...})]
(unsyntax @racketidfont{...})) (unsyntax @racketidfont{...}))
] ]
is equivalent to is equivalent to:
@racketblock[ @racketblock[
(define ((unsyntax @racket[datatypeid])? x) (define ((unsyntax @racket[datatype-name])? x)
(or ((unsyntax @racket[variantid])? x) (unsyntax @racketidfont{...}))) (or ((unsyntax @racket[variant-name])? x) (unsyntax @racketidfont{...})))
(define-struct variantid (fieldid (unsyntax @racketidfont{...}))) (define-struct variant-name (field-name (unsyntax @racketidfont{...})))
(unsyntax @racketidfont{...}) (unsyntax @racketidfont{...})
]} ]}
@; ----------------------------------------------------------------------
@section[#:tag "advanced-lambda"]{@racket[lambda]}
@deftogether[( @defform[(begin expression expression ...)]{
@defform[(lambda (id ...) expr)]
@defform[(λ (id ...) expr)]
)]{
The same as Intermediate with Lambda's @|intm-lambda|, except that a Evaluates the @racket[expression]s in order from left to right. The value of
function is allowed to accept zero arguments.} the @racket[begin] expression is the value of the last @racket[expression].}
@; ----------------------------------------------------------------------
@section[#:tag "advanced-call"]{Function Calls}
@defform/none[(expr expr ...)]{ @defform[(begin0 expression expression ...)]{
A function call in Advanced is the same as an Intermediate with Lambda Evaluates the @racket[expression]s in order from left to right. The value of
@seclink["intermediate-lambda-call"]{function call}, except that zero the @racket[begin] expression is the value of the first @racket[expression].}
arguments are allowed.}
@defform[(#%app expr expr ...)]{
A function call can be written with @racket[#%app], though it's
practically never written that way.}
@; ---------------------------------------------------------------------- @defform[(set! variable expression)]{
@section{@racket[begin]} Evaluates @racket[expression], and then changes the definition @racket[variable]
to have @racket[expression]'s value. The @racket[variable] must be defined or
bound by @racket[define], @racket[letrec], @racket[let*], or @racket[let].}
@defform[(begin expr expr ...)]{
Evaluates the @racket[expr]s in order from left to right. The value of @defform[(delay expression)]{
the @racket[begin] expression is the value of the last @racket[expr].}
@; ---------------------------------------------------------------------- Produces a ``promise'' to evaluate @racket[expression]. The @racket[expression]
is not evaluated until the promise is forced with @racket[force]; when
the promise is forced, the result is recorded, so that any further
@racket[force] of the promise immediately produces the remembered value.}
@section{@racket[begin0]}
@defform[(begin0 expr expr ...)]{
Evaluates the @racket[expr]s in order from left to right. The value of @defform[(shared ([name expression] ...) expression)]{
the @racket[begin] expression is the value of the first @racket[expr].}
@; ---------------------------------------------------------------------- Like @racket[letrec], but when an @racket[expression] next to an @racket[id]
@section{@racket[set!]}
@defform[(set! id expr)]{
Evaluates @racket[expr], and then changes the definition @racket[id]
to have @racket[expr]'s value. The @racket[id] must be defined or
bound by @racket[letrec], @racket[let], or @racket[let*].}
@; ----------------------------------------------------------------------
@section{@racket[delay]}
@defform[(delay expr)]{
Produces a ``promise'' to evaluate @racket[expr]. The @racket[expr] is
not evaluated until the promise is forced through the @racket[force]
operator; when the promise is forced, the result is recorded, so that
any further @racket[force] of the promise always produces the
remembered value.}
@; ----------------------------------------------------------------------
@section{@racket[shared]}
@defform[(shared ([id expr] ...) expr)]{
Like @racket[letrec], but when an @racket[expr] next to an @racket[id]
is a @racket[cons], @racket[list], @racket[vector], quasiquoted is a @racket[cons], @racket[list], @racket[vector], quasiquoted
expression, or @racketidfont{make-}@racket[_structid] from a expression, or @racketidfont{make-}@racket[_struct-name] from a
@racket[define-struct], the @racket[expr] can refer directly to any @racket[define-struct], the @racket[expression] can refer directly to any
@racket[id], not just @racket[id]s defined earlier. Thus, @racket[name], not just @racket[name]s defined earlier. Thus,
@racket[shared] can be used to create cyclic data structures.} @racket[shared] can be used to create cyclic data structures.}
@; ----------------------------------------------------------------------
@section[#:tag "advanced-let"]{@racket[let]}
@defform*[[(let ([id expr] ...) expr)
(let id ([id expr] ...) expr)]]{
The first form of @racket[let] is the same as Intermediate's
@|intm-let|.
The second form is equivalent to a @racket[recur] form.}
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section{@racket[recur]}
@defform[(recur id ([id expr] ...) expr)]{ @defform[(recur name ([name expression] ...) expression)]{
A short-hand recursion construct. The first @racket[id] corresponds to A short-hand syntax for recursive loops. The first @racket[name] corresponds to
the name of the recursive function. The parenthesized @racket[id]s are the name of the recursive function. The @racket[name]s in the parenthesis are
the function's arguments, and each corresponding @racket[expr] is a the function's arguments, and each corresponding @racket[expression] is a
value supplied for that argument in an initial starting call of the value supplied for that argument in an initial starting call of the
function. The last @racket[expr] is the body of the function. function. The last @racket[expression] is the body of the function.
More precisely, a @racket[recur] form More precisely, the following @racket[recur]:
@racketblock[ @racketblock[
(recur func-id ([arg-id arg-expr] (unsyntax @racketidfont{...})) (recur func-name ([arg-name arg-expression] (unsyntax @racketidfont{...}))
body-expr) body-expression)
] ]
is equivalent to is equivalent to:
@racketblock[ @racketblock[
((local [(define (func-id arg-id (unsyntax @racketidfont{...})) (local [(define (func-name arg-name (unsyntax @racketidfont{...})) body-expression)]
body-expr)] (func-name arg-expression (unsyntax @racketidfont{...})))
func-id)
arg-expr (unsyntax @racketidfont{...}))
]} ]}
@; ----------------------------------------------------------------------
@section{@racket[case]} @defform/none[(let name ([name expression] ...) expression)]{
@defform[(case expr [(choice ...) expr] ... [(choice ...) expr])]{ An alternate syntax for @racket[recur].}
A @racket[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
@racket[expr]. The initial @racket[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 @racket[expr] whose value is the result of
the whole @racket[case] expression. If none of the lines contains a
matching choice, it is an error.}
@defform/none[#:literals (case else)
(case expr [(choice ...) expr] ... [else expr])]{
This form of @racket[case] is similar to the prior one, except that
the final @racket[else] clause is always taken if no prior line
contains a choice matching the value of the initial @racket[expr]. In
other words, so there is no possibility to ``fall off the end'' of
the @racket[case] form.}
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section{@racket[match]}
@defform[(match expr [pattern expr] ...)]{ @defform[(case expression [(choice ...) expression] ... [(choice ...) expression])]{
A @racket[match] form contains one or more ``lines'' that are A @racket[case] form contains one or more clauses. Each clause contains a
surrounded by parentheses or square brackets. Each line contains a choices (in parentheses)---either numbers or names---and an answer
pattern---a description of a value---and an answer @racket[expr]. @racket[expression]. The initial @racket[expression] is evaluated, and its
The initial @racket[expr] is evaluated, and the resulting value value is compared to the choices in each clause, where the lines are considered
is matched against the pattern in each line, where the lines are in order. The first line that contains a matching choice provides an answer
considered in order. The first line that contains a matching pattern @racket[expression] whose value is the result of the whole @racket[case]
provides an answer @racket[expr] whose value is the result of the expression. Numbers match with the numbers in the choices, and symbols match
whole @racket[match] expression. This @racket[expr] may reference with the names. If none of the lines contains a matching choice, it is an
identifiers bound in the matching pattern. If none of the lines
contains a matching pattern, it is an error.}
@; ----------------------------------------------------------------------
@section{@racket[when] and @racket[unless]}
@defform[(when expr expr)]{
The first @racket[expr] (known as the ``test'' expression) is
evaluated. If it evaluates to @racket[true], the result of the
@racket[when] expression is the result of evaluating the second
@racket[expr], otherwise the result is @racket[(void)] and the second
@racket[expr] is not evaluated. If the result of evaluating the test
@racket[expr] is neither @racket[true] nor @racket[false], it is an
error.} error.}
@defform[(unless expr expr)]{ @defform/none[#:literals (case else)
(case expression [(choice ...) expression] ... [else expression])]{
Like @racket[when], but the second @racket[expr] is evaluated when the This form of @racket[case] is similar to the prior one, except that the final
first @racket[expr] produces @racket[false] instead of @racket[true].} @racket[else] clause is taken if no clause contains a choice matching the value
of the initial @racket[expression].}
@; ----------------------------------------------------------------------
@defform[(match expression [pattern expression] ...)]{
A @racket[match] form contains one or more clauses that are surrounded by
square brackets. Each clause contains a pattern---a description of a value---and
an answer @racket[expression]. The initial @racket[expression] is evaluated,
and its value is matched against the pattern in each clause, where the clauses are
considered in order. The first clause that contains a matching pattern provides
an answer @racket[expression] whose value is the result of the whole
@racket[match] expression. This @racket[expression] may reference identifiers
bound in the matching pattern. If none of the clauses contains a matching
pattern, it is an error.}
@; ----------------------------------------------------------------------
@defform[(when test-expression body-expression)]{
If @racket[test-expression] evaluates to @racket[true], the result of the
@racket[when] expression is the result of evaluating the
@racket[body-expression], otherwise the result is @racket[(void)] and the
@racket[body-expression] is not evaluated. If the result of evaluating the
@racket[test-expression] is neither @racket[true] nor @racket[false], it is an
error.}
@defform[(unless test-expression body-expression)]{
Like @racket[when], but the @racket[body-expression] is evaluated when the
@racket[test-expression] produces @racket[false] instead of @racket[true].}
@section[#:tag "advanced-common-syntax"]{Common Syntax}
@(intermediate-forms lambda
quote
quasiquote
unquote
unquote-splicing
local
letrec
let*
let
time)
@(define-forms/normal define)
@(prim-forms ("advanced")
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require)
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "advanced-prim-ops"]{Primitive Operations} @section[#:tag "advanced-pre-defined"]{Pre-Defined Functions}
@prim-op-defns['(lib "htdp-advanced.rkt" "lang") #'here '()] @prim-op-defns['(lib "htdp-advanced.ss" "lang") #'here '()]
@; ----------------------------------------------------------------------
@section[#:tag "advanced-unchanged"]{Unchanged Forms}
@deftogether[(
@defform[(local [definition ...] expr)]
@defform[(letrec ([id expr-for-let] ...) expr)]
@defform[(let* ([id expr-for-let] ...) expr)]
)]{
The same as Intermediate's @|intm-local|, @|intm-letrec|, and
@|intm-let*|.}
@deftogether[(
@defform[(cond [expr expr] ... [expr expr])]
@defidform[else]
)]{
The same as Beginning's @|beg-cond|, except that @racket[else] can be
used with @racket[case].}
@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|.}
@defform[(time expr)]{
The same as Intermediate's @|intm-time|.}
@deftogether[(
@defform[(check-expect expr expr)]
@defform[(check-within expr expr expr)]
@defform*[[(check-error expr expr)
(check-error expr)]]
@defform[(check-member-of expr expr expr ...)]
@defform[(check-range expr 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 module-path)]{
The same as Beginning's @|beg-require|.}

View File

@ -2,18 +2,6 @@
@(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt" @(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt"
(for-label lang/htdp-beginner-abbr)) (for-label lang/htdp-beginner-abbr))
@(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 @racket[define])
(define beg-define-struct @racket[define-struct])
(define beg-cond @racket[cond])
(define beg-if @racket[if])
(define beg-and @racket[and])
(define beg-or @racket[or])
(define beg-check-expect @racket[check-expect])
(define beg-require @racket[require])))
@(bd beg-define beg-define-struct beg-cond beg-if beg-and beg-or beg-check-expect beg-require)
@title[#:style 'toc #:tag "beginner-abbr"]{Beginning Student with List Abbreviations} @title[#:style 'toc #:tag "beginner-abbr"]{Beginning Student with List Abbreviations}
@ -21,96 +9,94 @@
@declare-exporting[lang/htdp-beginner-abbr] @declare-exporting[lang/htdp-beginner-abbr]
@racketgrammar*+qq[ @racketgrammar*+qq[
#:literals (define define-struct lambda cond else if and or empty true false require lib planet #:literals (define define-struct lambda cond else if and or require lib planet
check-expect check-within check-error) check-expect check-within check-error)
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
[program (code:line def-or-expr ...)] [program (code:line def-or-expr ...)]
[def-or-expr definition [def-or-expr definition
expr expression
test-case test-case
library-require] library-require]
[definition (define (id id id ...) expr) [definition (define (name variable variable ...) expression)
(define id expr) (define name expression)
(define id (lambda (id id ...) expr)) (define name (lambda (variable variable ...) expression))
(define-struct id (id ...))] (define-struct name (name ...))]
[expr (code:line (id expr expr ...) (code:comment @#,seclink["beginner-call"]{function call})) [expression (code:line (name expression expression ...))
(code:line (prim-op expr ...) (code:comment @#,seclink["beginner-prim-call"]{primitive operation call})) (code:line (prim-op expression ...))
(cond [expr expr] ... [expr expr]) (cond [expression expression] ... [expression expression])
(cond [expr expr] ... [else expr]) (cond [expression expression] ... [else expression])
(if expr expr expr) (if expression expression expression)
(and expr expr expr ...) (and expression expression expression ...)
(or expr expr expr ...) (or expression expression expression ...)
empty name
id (code:line @#,elem{@racketvalfont{'}@racket[_quoted]})
(code:line @#,elem{@racketvalfont{'}@racket[_quoted]} (code:comment @#,seclink["beginner-abbr-quote"]{quoted value})) (code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]})
(code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]} (code:comment @#,seclink["beginner-abbr-quasiquote"]{quasiquote}))
number number
true
false
string string
character] character]
] ]
@|prim-nonterms| @prim-nonterms[("beginner-abbr") define define-struct]
@prim-ops['(lib "htdp-beginner-abbr.rkt" "lang") #'here] @prim-variables[("beginner-abbr") empty true false]
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "beginner-abbr-quote"]{Quote} @section[#:tag "beginner-abbr-syntax"]{Syntax for Abbreviations}
@deftogether[( @deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{'}@racket[quoted]})] @defform/none[(unsyntax @elem{@racketvalfont{'}@racket[name]})]
@defform[(quote quoted)] @defform/none[(unsyntax @elem{@racketvalfont{'}@racket[part]})]
@defform[(quote name)]
@defform/none[(quote part)]
)]{ )]{
Creates symbols and abbreviates nested lists. A quoted name is a symbol. A quote part is an abbreviation for a nested lists.
Normally, this form is written with a @litchar{'}, like Normally, this quotation is written with a @litchar{'}, like
@racket['(apple banana)], but it can also be written with @racket[quote], like @racket['(apple banana)], but it can also be written with @racket[quote], like
@racket[(@#,racket[quote] (apple banana))].} @racket[(@#,racket[quote] (apple banana))].}
@; ----------------------------------------
@section[#:tag "beginner-abbr-quasiquote"]{Quasiquote}
@deftogether[( @deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{`}@racket[quasiquoted]})] @defform/none[(unsyntax @elem{@racketvalfont{`}@racket[name]})]
@defform[(quasiquote quasiquoted)] @defform/none[(unsyntax @elem{@racketvalfont{`}@racket[part]})]
@defform[(quasiquote name)]
@defform/none[(quasiquote part)]
)]{ )]{
Creates symbols and abbreviates nested lists, but also allows escaping Like @racket[quote], but also allows escaping to expression ``unquotes.''
to expression ``unquotes.''
Normally, this form is written with a backquote, @litchar{`}, like Normally, quasi-quotations are written with a backquote, @litchar{`}, like
@racket[`(apple ,(+ 1 2))], but it can also be written with @racket[`(apple ,(+ 1 2))], but they can also be written with
@racket[quasiquote], like @racket[quasiquote], like
@racket[(@#,racket[quasiquote] (apple ,(+ 1 2)))].} @racket[(@#,racket[quasiquote] (apple ,(+ 1 2)))].}
@deftogether[( @deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{,}@racket[quasiquoted]})] @defform/none[(unsyntax @elem{@racketvalfont{,}@racket[expression]})]
@defform[(unquote expr)] @defform[(unquote expression)]
)]{ )]{
Under a single quasiquote, @racketfont{,}@racket[expr] escapes from Under a single quasiquote, @racketfont{,}@racket[expression] escapes from
the quote to include an evaluated expression whose result is inserted the quote to include an evaluated expression whose value is inserted
into the abbreviated list. into the abbreviated list.
Under multiple quasiquotes, @racketfont{,}@racket[expr] is really Under multiple quasiquotes, @racketfont{,}@racket[expression] is really
@racketfont{,}@racket[quasiquoted], decrementing the quasiquote count the literal @racketfont{,}@racket[expression], decrementing the quasiquote count
by one for @racket[quasiquoted]. by one for @racket[expression].
Normally, an unquote is written with @litchar{,}, but it can also be Normally, an unquote is written with @litchar{,}, but it can also be
written with @racket[unquote].} written with @racket[unquote].}
@deftogether[( @deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont[",@"]@racket[quasiquoted]})] @defform/none[(unsyntax @elem{@racketvalfont[",@"]@racket[expression]})]
@defform[(unquote-splicing expr)] @defform[(unquote-splicing expression)]
)]{ )]{
Under a single quasiquote, @racketfont[",@"]@racket[expr] escapes from Under a single quasiquote, @racketfont[",@"]@racket[expression] escapes from
the quote to include an evaluated expression whose result is a list to the quote to include an evaluated expression whose result is a list to
splice into the abbreviated list. splice into the abbreviated list.
@ -121,70 +107,34 @@ Normally, a splicing unquote is written with @litchar{,}, but it can
also be written with @racket[unquote-splicing].} also be written with @racket[unquote-splicing].}
@; ----------------------------------------------------------------------
@section[#:tag "beginner-abbr-common-syntax"]{Common Syntax}
@(define-forms/normal define)
@(define-form/explicit-lambda define lambda)
@prim-forms[("beginner-abbr")
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require]
@; ---------------------------------------- @; ----------------------------------------
@section[#:tag "beginner-abbr-prim-ops"]{Primitive Operations} @section[#:tag "beginner-abbr-pre-defined"]{Pre-defined Functions}
@prim-op-defns['(lib "htdp-beginner-abbr.rkt" "lang") #'here '()] @prim-op-defns['(lib "htdp-beginner-abbr.ss" "lang") #'here '()]
@; ----------------------------------------------------------------------
@section{Unchanged Forms}
@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))]
@defidform[lambda]
)]{
The same as Beginning's @|beg-define|.}
@defform[(define-struct structid (fieldid ...))]{
The same as Beginning's @|beg-define-struct|.}
@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)
(check-error expr)]]
@defform[(check-member-of expr expr expr ...)]
@defform[(check-range expr 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 module-path)]{
The same as Beginning's @|beg-require|.}

View File

@ -8,373 +8,65 @@
@declare-exporting[lang/htdp-beginner #:use-sources (lang/htdp-beginner lang/private/teachprims)] @declare-exporting[lang/htdp-beginner #:use-sources (lang/htdp-beginner lang/private/teachprims)]
@racketgrammar*+library[ @racketgrammar*+library[
#:literals (define define-struct lambda cond else if and or empty true false require lib planet #:literals (define define-struct lambda cond else if and or require lib planet
check-expect check-within check-error) check-expect check-within check-error)
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
[program (code:line def-or-expr ...)] [program (code:line def-or-expr ...)]
[def-or-expr definition [def-or-expr definition
expr expression
test-case test-case
library-require] library-require]
[definition (define (id id id ...) expr) [definition (define (name variable variable ...) expression)
(define id expr) (define name expression)
(define id (lambda (id id ...) expr)) (define name (lambda (variable variable ...) expression))
(define-struct id (id ...))] (define-struct name (name ...))]
[expr (code:line (id expr expr ...) (code:comment @#,seclink["beginner-call"]{function call})) [expression (code:line (name expression expression ...))
(code:line (prim-op expr ...) (code:comment @#,seclink["beginner-prim-call"]{primitive operation call})) (cond [expression expression] ... [expression expression])
(cond [expr expr] ... [expr expr]) (cond [expression expression] ... [else expression])
(cond [expr expr] ... [else expr]) (if expression expression expression)
(if expr expr expr) (and expression expression expression ...)
(and expr expr expr ...) (or expression expression expression ...)
(or expr expr expr ...) name
empty (code:line @#,elem{@racketvalfont{'}@racket[name]})
id
(code:line id (code:comment @#,seclink["beginner-id"]{identifier}))
(code:line @#,elem{@racketvalfont{'}@racket[id]} (code:comment @#,seclink["beginner-quote"]{symbol}))
number number
true
false
string string
character] character]
] ]
@|prim-nonterms| @prim-nonterms[("beginner") define define-struct]
@prim-ops['(lib "htdp-beginner.rkt" "lang") #'here] @prim-variables[("beginner") empty true false]
@section[#:tag "beginner-syntax"]{Syntax}
@; ----------------------------------------------------------------------
@section{@racket[define]}
@defform[(define (id id id ...) expr)]{
Defines a function. The first @racket[id] inside the parentheses is
the name of the function. All remaining @racket[id]s are the names of
the function's arguments. The @racket[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 @racket[id] as a synonym for the value produced by
@racket[expr]. The defined name cannot be that of a primitive or
another definition, and @racket[id] itself must not appear in
@racket[expr].}
@defform/none[#:literals (define lambda)
(define id (lambda (id id ...) expr))]{
An alternate form for defining functions. The first @racket[id] is the
name of the function. The @racket[id]s in parentheses are the names of
the function's arguments, and the @racket[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 @racket[lambda] keyword can only be used with @racket[define] in
the alternative function-definition syntax.}
@; ----------------------------------------------------------------------
@section{@racket[define-struct]}
@defform[(define-struct structid (fieldid ...))]{
Define a new type of structure. The structure's fields are named by
the @racket[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{@racketidfont{make-}@racket[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{@racket[structid]@racketidfont{-}@racket[fieldid] : takes an
instance of the structure and returns the field named by
@racket[structid].}
@item{@racket[structid]@racketidfont{?} : takes any value, and returns
@racket[true] if the value is an instance of the structure type.}
@item{@racket[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.}
@; ----------------------------------------------------------------------
@;{ ------- COMMENTED OUT FOR NOW ---------
@section{@racket[define-wish]}
@defform[(define-wish id)]{
Defines a function named @racket[id] that we wish exists but have not implemented yet.
The name of the function cannot be that of a primitive or another definition.
The wished-for function can be called with one argument: @racket[(id _expr)].
Wished-for functions are reported in the test report for the current program.}
@defform/none[#:literals (define-wish)
(define-wish id expr)]{
Similar to the above form, defines a wished-for function named @racket[id]. If the
wished-for function is called with one value, the result of @racket[expr] is
returned as the default value. }
}
@; ----------------------------------------------------------------------
@section[#:tag "beginner-call"]{Function Calls}
@defform/none[(id expr expr ...)]{
Calls a function. The @racket[id] must refer to a defined function,
and the @racket[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 @racket[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 @racket[#%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 @racket[expr]s are evaluated from left to right, and
passed as arguments to the primitive operation named by
@racket[prim-op]. A @racket[define-struct] form creates new
primitives.}
@; ----------------------------------------------------------------------
@section{@racket[cond]}
@defform[(cond [expr expr] ... [expr expr])]{
A @racket[cond] form contains one or more ``lines'' that are
surrounded by parentheses or square brackets. Each line contains two
@racket[expr]s: a question @racket[expr] and an answer
@racket[expr].
The lines are considered in order. To evaluate a line, first evaluate
the question @racket[expr]. If the result is @racket[true], then the
result of the whole @racket[cond] expression is the result of
evaluating the answer @racket[expr] of the same line. If the result of
evaluating the question @racket[expr] is @racket[false], the line is
discarded and evaluation proceeds with the next line.
If the result of a question @racket[expr] is neither @racket[true] nor
@racket[false], it is an error. If none of the question @racket[expr]s
evaluates to @racket[true], it is also an error.}
@defform/none[#:literals (cond else)
(cond [expr expr] ... [else expr])]{
This form of @racket[cond] is similar to the prior one, except that
the final @racket[else] clause is always taken if no prior line's test
expression evaluates to @racket[true]. In other words, @racket[else]
acts like @racket[true], so there is no possibility to ``fall off the
end'' of the @racket[cond] form.}
@defidform[else]{
The @racket[else] keyword can be used only with @racket[cond].}
@; ----------------------------------------------------------------------
@section{@racket[if]}
@defform[(if expr expr expr)]{
The first @racket[expr] (known as the ``test'' @racket[expr]) is
evaluated. If it evaluates to @racket[true], the result of the
@racket[if] expression is the result of evaluating the second
@racket[expr] (often called the ``then'' @racket[expr]). If the text
@racket[expr] evaluates to @racket[false], the result of the
@racket[if] expression is the result of evaluating the third
@racket[expr] (known as the ``else'' @racket[expr]). If the
result of evaluating the test @racket[expr] is neither @racket[true]
nor @racket[false], it is an error.}
@; ----------------------------------------------------------------------
@section{@racket[and]}
@defform[(and expr expr expr ...)]{
The @racket[expr]s are evaluated from left to right. If the first
@racket[expr] evaluates to @racket[false], the @racket[and] expression
immediately evaluates to @racket[false]. If the first @racket[expr]
evaluates to @racket[true], the next expression is considered. If all
@racket[expr]s evaluate to @racket[true], the @racket[and] expression
evaluates to @racket[true]. If any of the expressions evaluate to a
value other than @racket[true] or @racket[false], it is an error.}
@; ----------------------------------------------------------------------
@section{@racket[or]}
@defform[(or expr expr expr ...)]{
The @racket[expr]s are evaluated from left to right. If the first
@racket[expr] evaluates to @racket[true], the @racket[or] expression
immediately evaluates to @racket[true]. If the first @racket[expr]
evaluates to @racket[false], the next expression is considered. If all
@racket[expr]s evaluate to @racket[false], the @racket[or] expression
evaluates to @racket[false]. If any of the expressions evaluate to a
value other than @racket[true] or @racket[false], it is an error.}
@; ----------------------------------------------------------------------
@section{Test Cases}
@defform[(check-expect expr expr)]{
A test case to check that the first @racket[expr] produces the same
value as the second @racket[expr], where the latter is normally an
immediate value.}
@defform[(check-within expr expr expr)]{
Like @racket[check-expect], but with an extra expression that produces
a number @racket[_delta]. The test case checks that each number in the
result of the first @racket[expr] is within @racket[_delta] of each
corresponding number from the second @racket[expr].}
@defform*[[(check-error expr expr)
(check-error expr)]]{
A test case to check that the first @racket[expr] signals an error,
where the error messages matches the string produced by the second
@racket[expr], if it is present.}
@defform[(check-member-of expr expr expr ...)]{
A test case to check that the first @racket[expr] produces an element
that is equivalent to one of the following @racket[expr]s.}
@defform[(check-range expr expr expr)]{
A test case to check that the first @racket[expr] produces a number
inbetween the numbers produced by the second and third @racket[expr]s,
inclusive.}
@; ----------------------------------------------------------------------
@section{@racket[empty]}
@defthing[empty empty?]{
The empty list.}
@; ----------------------------------------------------------------------
@section[#:tag "beginner-id"]{Identifiers}
@defform/none[id]{
An @racket[id] refers to a defined constant or argument within a
function body. If no definition or argument matches the @racket[id]
name, an error is reported. Similarly, if @racket[id] matches the name
of a defined function or primitive operation, an error is reported.}
@; ----------------------------------------------------------------------
@section[#:tag "beginner-quote"]{Symbols}
@deftogether[( @deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{'}@racket[id]})] @defform/none[(unsyntax @elem{@racketvalfont{'}@racket[name]})]
@defform[(quote id)] @defform[(quote name)]
)]{ )]{
A quoted @racket[id] is a symbol. A symbol is a constant, like A quoted @racket[name] is a symbol. A symbol is a value, just like
@racket[0] and @racket[empty]. @racket[0] or @racket[empty].}
Normally, a symbol is written with a @litchar{'}, like
@racket['apple], but it can also be written with @racket[quote], like
@racket[(@#,racket[quote] apple)].
The @racket[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{#}}
@; ---------------------------------------------------------------------- @(define-forms/normal define)
@(define-form/explicit-lambda define lambda)
@section{@racket[true] and @racket[false]} @(prim-forms ("beginner")
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require)
@defthing[true boolean?]{ @section[#:tag "beginner-pre-defined"]{Pre-defined Functions}
The true value.}
@defthing[false boolean?]{
The false value.}
@; ----------------------------------------------------------------------
@section{@racket[require]}
@defform[(require string)]{
Makes the definitions of the module specified by @racket[string]
available in the current module (i.e., current file), where @racket[string]
refers to a file relative to the enclosing file.
The @racket[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)
(require module-id)]{
Accesses a file in an installed library. The library name is an
identifier with the same constraints as for a relative-path string,
with the additional constraint that it must not contain a
@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
@racket[string] names the library file, and the remaining
@racket[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 @racket[(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.rkt" "lang") #'here '()] @prim-op-defns['(lib "htdp-beginner.rkt" "lang") #'here '()]

View File

@ -1,4 +1,4 @@
#lang scheme/base #lang racket/base
(require scribble/manual) (require scribble/manual)

View File

@ -2,196 +2,116 @@
@(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt" @(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt"
(for-label lang/htdp-intermediate-lambda)) (for-label lang/htdp-intermediate-lambda))
@(define-syntax-rule (bd intm-define intm-define-struct intm-local intm-letrec intm-let intm-let* intm-time)
(begin
(require (for-label lang/htdp-intermediate))
(define intm-define @racket[define])
(define intm-define-struct @racket[define-struct])
(define intm-local @racket[local])
(define intm-letrec @racket[letrec])
(define intm-let @racket[let])
(define intm-let* @racket[let*])
(define intm-time @racket[time])))
@(bd intm-define intm-define-struct intm-local intm-letrec intm-let intm-let* intm-time)
@(define-syntax-rule (bbd 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 @racket[define])
(define beg-define-struct @racket[define-struct])
(define beg-cond @racket[cond])
(define beg-if @racket[if])
(define beg-and @racket[and])
(define beg-or @racket[or])
(define beg-check-expect @racket[check-expect])
(define beg-require @racket[require])))
@(bbd beg-define beg-define-struct beg-cond beg-if beg-and beg-or beg-check-expect beg-require)
@title[#:style 'toc #:tag "intermediate-lam"]{Intermediate Student with Lambda} @title[#:style 'toc #:tag "intermediate-lam"]{Intermediate Student with Lambda}
@declare-exporting[lang/htdp-intermediate-lambda] @declare-exporting[lang/htdp-intermediate-lambda]
@racketgrammar*+qq[ @racketgrammar*+qq[
#:literals (define define-struct lambda λ cond else if and or empty true false require lib planet #:literals (define define-struct lambda λ cond else if and or require lib planet
local let let* letrec time check-expect check-within check-error) local let let* letrec time check-expect check-within check-member-of check-range check-error)
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
[program (code:line def-or-expr ...)] [program (code:line def-or-expr ...)]
[def-or-expr definition [def-or-expr definition
expr expression
test-case test-case
library-require] library-require]
[definition (define (id id id ...) expr) [definition (define (name variable variable ...) expression)
(define id expr) (define name expression)
(define-struct id (id ...))] (define-struct name (name ...))]
[expr (lambda (id id ...) expr) [expression (lambda (variable variable ...) expression)
(λ (id id ...) expr) (λ (variable variable ...) expression)
(local [definition ...] expr) (local [definition ...] expression)
(letrec ([id expr] ...) expr) (letrec ([name expression] ...) expression)
(let ([id expr] ...) expr) (let ([name expression] ...) expression)
(let* ([id expr] ...) expr) (let* ([name expression] ...) expression)
(code:line (expr expr expr ...) (code:comment @#,seclink["intermediate-lambda-call"]{function call})) (code:line (expression expression expression ...))
(cond [expr expr] ... [expr expr]) (cond [expression expression] ... [expression expression])
(cond [expr expr] ... [else expr]) (cond [expression expression] ... [else expression])
(if expr expr expr) (if expression expression expression)
(and expr expr expr ...) (and expression expression expression ...)
(or expr expr expr ...) (or expression expression expression ...)
(time expr) (time expression)
empty (code:line name)
(code:line id (code:comment @#,seclink["intermediate-id"]{identifier})) (code:line prim-op)
(code:line prim-op (code:comment @#,seclink["intermediate-lambda-prim-op"]{primitive operation})) (code:line @#,elem{@racketvalfont{'}@racket[_quoted]})
(code:line @#,elem{@racketvalfont{'}@racket[_quoted]} (code:comment @#,seclink["beginner-abbr-quote"]{quoted value})) (code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]})
(code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]} (code:comment @#,seclink["beginner-abbr-quasiquote"]{quasiquote}))
number number
true
false
string string
character] character]
] ]
@|prim-nonterms| @prim-nonterms[("intermediate-w-lambda") define define-struct]
@prim-variables[("intermedia-w-lambda") empty true false]
@prim-ops['(lib "htdp-intermediate-lambda.rkt" "lang") #'here]
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "intermediate-lambda-define"]{@racket[define]} @section[#:tag "intermediate-lambda-syntax"]{Syntax for Intermediate with Lambda}
@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 @defform[(lambda (variable variable ...) expression)]{
for @racket[lambda], since a @racket[lambda] form is an expression.}
@; ---------------------------------------------------------------------- Creates a function that takes as many arguments as given @racket[variables]s,
and whose body is @racket[expression].}
@section[#:tag "intermediate-lambda"]{@racket[lambda]} @defform[(λ (variable variable ...) expression)]{
@defform[(lambda (id id ...) expr)]{
Creates a function that takes as many arguments as given @racket[id]s,
and whose body is @racket[expr].}
@defform[(λ (id id ...) expr)]{
The Greek letter @racket[λ] is a synonym for @racket[lambda].} The Greek letter @racket[λ] is a synonym for @racket[lambda].}
@; ----------------------------------------------------------------------
@section[#:tag "intermediate-lambda-call"]{Function Calls}
@defform/none[(expr expr expr ...)]{ @defform/none[(expression expression expression ...)]{
Like a Beginning @seclink["beginner-call"]{function call}, except that Calls the function that results from evaluating the first
the function position can be an arbitrary expression---perhaps a @racket[expression]. The value of the call is the value of function's body when
@racket[lambda] expression or a @racket[_prim-op].} every instance of @racket[name]'s variables are replaced by the values of the
corresponding @racket[expression]s.
@defform[(#%app expr expr expr ...)]{ The function being called must come from either a definition appearing before the
function call, or from a @racket[lambda] expression. The number of argument
@racket[expression]s must be the same as the number of arguments expected by
the function.}
A function call can be written with @racket[#%app], though it's
practically never written that way.}
@; ----------------------------------------------------------------------
@section[#:tag "intermediate-lambda-prim-op"]{Primitive Operation Names} @(intermediate-forms lambda
quote
quasiquote
unquote
unquote-splicing
local
letrec
let*
let
time)
@defform/none[prim-op]{
The name of a primitive operation can be used as an expression. It
produces a function version of the operation.}
@prim-op-defns['(lib "htdp-intermediate-lambda.rkt" "lang") #'here '()]
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "intermediate-lambda-unchanged"]{Unchanged Forms} @section[#:tag "intermediate-lambda-common-syntax"]{Common Syntax}
@defform[(define-struct structid (fieldid ...))]{ @(define-forms/normal define)
The same as Intermediate's @|intm-define-struct|.} @(prim-forms ("beginner")
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require)
@section[#:tag "intermediate-lambda-pre-defined"]{Pre-defined Functions}
@deftogether[( @prim-op-defns['(lib "htdp-intermediate-lambda.ss" "lang") #'here '()]
@defform[(local [definition ...] expr)]
@defform[(letrec ([id expr-for-let] ...) expr)]
@defform[(let ([id expr-for-let] ...) expr)]
@defform[(let* ([id expr-for-let] ...) expr)]
)]{
The same as Intermediate's @|intm-local|, @|intm-letrec|, @|intm-let|,
and @|intm-let*|.}
@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|.}
@defform[(time expr)]{
The same as Intermediate's @|intm-time|.}
@deftogether[(
@defform[(check-expect expr expr)]
@defform[(check-within expr expr expr)]
@defform*[[(check-error expr expr)
(check-error expr)]]
@defform[(check-member-of expr expr expr ...)]
@defform[(check-range expr 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 module-path)]{
The same as Beginning's @|beg-require|.}

View File

@ -2,242 +2,94 @@
@(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt" @(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt"
(for-label lang/htdp-intermediate)) (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 (racket define))
(define beg-define-struct (racket define-struct))
(define beg-cond (racket cond))
(define beg-if (racket if))
(define beg-and (racket and))
(define beg-or (racket or))
(define beg-check-expect (racket check-expect))
(define beg-require (racket 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} @title[#:style 'toc #:tag "intermediate"]{Intermediate Student}
@declare-exporting[lang/htdp-intermediate] @declare-exporting[lang/htdp-intermediate]
@racketgrammar*+qq[ @racketgrammar*+qq[
#:literals (define define-struct lambda cond else if and or empty true false require lib planet #:literals (define define-struct lambda cond else if and or require lib planet
local let let* letrec time check-expect check-within check-error) local let let* letrec time check-expect check-within check-error)
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
[program (code:line def-or-expr ...)] [program (code:line def-or-expr ...)]
[def-or-expr definition [def-or-expr definition
expr expression
test-case test-case
library-require] library-require]
[definition (define (id id id ...) expr) [definition (define (name variable variable ...) expression)
(define id expr) (define name expression)
(define id (lambda (id id ...) expr)) (define name (lambda (variable variable ...) expression))
(define-struct id (id ...))] (define-struct name (name ...))]
[expr (local [definition ...] expr) [expression (local [definition ...] expression)
(letrec ([id expr-for-let] ...) expr) (letrec ([name expr-for-let] ...) expression)
(let ([id expr-for-let] ...) expr) (let ([name expr-for-let] ...) expression)
(let* ([id expr-for-let] ...) expr) (let* ([name expr-for-let] ...) expression)
(code:line (id expr expr ...) (code:comment @#,seclink["intermediate-call"]{function call})) (code:line (name expression expression ...) )
(code:line (prim-op expr ...) (code:comment @#,seclink["beginner-prim-call"]{primitive operation call})) (cond [expression expression] ... [expression expression])
(cond [expr expr] ... [expr expr]) (cond [expression expression] ... [else expression])
(cond [expr expr] ... [else expr]) (if expression expression expression)
(if expr expr expr) (and expression expression expression ...)
(and expr expr expr ...) (or expression expression expression ...)
(or expr expr expr ...) (time expression)
(time expr) (code:line name)
empty (code:line @#,elem{@racketvalfont{'}@racket[_quoted]})
(code:line id (code:comment @#,seclink["intermediate-id"]{identifier})) (code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]})
(code:line prim-op (code:comment @#,seclink["intermediate-prim-op"]{primitive operation}))
(code:line @#,elem{@racketvalfont{'}@racket[_quoted]} (code:comment @#,seclink["beginner-abbr-quote"]{quoted value}))
(code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]} (code:comment @#,seclink["beginner-abbr-quasiquote"]{quasiquote}))
number number
true
false
string string
character] character]
[expr-for-let (lambda (id id ...) expr) [expr-for-let (lambda (variable variable ...) expression)
expr] expression]
] ]
@|prim-nonterms| @prim-nonterms[("intermediate") define define-struct]
@prim-variables[("intermediate") empty true false]
@prim-ops['(lib "htdp-intermediate.rkt" "lang") #'here]
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "intermediate-define"]{@racket[define]} @section[#:tag "intermediate-syntax"]{Syntax for Intermediate}
@deftogether[( @(intermediate-forms lambda
@defform[(define (id id id ...) expr)] quote
@defform/none[#:literals (define) quasiquote
(define id expr)] unquote
@defform/none[#:literals (define lambda) unquote-splicing
(define id (lambda (id id ...) expr))] local
)]{ letrec
Besides working in @racket[local], definition forms are let*
the same as Beginning's @|beg-define|.} let
time)
@defidform[lambda]{
As in Beginning, @racket[lambda] keyword can only be used with
@racket[define] in the alternative function-definition syntax.}
@; ---------------------------------------------------------------------- @; ----------------------------------------------------------------------
@section[#:tag "intermediate-define-struct"]{@racket[define-struct]} @section[#:tag "intermediate-common-syntax"]{Common Syntax}
@defform[(define-struct structid (fieldid ...))]{ @(define-forms/normal define)
@(define-form/explicit-lambda define lambda)
Besides working in @racket[local], this form is the same as Beginning's @(prim-forms
@|beg-define-struct|.} ("beginner")
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require)
@; ----------------------------------------------------------------------
@section{@racket[local]}
@defform[(local [definition ...] expr)]{
Groups related definitions for use in @racket[expr]. Each @section[#:tag "intermediate-pre-defined"]{Pre-defined Functions}
@racket[definition] is evaluated in order, and finally the body
@racket[expr] is evaluated. Only the expressions within the
@racket[local] form (including the right-hand-sides of the
@racket[definition]s and the @racket[expr]) may refer to the names
defined by the @racket[definition]s. If a name defined in the
@racket[local] form is the same as a top-level binding, the inner one
``shadows'' the outer one. That is, inside the @racket[local] form,
any references to that name refer to the inner one.
Since @racket[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{@racket[letrec], @racket[let], and @racket[let*]}
@defform[(letrec ([id expr-for-let] ...) expr)]{
Similar to @racket[local], but essentially omitting the
@racket[define] for each definition.
A @racket[expr-for-let] can be either an expression for a constant
definition or a @racket[lambda] form for a function definition.}
@defform[(let ([id expr-for-let] ...) expr)]{
Like @racket[letrec], but the defined @racket[id]s can be used only in
the last @racket[expr], not the @racket[expr-for-let]s next to the
@racket[id]s.}
@defform[(let* ([id expr-for-let] ...) expr)]{
Like @racket[let], but each @racket[id] can be used in any subsequent
@racket[expr-for-let], in addition to @racket[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
@racket[local]ly defined functions or functions passed as
arguments. That is, @racket[id] can be a function defined in
@racket[local] or an argument name while in a function.}
@defform[(#%app id expr expr ...)]{
A function call can be written with @racket[#%app], though it's
practically never written that way.}
@; ----------------------------------------------------------------------
@section{@racket[time]}
@defform[(time expr)]{
This form is used to measure the time taken to evaluate
@racket[expr]. After evaluating @racket[expr], Racket 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.
(The reported time is measured as the number of milliseconds of CPU time
required to obtain this result, the number of “real” milliseconds required
for the result, and the number of milliseconds of CPU time (included in the
first result) spent on garbage collection. The reliability of the timing
numbers depends on the platform.)
}
@; ----------------------------------------------------------------------
@section[#:tag "intermediate-id"]{Identifiers}
@defform/none[id]{
An @racket[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 @racket[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.rkt" "lang") #'here '()] @prim-op-defns['(lib "htdp-intermediate.rkt" "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)
(check-error expr)]]
@defform[(check-member-of expr expr expr ...)]
@defform[(check-range expr 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 module-path)]{
The same as Beginning's @|beg-require|.}

View File

@ -1,14 +1,21 @@
#reader scribble/reader #reader scribble/reader
#lang scheme/base #lang racket/base
(require "common.rkt" (require "common.ss"
scribble/decode scribble/decode
scribble/struct scribble/struct
scribble/scheme scribble/racket
scheme/list racket/list
scheme/pretty racket/pretty
syntax/docprovide) syntax/docprovide
(for-syntax racket/base)
)
(provide prim-ops (provide prim-variables
prim-forms
define-forms/normal
define-form/explicit-lambda
intermediate-forms
prim-ops
prim-op-defns) prim-op-defns)
(define (maybe-make-table l t) (define (maybe-make-table l t)
@ -48,6 +55,411 @@
(to-paragraph (to-paragraph
(typeset-type (cadr func))))) (typeset-type (cadr func)))))
(define-syntax-rule (prim-variables (section-prefix) empty true false)
(make-splice
(list
@section[#:tag (string-append section-prefix " Pre-Defined Variables")]{Pre-Defined Variables}
@defthing[empty empty?]{
The empty list.}
@defthing[true boolean?]{
The true value.}
@defthing[false boolean?]{
The false value.}
)))
(define-syntax-rule (define-forms/normal define)
(make-splice
(list
@defform*[[(define (... (name variable variable ...)) expression)]]{
Defines a function named @racket[name]. The @racket[expression] is the body
of the function. When the function is called,
the values of the arguments are inserted into the body in place of the
@racket[variable]s. The function returns the value of that new expression.
The function name's cannot be the same as that of another function or
variable.}
@defform/none[#:literals (define) (define name expression)]{
Defines a variable called @racket[name] with the the value of
@racket[expression]. The variable name's cannot be the same as that of
another function or variable, and @racket[name] itself must not appear in
@racket[expression].}
)))
(define-syntax-rule (define-form/explicit-lambda define lambda)
(make-splice
(list
@defform/none[#:literals (define lambda)
(... (define name (lambda (variable variable ...) expression)))]{
An alternate way on defining functions. The @racket[name] is the name of
the function, which cannot be the same as that of another function or
variable.
@defidform/inline[lambda] cannot be used outside of this alternate syntax.
}
)))
(define-syntax-rule (prim-forms
(section-prefix)
define
lambda
define-struct
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require)
(make-splice
(list
@; ----------------------------------------------------------------------
@defform*[[(... (define-struct structure-name (field-name ...)))]]{
Defines a new structure called @racket[field-name]. The structure's fields are
named by the @racket[field-name]s. After the @racket[define-struct], the following new
functions are available:
@itemize[
@item{@racketidfont{make-}@racket[structure-name] : takes in a number of
arguments equal to the number of fields in the structure,
and creates a new instance of that structure.}
@item{@racket[structure-name]@racketidfont{-}@racket[field-name] : takes in an
instance of the structure and returns the value in the field named by
@racket[field-name].}
@item{@racket[structure-name]@racketidfont{?} : takes in any value, and returns
@racket[true] if the value is an instance of the structure.}
]
The name of the new functions introduced by @racket[define-struct] must not be the same as that of other functions or
variables, otherwise @racket[define-struct] reports an error.}
#|
@defform*[[(define-wish name)]]{
Defines a function called @racket[name] that we wish exists but have not
implemented yet. The wished-for function can be called with one argument, and
are reported in the test report for the current program.
The name of the function cannot be the same as another function or variable.}
@defform/none[#:literals (define-wish)
(define-wish name expression)]{
Similar to the above form, defines a wished-for function named @racket[name]. If the
wished-for function is called with one value, it returns the values of @racket[expression]. }
|#
@; ----------------------------------------------------------------------
@defform*[[(... (name expression expression ...))]]{
Calls the function named @racket[name]. The value of the call is the value of
@racket[name]'s body when every one of the function's variables are
replaced by the values of the corresponding @racket[expression]s.
The function named @racket[name] must defined before it can be called. The
number of argument @racket[expression]s must be the same as the number of arguments
expected by the function.}
@; ----------------------------------------------------------------------
@defform*[#:literals (cond else)
[(... (cond [question-expression answer-expression] ...))
(... (cond [question-expression answer-expression] ... [else answer-expression]))]]{
Chooses a clause base on a condition. @racket[cond] finds the first
@racket[question-expression] which evaluates to @racket[true], then it evaluates
the corresponding @racket[answer-expression].
If none of the @racket[question-expression]s evaluates to @racket[true],
@racket[cond]'s value is the @racket[answer-expression] of the
@racket[else] clause. If there is no @racket[else], @racket[cond] reports
an error. If the result of a @racket[question-expression] is neither
@racket[true] nor @racket[false], @racket[cond] also reports an error.
@defidform/inline[else] cannot be used outside of @racket[cond].
}
@; ----------------------------------------------------------------------
@defform*[[(if test-expression then-expression else-expression)]]{
When the value of the @racket[test-expression] is @racket[true],
@racket[if] evaluates the @racket[then-expression]. When the test is
@racket[false], @racket[if] evaluates the @racket[else-expression].
If the @racket[test-expression] is neither @racket[true] nor
@racket[false], @racket[if] reports an error.}
@; ----------------------------------------------------------------------
@defform*[[(... (and expression expression expression ...))]]{
@racket[and] evaluates to @racket[true] if all the @racket[expression]s are
@racket[true]. If any @racket[expression] is false, the @racket[and]
expression immediately evaluates to @racket[false] (the expressions to the
right of that expression are not evaluated.)
If any of the expressions evaluate to a value other than @racket[true] or
@racket[false], it is an error.}
@; ----------------------------------------------------------------------
@defform*[[(... (or expression expression expression ...))]]{
@racket[or] evaluates to @racket[true] as soon as one of the
@racket[expression]s is @racket[true] (the expressions to the right of that
expression are not evaluated.) If all the @racket[expression] are false,
@racket[or] is @racket[false].
If any of the expressions evaluate to a value other than @racket[true] or
@racket[false], @racket[or] reports an error.}
@; ----------------------------------------------------------------------
@defform*[[(check-expect expression expected-expression)]]{
Checks that the first @racket[expression] evaluates to the same value as the
@racket[expected-expression].}
@defform*[[(check-within expression expected-expression delta-expression)]]{
Checks that the first @racket[expression] evaluates to a value within
@racket[delta-expression] of the @racket[expected-expression]. If
@racket[delta-expression] is not a number, @racket[check-within] report an
error.}
@defform*[[(check-error expression expression)
(check-error expression)]]{
Checks that the first @racket[expression] reports an error,
where the error messages matches the string produced by the second
@racket[expression], if it is present.}
@defform*[[(... (check-member-of expression expression expression ...))]]{
Checks that the first @racket[expression] produces the same value as one of
the following @racket[expression]s.}
@defform*[[(check-range expression expression expression)]]{
Checks that the first @racket[expression] produces a number in between the numbers
produced by the second and third @racket[expression]s, inclusive.}
@; ----------------------------------------------------------------------
@defform*[[(require string)]]{
Makes the definitions of the module specified by @racket[string]
available in the current module (i.e., the current file), where @racket[string]
refers to a file relative to the current file.
The @racket[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)
(require module-name)]{
Accesses a file in an installed library. The library name is an identifier
with the same constraints as for a relative-path string (though without the
quotes), with the additional constraint that it must not contain a
@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., the current file). The first
@racket[string] names the library file, and the remaining
@racket[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 @racket[(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).}
)))
(define-syntax-rule
(intermediate-forms lambda
quote
quasiquote
unquote
unquote-splicing
local
letrec
let*
let
time)
(make-splice
(list
@deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{'}@racket[name]})]
@defform/none[(unsyntax @elem{@racketvalfont{'}@racket[part]})]
@defform[(quote name)]
@defform/none[(quote part)]
)]{
A quoted name is a symbol. A quote part is an abbreviation for a nested lists.
Normally, this quotation is written with a @litchar{'}, like
@racket['(apple banana)], but it can also be written with @racket[quote], like
@racket[(@#,racket[quote] (apple banana))].}
@deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{`}@racket[name]})]
@defform/none[(unsyntax @elem{@racketvalfont{`}@racket[part]})]
@defform[(quasiquote name)]
@defform/none[(quasiquote part)]
)]{
Like @racket[quote], but also allows escaping to expression ``unquotes.''
Normally, quasi-quotations are written with a backquote, @litchar{`}, like
@racket[`(apple ,(+ 1 2))], but they can also be written with
@racket[quasiquote], like
@racket[(@#,racket[quasiquote] (apple ,(+ 1 2)))].}
@deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont{,}@racket[expression]})]
@defform[(unquote expression)]
)]{
Under a single quasiquote, @racketfont{,}@racket[expression] escapes from
the quote to include an evaluated expression whose result is inserted
into the abbreviated list.
Under multiple quasiquotes, @racketfont{,}@racket[expression] is really
the literal @racketfont{,}@racket[expression], decrementing the quasiquote count
by one for @racket[expression].
Normally, an unquote is written with @litchar{,}, but it can also be
written with @racket[unquote].}
@deftogether[(
@defform/none[(unsyntax @elem{@racketvalfont[",@"]@racket[expression]})]
@defform[(unquote-splicing expression)]
)]{
Under a single quasiquote, @racketfont[",@"]@racket[expression] 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 @racket[unquote-splicing].}
@defform[(... (local [definition ...] expression))]{
Groups related definitions for use in @racket[expression]. Each
@racket[definition] can be either a variable definition, a function
definition, or a structure definition, using the usual syntax.
When evaluating @racket[local], each @racket[definition] is evaluated in
order, and finally the body @racket[expression] is evaluated. Only the
expressions within the @racket[local] (including the right-hand-sides of
the @racket[definition]s and the @racket[expression]) may refer to the
names defined by the @racket[definition]s. If a name defined in the
@racket[local] is the same as a top-level binding, the inner one
``shadows'' the outer one. That is, inside the @racket[local], any
references to that name refer to the inner one.}
@; ----------------------------------------------------------------------
@defform[(... (letrec ([name expr-for-let] ...) expression))]{
Like @racket[local], but with a simpler syntax. Each @racket[name] defines
a variables (or a functions) with the value of the corresponding
@racket[expr-for-let]. If @racket[expr-for-let] is a @racket[lambda],
@racket[letrec] defines a function, otherwise it defines a variable.}
@defform[(... (let* ([name expr-for-let] ...) expression))]{
Like @racket[letrec], but each @racket[name] can only be used in
@racket[expression], and in @racket[expr-for-let]s occuring after that
@racket[name].}
@defform[(... (let ([name expr-for-let] ...) expression))]{
Like @racket[letrec], but the defined @racket[name]s can be used only in
the last @racket[expression], not the @racket[expr-for-let]s next to the
@racket[name]s.}
@; ----------------------------------------------------------------------
@defform[(time expression)]{
Measures the time taken to evaluate @racket[expression]. After evaluating
@racket[expression], @racket[time] prints out the time taken by the
evaluation (including real time, time taken by the cpu, and the time spent
collecting free memory). The value of @racket[time] is the same as that of @racket[expression].}
)))
(define (prim-ops lib ctx-stx) (define (prim-ops lib ctx-stx)
(let ([ops (map (lambda (cat) (let ([ops (map (lambda (cat)
(cons (car cat) (cons (car cat)
@ -60,7 +472,8 @@
(make-flow (make-flow
(list (list
(make-paragraph (make-paragraph
(list "A " (racket _prim-op) " is one of:"))))) (list "In function calls, the function appearing immediatly after the open parenthesis can be any functions
defined with " (racket define) " or " (racket define-struct) ", or any one of:")))))
(apply (apply
append append
(map (lambda (category) (map (lambda (category)
@ -110,6 +523,7 @@
(defthing/proc (defthing/proc
id id
(to-paragraph (typeset-type (cadr func))) (to-paragraph (typeset-type (cadr func)))
(cons "Purpose: " desc-strs)))))) desc-strs)))))
(sort-category category))))) (sort-category category)))))
ops))))) ops)))))

View File

@ -1,8 +1,7 @@
#reader scribble/reader #reader scribble/reader
#lang scheme/base #lang racket/base
(require "common.rkt" (require "common.ss"
scribble/decode scribble/decode)
(for-label lang/htdp-beginner-abbr))
(provide prim-nonterms (provide prim-nonterms
racketgrammar*+library racketgrammar*+library
@ -12,17 +11,17 @@
(define-syntax-rule (racketgrammar*+library (define-syntax-rule (racketgrammar*+library
#:literals lits #:literals lits
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
form ...) form ...)
(racketgrammar* (racketgrammar*
#:literals lits #:literals lits
form ... form ...
[test-case @#,racket[(check-expect expr expr)] [test-case @#,racket[(check-expect expression expression)]
@#,racket[(check-within expr expr expr)] @#,racket[(check-within expression expression expression)]
@#,racket[(check-member-of expr expr (... ...))] @#,racket[(check-member-of expression expression (... ...))]
@#,racket[(check-range expr expr expr)] @#,racket[(check-range expression expression expression)]
@#,racket[(check-error expr expr)] @#,racket[(check-error expression expression)]
@#,racket[(check-error expr)]] @#,racket[(check-error expression)]]
(... (...
[library-require @#,racket[(require string)] [library-require @#,racket[(require string)]
@#,racket[(require (lib string string ...))] @#,racket[(require (lib string string ...))]
@ -32,14 +31,14 @@
(define-syntax-rule (racketgrammar*+qq (define-syntax-rule (racketgrammar*+qq
#:literals lits #:literals lits
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
form ...) form ...)
(racketgrammar*+library (racketgrammar*+library
#:literals lits #:literals lits
(check-expect check-within check-error require) (check-expect check-within check-member-of check-range check-error require)
form ... form ...
(... (...
[quoted id [quoted name
number number
string string
character character
@ -49,22 +48,23 @@
@#,elem{@racketfont{,}@racket[quoted]} @#,elem{@racketfont{,}@racket[quoted]}
@#,elem{@racketfont[",@"]@racket[quoted]}]) @#,elem{@racketfont[",@"]@racket[quoted]}])
(... (...
[quasiquoted id [quasiquoted name
number number
string string
character character
@#,racket[(quasiquoted ...)] @#,racket[(quasiquoted ...)]
@#,elem{@racketvalfont{'}@racket[quasiquoted]} @#,elem{@racketvalfont{'}@racket[quasiquoted]}
@#,elem{@racketvalfont{`}@racket[quasiquoted]} @#,elem{@racketvalfont{`}@racket[quasiquoted]}
@#,elem{@racketfont{,}@racket[expr]} @#,elem{@racketfont{,}@racket[expression]}
@#,elem{@racketfont[",@"]@racket[expr]}]))) @#,elem{@racketfont[",@"]@racket[expression]}])))
(define-syntax-rule (prim-nonterms (section-prefix) define define-struct)
(define prim-nonterms
(make-splice (make-splice
(list (list
@t{An @racket[_id] is a sequence of characters not including a @t{An @racket[_name] or a @racket[_variable] is a sequence of characters
space or one of the following:} not including a space or one of the following:}
@t{@hspace[2] @litchar{"} @litchar{,} @litchar{'} @litchar{`} @t{@hspace[2] @litchar{"} @litchar{,} @litchar{'} @litchar{`}
@litchar{(} @litchar{)} @litchar{[} @litchar{]} @litchar{(} @litchar{)} @litchar{[} @litchar{]}
@ -74,13 +74,22 @@ space or one of the following:}
@t{A @racket[_number] is a number such as @racket[123], @racket[3/2], or @t{A @racket[_number] is a number such as @racket[123], @racket[3/2], or
@racket[5.5].} @racket[5.5].}
@t{A @racket[_symbol] is a quote character followed by a name. A
symbol is a value, just like 0 or empty.}
@t{A @racket[_string] is enclosed by a pair of @litchar{"}. Unlike @t{A @racket[_string] is enclosed by a pair of @litchar{"}. Unlike
symbols, strings may be split into characters and manipulated by a symbols, strings may be split into characters and manipulated by a
variety of primitive functions. For example, @racket["abcdef"], variety of functions. For example, @racket["abcdef"],
@racket["This is a string"], and @racket[#,ex-str] are all strings.} @racket["This is a string"], and @racket[#,ex-str] are all strings.}
@t{A @racket[_character] begins with @litchar{#\} and has the @t{A @racket[_character] begins with @litchar{#\} and has the
name of the character. For example, @racket[#\a], @racket[#\b], name of the character. For example, @racket[#\a], @racket[#\b],
and @racket[#\space] are characters.} and @racket[#\space] are characters.}
@t{In @seclink[(string-append section-prefix "-syntax")]{function calls}, the function appearing
immediatly after the open parenthesis can be any functions defined
with @racket[define] or @racket[define-struct], or any one of the
@seclink[(string-append section-prefix "-pre-defined")]{pre-defined functions}.}
))) )))