reorganize guide to have the Scheme background in one section
svn: r6284
This commit is contained in:
parent
b82a2f7f8c
commit
75632a9cc3
|
@ -252,36 +252,40 @@
|
|||
;; ----------------------------------------
|
||||
|
||||
(define/public (table-of-contents part ht)
|
||||
(make-table #f (cdr (render-toc part))))
|
||||
(make-table #f (render-toc part #t)))
|
||||
|
||||
(define/private (render-toc part)
|
||||
(define/private (render-toc part skip?)
|
||||
(let ([number (collected-info-number (part-collected-info part))])
|
||||
(let ([l (cons
|
||||
(list (make-flow
|
||||
(list
|
||||
(make-paragraph
|
||||
(list
|
||||
(make-element 'hspace (list (make-string (* 2 (length number)) #\space)))
|
||||
(make-link-element (if (= 1 (length number))
|
||||
"toptoclink"
|
||||
"toclink")
|
||||
(append
|
||||
(format-number number
|
||||
(list
|
||||
(make-element 'hspace '(" "))))
|
||||
(part-title-content part))
|
||||
`(part ,(part-tag part))))))))
|
||||
(apply
|
||||
append
|
||||
(map (lambda (p) (render-toc p)) (part-parts part))))])
|
||||
(if (and (= 1 (length number))
|
||||
(or (not (car number))
|
||||
((car number) . > . 1)))
|
||||
(cons (list (make-flow (list (make-paragraph (list
|
||||
(make-element 'hspace (list "")))))))
|
||||
l)
|
||||
l))))
|
||||
|
||||
(let ([subs
|
||||
(apply
|
||||
append
|
||||
(map (lambda (p) (render-toc p #f)) (part-parts part)))])
|
||||
(if skip?
|
||||
subs
|
||||
(let ([l (cons
|
||||
(list (make-flow
|
||||
(list
|
||||
(make-paragraph
|
||||
(list
|
||||
(make-element 'hspace (list (make-string (* 2 (length number)) #\space)))
|
||||
(make-link-element (if (= 1 (length number))
|
||||
"toptoclink"
|
||||
"toclink")
|
||||
(append
|
||||
(format-number number
|
||||
(list
|
||||
(make-element 'hspace '(" "))))
|
||||
(part-title-content part))
|
||||
`(part ,(part-tag part))))))))
|
||||
subs)])
|
||||
(if (and (= 1 (length number))
|
||||
(or (not (car number))
|
||||
((car number) . > . 1)))
|
||||
(cons (list (make-flow (list (make-paragraph (list
|
||||
(make-element 'hspace (list "")))))))
|
||||
l)
|
||||
l))))))
|
||||
|
||||
;; ----------------------------------------
|
||||
|
||||
(super-new))))
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
(content->string content)
|
||||
"_"))
|
||||
|
||||
(define/kw (title #:key [tag #f] #:body str)
|
||||
(define/kw (title #:key [tag #f] [style #f] #:body str)
|
||||
(let ([content (decode-content str)])
|
||||
(make-title-decl (or tag (gen-tag content)) content)))
|
||||
(make-title-decl (or tag (gen-tag content)) style content)))
|
||||
|
||||
(define/kw (section #:key [tag #f] #:body str)
|
||||
(let ([content (decode-content str)])
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
(provide-structs
|
||||
[title-decl ([tag any/c]
|
||||
[style any/c]
|
||||
[content list?])]
|
||||
[part-start ([depth integer?]
|
||||
[tag (or/c false/c string?)]
|
||||
|
@ -48,14 +49,15 @@
|
|||
null
|
||||
(list (decode-paragraph (reverse (skip-whitespace accum))))))
|
||||
|
||||
(define (decode-flow* l tag title part-depth)
|
||||
(let loop ([l l][next? #f][accum null][title title][tag tag])
|
||||
(define (decode-flow* l tag style title part-depth)
|
||||
(let loop ([l l][next? #f][accum null][title title][tag tag][style style])
|
||||
(cond
|
||||
[(null? l) (make-part tag
|
||||
title
|
||||
#f
|
||||
(make-flow (decode-accum-para accum))
|
||||
null)]
|
||||
[(null? l) (make-styled-part tag
|
||||
title
|
||||
#f
|
||||
(make-flow (decode-accum-para accum))
|
||||
null
|
||||
style)]
|
||||
[(title-decl? (car l))
|
||||
(unless part-depth
|
||||
(error 'decode
|
||||
|
@ -65,30 +67,35 @@
|
|||
(error 'decode
|
||||
"found extra title: ~v"
|
||||
(car l)))
|
||||
(loop (cdr l) next? accum (title-decl-content (car l)) (title-decl-tag (car l)))]
|
||||
(loop (cdr l) next? accum
|
||||
(title-decl-content (car l))
|
||||
(title-decl-tag (car l))
|
||||
(title-decl-style (car l)))]
|
||||
[(or (paragraph? (car l))
|
||||
(table? (car l))
|
||||
(itemization? (car l))
|
||||
(delayed-flow-element? (car l)))
|
||||
(let ([para (decode-accum-para accum)]
|
||||
[part (decode-flow* (cdr l) tag title part-depth)])
|
||||
(make-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append para
|
||||
(list (car l))
|
||||
(flow-paragraphs (part-flow part))))
|
||||
(part-parts part)))]
|
||||
[part (decode-flow* (cdr l) tag style title part-depth)])
|
||||
(make-styled-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append para
|
||||
(list (car l))
|
||||
(flow-paragraphs (part-flow part))))
|
||||
(part-parts part)
|
||||
(styled-part-style part)))]
|
||||
[(part? (car l))
|
||||
(let ([para (decode-accum-para accum)]
|
||||
[part (decode-part (cdr l) tag title part-depth)])
|
||||
(make-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append para
|
||||
(flow-paragraphs
|
||||
(part-flow part))))
|
||||
(cons (car l) (part-parts part))))]
|
||||
[part (decode-flow* (cdr l) tag style title part-depth)])
|
||||
(make-styled-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append para
|
||||
(flow-paragraphs
|
||||
(part-flow part))))
|
||||
(cons (car l) (part-parts part))
|
||||
(styled-part-style part)))]
|
||||
[(and (part-start? (car l))
|
||||
(or (not part-depth)
|
||||
((part-start-depth (car l)) . <= . part-depth)))
|
||||
|
@ -109,38 +116,40 @@
|
|||
(part-start-title s)
|
||||
(add1 part-depth))]
|
||||
[part (decode-part l tag title part-depth)])
|
||||
(make-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow para)
|
||||
(cons s (part-parts part))))
|
||||
(make-styled-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow para)
|
||||
(cons s (part-parts part))
|
||||
(styled-part-style part)))
|
||||
(loop (cdr l) (cons (car l) s-accum)))))]
|
||||
[(splice? (car l))
|
||||
(loop (append (splice-run (car l)) (cdr l)) next? accum title tag)]
|
||||
[(null? (cdr l)) (loop null #f (cons (car l) accum) title tag)]
|
||||
(loop (append (splice-run (car l)) (cdr l)) next? accum title tag style)]
|
||||
[(null? (cdr l)) (loop null #f (cons (car l) accum) title tag style)]
|
||||
[(and (pair? (cdr l))
|
||||
(splice? (cadr l)))
|
||||
(loop (cons (car l) (append (splice-run (cadr l)) (cddr l))) next? accum title tag)]
|
||||
(loop (cons (car l) (append (splice-run (cadr l)) (cddr l))) next? accum title tag style)]
|
||||
[(line-break? (car l))
|
||||
(if next?
|
||||
(loop (cdr l) #t accum title tag)
|
||||
(loop (cdr l) #t accum title tag style)
|
||||
(let ([m (match-newline-whitespace (cdr l))])
|
||||
(if m
|
||||
(let ([part (loop m #t null title tag)])
|
||||
(make-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append (decode-accum-para accum)
|
||||
(flow-paragraphs (part-flow part))))
|
||||
(part-parts part)))
|
||||
(loop (cdr l) #f (cons (car l) accum) title tag))))]
|
||||
[else (loop (cdr l) #f (cons (car l) accum) title tag)])))
|
||||
(let ([part (loop m #t null title tag style)])
|
||||
(make-styled-part (part-tag part)
|
||||
(part-title-content part)
|
||||
(part-collected-info part)
|
||||
(make-flow (append (decode-accum-para accum)
|
||||
(flow-paragraphs (part-flow part))))
|
||||
(part-parts part)
|
||||
(styled-part-style part)))
|
||||
(loop (cdr l) #f (cons (car l) accum) title tag style))))]
|
||||
[else (loop (cdr l) #f (cons (car l) accum) title tag style)])))
|
||||
|
||||
(define (decode-part l tag title depth)
|
||||
(decode-flow* l tag title depth))
|
||||
(decode-flow* l tag #f title depth))
|
||||
|
||||
(define (decode-flow l)
|
||||
(part-flow (decode-flow* l #f #f #f)))
|
||||
(part-flow (decode-flow* l #f #f #f #f)))
|
||||
|
||||
(define (match-newline-whitespace l)
|
||||
(cond
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
(require "struct.ss"
|
||||
(lib "class.ss")
|
||||
(lib "file.ss")
|
||||
(lib "list.ss")
|
||||
(lib "runtime-path.ss")
|
||||
(prefix xml: (lib "xml.ss" "xml")))
|
||||
(provide render-mixin
|
||||
|
@ -14,7 +15,8 @@
|
|||
|
||||
(define current-subdirectory (make-parameter #f))
|
||||
(define current-output-file (make-parameter #f))
|
||||
(define on-separate-page (make-parameter #f))
|
||||
(define on-separate-page (make-parameter #t))
|
||||
(define next-separate-page (make-parameter #f))
|
||||
(define collecting-sub (make-parameter 0))
|
||||
|
||||
;; ----------------------------------------
|
||||
|
@ -243,9 +245,15 @@
|
|||
(define/override (part-whole-page? d)
|
||||
(= 2 (collecting-sub)))
|
||||
|
||||
(define/private (toc-part? d)
|
||||
(and (styled-part? d)
|
||||
(eq? 'toc (styled-part-style d))))
|
||||
|
||||
(define/override (collect-part d parent ht number)
|
||||
(let ([prev-sub (collecting-sub)])
|
||||
(parameterize ([collecting-sub (add1 prev-sub)])
|
||||
(parameterize ([collecting-sub (if (toc-part? d)
|
||||
1
|
||||
(add1 prev-sub))])
|
||||
(if (= 1 prev-sub)
|
||||
(let ([filename (derive-filename d)])
|
||||
(parameterize ([current-output-file (build-path (path-only (current-output-file))
|
||||
|
@ -275,19 +283,43 @@
|
|||
|
||||
(inherit render-table)
|
||||
|
||||
(define/private (find-siblings d)
|
||||
(let ([parent (collected-info-parent (part-collected-info d))])
|
||||
(let loop ([l (if parent
|
||||
(part-parts parent)
|
||||
(if (null? (part-parts d))
|
||||
(list d)
|
||||
(list d (car (part-parts d)))))]
|
||||
[prev #f])
|
||||
(cond
|
||||
[(eq? (car l) d) (values prev
|
||||
(and (pair? (cdr l))
|
||||
(cadr l)))]
|
||||
[else (loop (cdr l) (car l))]))))
|
||||
|
||||
(define/private (navigation d ht)
|
||||
(let ([parent (collected-info-parent (part-collected-info d))])
|
||||
(let-values ([(prev next)
|
||||
(let loop ([l (if parent
|
||||
(part-parts parent)
|
||||
(if (null? (part-parts d))
|
||||
(list d)
|
||||
(list d (car (part-parts d)))))]
|
||||
[prev #f])
|
||||
(cond
|
||||
[(eq? (car l) d) (values prev (and (pair? (cdr l))
|
||||
(cadr l)))]
|
||||
[else (loop (cdr l) (car l))]))])
|
||||
(let*-values ([(prev next) (find-siblings d)]
|
||||
[(prev) (if prev
|
||||
(let loop ([prev prev])
|
||||
(if (and (toc-part? prev)
|
||||
(pair? (part-parts prev)))
|
||||
(loop (car (last-pair (part-parts prev))))
|
||||
prev))
|
||||
(and parent
|
||||
(toc-part? parent)
|
||||
parent))]
|
||||
[(next) (cond
|
||||
[(and (toc-part? d)
|
||||
(pair? (part-parts d)))
|
||||
(car (part-parts d))]
|
||||
[(and (not next)
|
||||
parent
|
||||
(toc-part? parent))
|
||||
(let-values ([(prev next)
|
||||
(find-siblings parent)])
|
||||
next)]
|
||||
[else next])])
|
||||
(render-table (make-table
|
||||
'at-right
|
||||
(list
|
||||
|
@ -306,13 +338,17 @@
|
|||
sep-element
|
||||
(if parent
|
||||
(make-element
|
||||
(make-target-url "index.html")
|
||||
(make-target-url
|
||||
(if (toc-part? parent)
|
||||
(derive-filename parent)
|
||||
"index.html"))
|
||||
up-content)
|
||||
"")
|
||||
sep-element
|
||||
(make-element
|
||||
(and next
|
||||
(make-target-url (derive-filename next)))
|
||||
(if next
|
||||
(make-target-url (derive-filename next))
|
||||
"nonavigation")
|
||||
next-content))))))))
|
||||
d
|
||||
ht))))
|
||||
|
@ -321,7 +357,8 @@
|
|||
(let ([number (collected-info-number (part-collected-info d))])
|
||||
(cond
|
||||
[(and (not (on-separate-page))
|
||||
(= 1 (length number)))
|
||||
(or (= 1 (length number))
|
||||
(next-separate-page)))
|
||||
;; Render as just a link, and put the actual
|
||||
;; content in a new file:
|
||||
(let* ([filename (derive-filename d)]
|
||||
|
@ -334,16 +371,19 @@
|
|||
'truncate/replace)
|
||||
null))]
|
||||
[else
|
||||
(if ((length number) . <= . 1)
|
||||
;; Navigation bars;
|
||||
`(,@(navigation d ht)
|
||||
(p nbsp)
|
||||
,@(super render-part d ht)
|
||||
(p nbsp)
|
||||
,@(navigation d ht)
|
||||
(p nbsp))
|
||||
;; Normal section render
|
||||
(super render-part d ht))])))
|
||||
(let ([sep? (on-separate-page)])
|
||||
(parameterize ([next-separate-page (toc-part? d)]
|
||||
[on-separate-page #f])
|
||||
(if sep?
|
||||
;; Navigation bars;
|
||||
`(,@(navigation d ht)
|
||||
(p nbsp)
|
||||
,@(super render-part d ht)
|
||||
(p nbsp)
|
||||
,@(navigation d ht)
|
||||
(p nbsp))
|
||||
;; Normal section render
|
||||
(super render-part d ht))))])))
|
||||
|
||||
(super-new)))
|
||||
|
||||
|
|
|
@ -202,11 +202,8 @@
|
|||
font-family: monospace;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
color: red;
|
||||
text-align: right;
|
||||
font-size: medium;
|
||||
font-style: italic;
|
||||
.nonavigation {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.disable {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
[collected-info (or/c false/c collected-info?)]
|
||||
[flow flow?]
|
||||
[parts (listof part?)])]
|
||||
[(styled-part part) ([style any/c])]
|
||||
[(unnumbered-part part) ()]
|
||||
[flow ([paragraphs (listof flow-element?)])]
|
||||
[paragraph ([content list?])]
|
||||
|
|
|
@ -5,26 +5,23 @@
|
|||
|
||||
@title{A Guide to PLT Scheme}
|
||||
|
||||
This guide is intended for programmers who are new to Scheme, new to
|
||||
PLT Scheme, or new to some part of PLT Scheme.
|
||||
This guide is intended for programmers who are new to Scheme, new to PLT
|
||||
Scheme, or new to some part of PLT Scheme. It definitely assumes some
|
||||
programming experience. If you are new to programming, consider
|
||||
instead reading @|HtDP|. If you want a quick and pretty overview of PLT
|
||||
Scheme, start with @|Quick|.
|
||||
|
||||
If you are new to programming, consider instead reading @|HtDP|.
|
||||
|
||||
If you want a quicker, prettier, higher-level overview of PLT Scheme,
|
||||
start with @|Quick|.
|
||||
|
||||
For everyone else, this guide assumes some programming experience.
|
||||
After a somewhat gentle introduction to Scheme (chapters 1 through 4),
|
||||
we dive into the details of putting Scheme to work. This guide covers
|
||||
much of the PLT Scheme toolbox, but it leaves the precise details
|
||||
to @|MzScheme| and other reference manuals.
|
||||
@seclink["to-scheme"]{Chapter 2} provides a somewhat gentle
|
||||
introduction to Scheme. After that, this guide dives into the details
|
||||
of putting Scheme to work. Even though this guide covers much of the
|
||||
PLT Scheme toolbox, it leaves precise details to @|MzScheme| and other
|
||||
reference manuals.
|
||||
|
||||
@table-of-contents[]
|
||||
|
||||
@include-section["welcome.scrbl"]
|
||||
@include-section["syntax.scrbl"]
|
||||
@include-section["lists.scrbl"]
|
||||
@include-section["truth.scrbl"]
|
||||
|
||||
@include-section["to-scheme.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "datatypes"]{Built-In and Programmer-Defined Datatypes}
|
||||
|
|
|
@ -118,7 +118,7 @@ the @scheme[fold-for] syntax as follows:
|
|||
@interaction[
|
||||
(fold-for ([sum 0])
|
||||
([elem (list 1 2 3)])
|
||||
(+ sum elem))
|
||||
(+ sum (* elem elem)))
|
||||
]
|
||||
|
||||
Compare to analogous Java code, where @scheme[(list 1 2 3)] is
|
||||
|
@ -128,7 +128,7 @@ replaced by a collection @scheme[lst]:
|
|||
#<<EOS
|
||||
int sum = 0;
|
||||
for (Object elem : lst) {
|
||||
sum = sum + elem;
|
||||
sum = sum + elem * elem;
|
||||
}
|
||||
return sum;
|
||||
EOS
|
||||
|
@ -187,7 +187,7 @@ Scheme programmers tend to use them, partly because the syntax is
|
|||
simpler (just a procedure call).
|
||||
|
||||
We have ignored several other variants of the interation
|
||||
form---including plain @scheme[for], which is use when the iteration
|
||||
form---including plain @scheme[for], which is used when the iteration
|
||||
body is to be run only for its effect. For more complete information,
|
||||
see @secref["iterations+comprehensions"].
|
||||
|
||||
|
|
|
@ -4,29 +4,29 @@
|
|||
@require[(lib "bnf.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "syntax-overview"]{Basic Scheme Syntax}
|
||||
@title[#:tag "syntax-overview"]{Simple Definitions and Expressions}
|
||||
|
||||
The syntax of a Scheme program is specified in an unusual way compared
|
||||
to most programming languages. In particular, importing a module can
|
||||
introduce new definition and expression forms, so the syntax of a
|
||||
Scheme module cannot be written as a context-free grammar. Even more
|
||||
radically, the language name after @schemefont{#module} determines the
|
||||
token-level syntax of the code that follows it.
|
||||
A program module is written as
|
||||
|
||||
As a starting point, however, we can pretend that Scheme's syntax
|
||||
follows a context-free grammar. We'll start with this approximation,
|
||||
and work from there to build up a more complete picture of the
|
||||
language.
|
||||
@schemeblock[
|
||||
#, @BNF-seq[@litchar{#module} @nonterm{langname} @kleenestar{@nonterm{topform}}]
|
||||
]
|
||||
|
||||
The following BNF grammar sketches a simplified syntax for Scheme.
|
||||
Text with a gray background, such as @litchar{#module}, represents
|
||||
literal text. Whitespace must appear between separate such literals
|
||||
and nonterminals like @nonterm{id}, except that whitespace is
|
||||
not required before or after @litchar{(}, @litchar{)}, @litchar{[}, or
|
||||
@litchar{]}. Following the usual conventions, @kleenestar{} means
|
||||
zero or more repetitions of the preceding element, @kleeneplus{} means
|
||||
one or more repetitions of the preceding element, and @BNF-group{}
|
||||
groups a sequence as an element for repetition.
|
||||
where a @nonterm{topform} is either a @nonterm{definition} or an
|
||||
@nonterm{expr}. The REPL also evaluates @nonterm{topform}s.
|
||||
|
||||
In syntax specifications, text with a gray background, such as
|
||||
@litchar{#module}, represents literal text. Whitespace must appear
|
||||
between separate such literals and nonterminals like @nonterm{id},
|
||||
except that whitespace is not required before or after @litchar{(},
|
||||
@litchar{)}, @litchar{[}, or @litchar{]}. A comment, which starts
|
||||
with @litchar{;} and runs until the end of the line, is treated the
|
||||
same as whitespace.
|
||||
|
||||
Following the usual conventions, @kleenestar{} in a grammar means zero
|
||||
or more repetitions of the preceding element, @kleeneplus{} means one
|
||||
or more repetitions of the preceding element, and @BNF-group{} groups
|
||||
a sequence as an element for repetition.
|
||||
|
||||
@define[val-defn-stx @BNF-seq[@litchar{(}@litchar{define} @nonterm{id} @nonterm{expr} @litchar{)}]]
|
||||
@define[fun-defn-stx
|
||||
|
@ -57,29 +57,6 @@ groups a sequence as an element for repetition.
|
|||
@define[let-expr-stx (make-let-expr-stx @litchar{let})]
|
||||
@define[let*-expr-stx (make-let-expr-stx @litchar{let*})]
|
||||
|
||||
|
||||
@BNF[(list @nonterm{module} @BNF-seq[@litchar{#module} @nonterm{langname} @kleenestar{@nonterm{topform}}])
|
||||
(list @nonterm{topform} @nonterm{definition}
|
||||
@nonterm{expr}
|
||||
@BNF-etc)
|
||||
(list @nonterm{definition} val-defn-stx
|
||||
fun-defn-stx
|
||||
@BNF-etc)
|
||||
(list @nonterm{expr} @nonterm{id}
|
||||
@nonterm{constant}
|
||||
app-expr-stx
|
||||
if-expr-stx
|
||||
lambda-expr-stx
|
||||
let-expr-stx
|
||||
let*-expr-stx
|
||||
@BNF-etc)]
|
||||
|
||||
The syntax for comments, which are are treated the same as whitespace,
|
||||
is not shown in the grammar above. A comment starts with @litchar{;}
|
||||
and runs until the end of the line.
|
||||
|
||||
The REPL evaluates @nonterm{topform}s, just like the body of a module.
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Definitions}
|
||||
|
||||
|
@ -116,18 +93,6 @@ piece
|
|||
substring
|
||||
]
|
||||
|
||||
Within a module, each definition must bind a distinct
|
||||
@nonterm{id}, and only identifiers without an imported binding
|
||||
can be defined. A definition in the REPL, in contrast, overwrites any
|
||||
previous definition for the same @nonterm{id}.
|
||||
|
||||
@examples[
|
||||
(define five 5)
|
||||
(substring "hello world" 0 five)
|
||||
(define five 8)
|
||||
(substring "hello world" 0 five)
|
||||
]
|
||||
|
||||
A procedure definition can include multiple expressions for the
|
||||
procedure's body. In that case, only the value of the last expression
|
||||
is returned when the procedure is called. The other expressions are
|
||||
|
@ -140,12 +105,10 @@ evaluated only for some side-effect, such as printing.
|
|||
(greet "universe")
|
||||
]
|
||||
|
||||
You should generally avoid side-effects in Scheme; printing is a
|
||||
reasonable effect to use in some programs, but it's no substitute for
|
||||
simply returning a value. In any case, you should understand that
|
||||
multiple expressions are allowed in a definition body, because it
|
||||
explains why the following @scheme[nogreet] procedure simply returns
|
||||
its argument:
|
||||
Scheme programmers prefer to avoid assignment statements; it's
|
||||
important, though, to understand that multiple expressions are allowed
|
||||
in a definition body, because it explains why the following
|
||||
@scheme[nogreet] procedure simply returns its argument:
|
||||
|
||||
@def+int[
|
||||
(define (nogreet name)
|
||||
|
@ -187,66 +150,6 @@ more examples:
|
|||
#, @schemeid[call/cc]
|
||||
#, @schemeid[call-with-composable-continuation]
|
||||
#, @schemeid[x-1+3i]
|
||||
#, @schemeid[define]
|
||||
]
|
||||
|
||||
Since @schemeid[define] is itself an identifier, you could
|
||||
re-define @schemeid[define] in the REPL. That's rarely a good idea,
|
||||
of course, and it's not allowed in any module where
|
||||
@scheme[define] already has a meaning.
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Constants}
|
||||
|
||||
Scheme constants include numbers, booleans, strings, and byte
|
||||
strings. In documentation examples and in DrScheme, constant
|
||||
expressions are shown in green.
|
||||
|
||||
@defterm{Numbers} are written in the usual way, including fractions
|
||||
and imagnary numbers. Numbers that use decimal points or exponent
|
||||
markers are implemented as double-precision floating-point numbers,
|
||||
and they are called @defterm{inexact} numbers in Scheme
|
||||
terminology. Other numbers are implemented as @defterm{exact} with
|
||||
arbitrary precision. In the example number constants below, the ones
|
||||
on the left are exact, and the ones on the right are inexact
|
||||
approximations:
|
||||
|
||||
@schemeblock[
|
||||
1 1.0
|
||||
1/2 0.5
|
||||
1+2i 1.0+2i
|
||||
9999999999999999999999 1e+22
|
||||
]
|
||||
|
||||
@defterm{Booleans} are @scheme[#t] for true and @scheme[#f] for
|
||||
false. In conditionals, however, all non-@scheme[#f] values are
|
||||
treated as true.
|
||||
|
||||
@defterm{Strings} are written between double quotes. Within a string,
|
||||
backslash is an escaping character; for example, a backslash followed
|
||||
by a double-quote includes a little double-quote in the string. Except
|
||||
for an unescaped double-quote or backslash, any Unicode character can
|
||||
appear in a string constant.
|
||||
|
||||
@schemeblock[
|
||||
"hello world"
|
||||
"A \"fancy\" string"
|
||||
"\u03BBx:(\u03BC\u03B1.\u03B1\u2192\u03B1).xx"
|
||||
]
|
||||
|
||||
When a constant is evaluated in the REPL, it typically prints the same
|
||||
as its input syntax. In some cases, the printed form is a normalized
|
||||
version of the input syntax. In other cases, the printed result of an
|
||||
expression does not correspond to input syntax at all, such as when an
|
||||
expression proceduces a procedure (instead of applying the
|
||||
procedure). In documentation and in DrScheme's REPL, results are
|
||||
printed in blue instead of green to highlight the difference between
|
||||
an input expression and a printed result.
|
||||
|
||||
@examples[
|
||||
(eval-example-string "1.0000")
|
||||
(eval-example-string "\"A \\u0022fancy\\u0022 string\"")
|
||||
string-append
|
||||
]
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -426,10 +329,9 @@ few key places makes Scheme code even more readable.
|
|||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Procedure Applications, Again}
|
||||
|
||||
In our pretend grammar of Scheme, we oversimplified in the description
|
||||
of procedure applications. The actual syntax of a procedure
|
||||
application allows an arbitrary expression for the procedure, instead
|
||||
of just an @nonterm{id}:
|
||||
In our earlier grammar procedure applications, we oversimplified. The
|
||||
actual syntax of a procedure application allows an arbitrary
|
||||
expression for the procedure, instead of just an @nonterm{id}:
|
||||
|
||||
@schemeblock[
|
||||
#, app2-expr-stx
|
||||
|
@ -557,14 +459,15 @@ louder
|
|||
]
|
||||
|
||||
Note that the expression for @scheme[louder] in the second case is an
|
||||
``anonymous'' procedure written with @scheme[lambda], but the compiler
|
||||
infers a name, anyway, for the purpose of printing the procedure.
|
||||
``anonymous'' procedure written with @scheme[lambda], but, if
|
||||
possible, the compiler infers a name, anyway, to make printing and
|
||||
error reporting as informative as possible.
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section[#:tag "local-binding-intro"]{Local Binding with with
|
||||
@scheme[define], @scheme[let], and @scheme[let*]}
|
||||
@section[#:tag "local-binding-intro"]{Local Binding with
|
||||
@scheme[define], @scheme[let], and @scheme[let*]}
|
||||
|
||||
It's time to retract another simplification in our pretend grammar of
|
||||
It's time to retract another simplification in our grammar of
|
||||
Scheme. In the body of a procedure, definitions can appear before the
|
||||
body expressions:
|
||||
|
||||
|
@ -623,36 +526,3 @@ use earlier bindings:
|
|||
[z (+ x y)])
|
||||
(format "adding ~s and ~s produces ~s" x y z))
|
||||
]
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{The Language So Far}
|
||||
|
||||
As you saw, the little grammar that we showed at the
|
||||
@seclink["syntax-overview"]{beginning} of the chapter turned out to be
|
||||
too simple even for this chapter. Here's the grammar that we have now:
|
||||
|
||||
@BNF[(list @nonterm{module} @BNF-seq[@litchar{#module} @nonterm{langname} @kleenestar{@nonterm{topform}}])
|
||||
(list @nonterm{topform} @nonterm{definition}
|
||||
@nonterm{expr}
|
||||
@BNF-etc)
|
||||
(list @nonterm{definition} val-defn-stx
|
||||
fun-defn2-stx
|
||||
@BNF-etc)
|
||||
(list @nonterm{expr} @nonterm{id}
|
||||
@nonterm{constant}
|
||||
app2-expr-stx
|
||||
if-expr-stx
|
||||
or-expr-stx
|
||||
and-expr-stx
|
||||
cond-expr-stx
|
||||
lambda2-expr-stx
|
||||
let-expr-stx
|
||||
let*-expr-stx
|
||||
@BNF-etc)]
|
||||
|
||||
For an expanded grammar, it's still a pretty small language! This
|
||||
language is enough, however, to write lots of interesting programs.
|
||||
|
||||
Depending on your programming background, you may be struck by the
|
||||
apparent absence of an iteration form. We'll add one in the next
|
||||
chapter, but also explain why it isn't really necessary.
|
||||
|
|
|
@ -49,8 +49,8 @@ mistake, such as accidentally reversing the arguments to
|
|||
|
||||
Non-list pairs are used intentionally, sometimes. For example, the
|
||||
@scheme[make-immutable-hash-table] procedure takes a list of pairs,
|
||||
where the @scheme[car] of each pair is a key and the @scheme[cdr] is a
|
||||
value.
|
||||
where the @scheme[car] of each pair is a key and the @scheme[cdr] is an
|
||||
arbitrary value.
|
||||
|
||||
The only thing more confusing to new Schemers than non-list pairs is
|
||||
the printing convention for pairs where the second element @italic{is}
|
||||
|
@ -182,11 +182,6 @@ Beware, however, that the REPL's printer recognizes the symbol
|
|||
(eval:alts '(#, @schemevalfont{quote} #, @schemevalfont{road}) ''road)
|
||||
]
|
||||
|
||||
There's a method to this madness; it has to do with the true nature of
|
||||
Scheme syntax (which we discuss in the next section) and the
|
||||
traditional Lisp approach to meta-programming (which we discuss in the
|
||||
@seclink["quote-eval"]{section afterward}).
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Lists and Scheme Syntax}
|
||||
|
||||
|
@ -225,35 +220,6 @@ way of writing @scheme[(+ 1 2)]. It is practically never a good idea
|
|||
to write application expressions using this dot notation; it's just a
|
||||
consequence of the way Scheme's syntax is defined.
|
||||
|
||||
The rule for converting @litchar{'} to a use of @scheme[quote] is also
|
||||
defined at the read level. If you (accidentally) use
|
||||
@schemeidfont{quote} as an identifier, the result makes sense only
|
||||
when you understand the reader's conversion:
|
||||
|
||||
@def+int[
|
||||
(define (shakespeare quot)
|
||||
(list 'shakespeare 'says quot))
|
||||
(shakespeare "to be or not to be")]
|
||||
@schemeblock[
|
||||
(define (shakey #, @schemeidfont{quote})
|
||||
(list '#, @schemeidfont{shakey} '#, @schemeidfont{says} #, @schemeidfont{quote}))
|
||||
]
|
||||
|
||||
@interaction[
|
||||
(eval:alts (shakey "to be or not to be") (let ([shakey (lambda (x) x)]) ("to be or not to be" shakey)))
|
||||
]
|
||||
|
||||
The second example fails because @scheme['#, @schemeidfont{shakey}] is
|
||||
really @scheme[(#, @schemeidfont{quote} #, @schemeidfont{shakey})],
|
||||
which means the application of @scheme[shakey]'s argument (which turns
|
||||
out to be a string, not a procedure).
|
||||
|
||||
A few other character combinations trigger @litchar{'}-like
|
||||
conversions, including @litchar{`}, @litchar{,}, @litchar["@,"], and
|
||||
@litchar{#`}. Also, @litchar{#module big} triggers a read-time
|
||||
conversion that bundles file content into a single
|
||||
@scheme[module] declaration (see @secref["module"]).
|
||||
|
||||
Normally, @litchar{.} is allowed by the reader only with a
|
||||
parenthesized sequence, and only before the last element of the
|
||||
sequence. However, a pair of @litchar{.}s can also appear around a
|
||||
|
@ -271,11 +237,3 @@ This two-dot convension is non-traditional, and it has essentially
|
|||
nothing to do with the dot notation for non-list pairs. PLT Scheme
|
||||
programmers use the infix convension sparingly---mostly for asymmetric
|
||||
binary operators such as @scheme[<] and @scheme[is-a?].
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "eval-quote"]{Traditional Metaprogramming}
|
||||
|
||||
[The whole quote and printer thing has to do with manipulating
|
||||
programs as represented by pairs, symbols, etc. Not usually a good
|
||||
idea anymore...]
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ Depending on how you look at it, @bold{PLT Scheme} is
|
|||
|
||||
@itemize{
|
||||
|
||||
@item{a @defterm{programming language}---a dialect of Scheme, which
|
||||
@item{a @defterm{programming language}---a descendant of Scheme, which
|
||||
is a dialect of Lisp;}
|
||||
|
||||
@item{a @defterm{family} of programming languages---variants of
|
||||
|
@ -37,12 +37,12 @@ Most likely, you'll want to explore PLT Scheme using DrScheme,
|
|||
especially at the beginning. If you prefer, you can also work with the
|
||||
command-line @exec{mzscheme} interpreter and your favorite text
|
||||
editor. The rest of this guide presents the language mostly
|
||||
independent of the tool that you use.
|
||||
independent of your choice of editor.
|
||||
|
||||
If you're using DrScheme, you'll need to set it in the right mode,
|
||||
because DrScheme is less biased to a particular Scheme variant than
|
||||
@exec{mzscheme}. Assuming that you've never used DrScheme before,
|
||||
start it up, type the line
|
||||
If you're using DrScheme, you'll need to choose the proper language,
|
||||
because DrScheme accommodates many different variants of
|
||||
Scheme. Assuming that you've never used DrScheme before, start it up,
|
||||
type the line
|
||||
|
||||
@schememod[big]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user