Merge remote branch 'origin/master' into samth/new-logic2

Conflicts:
	collects/tests/typed-scheme/unit-tests/typecheck-tests.rkt
This commit is contained in:
Sam Tobin-Hochstadt 2010-04-30 13:48:49 -04:00
commit 5e9ae84b15
224 changed files with 1810 additions and 1733 deletions

View File

@ -1,6 +1,6 @@
#lang scheme/load
(require rktunit)
(require racunit)
(require 2htdp/batch-io)
(define file "batch-io.txt")

View File

@ -45,7 +45,7 @@
scheme/math
scheme/class
scheme/gui/base
rktunit
racunit
(prefix-in 1: htdp/image)
(only-in lang/htdp-advanced equal~?))

View File

@ -662,7 +662,7 @@ mz-extras :+= (- (package: "unstable")
;; -------------------- plai
plt-extras :+= (package: "plai/")
plt-extras :+= (package: "rktunit/")
plt-extras :+= (package: "racunit/")
plt-extras :+= (package: "schemeunit/")
;; ============================================================================

View File

@ -615,26 +615,26 @@
("schematics" "port.plt" 1 0 #f)
("schematics" "random.plt" 1 0 #f)
("schematics" "sake.plt" 1 0 "4.0")
("schematics" "rktunit.plt" 3 4 "4.0")
("schematics" "rktunit.plt" 3 3 "4.0")
("schematics" "rktunit.plt" 3 2 "4.0")
("schematics" "rktunit.plt" 3 1 "4.0")
("schematics" "rktunit.plt" 3 0 "4.0")
("schematics" "rktunit.plt" 2 11 "4.1.0.3")
("schematics" "rktunit.plt" 2 10 "369.1")
("schematics" "rktunit.plt" 2 9 "369.1")
("schematics" "rktunit.plt" 2 8 "369.1")
("schematics" "rktunit.plt" 2 7 "369.1")
("schematics" "rktunit.plt" 2 6 "369.1")
("schematics" "rktunit.plt" 2 5 "369.1")
("schematics" "rktunit.plt" 2 4 "369.1")
("schematics" "rktunit.plt" 2 3 #f)
("schematics" "rktunit.plt" 2 2 #f)
("schematics" "rktunit.plt" 2 1 #f)
("schematics" "rktunit.plt" 2 0 #f)
("schematics" "rktunit.plt" 1 2 #f)
("schematics" "rktunit.plt" 1 1 #f)
("schematics" "rktunit.plt" 1 0 #f)
("schematics" "racunit.plt" 3 4 "4.0")
("schematics" "racunit.plt" 3 3 "4.0")
("schematics" "racunit.plt" 3 2 "4.0")
("schematics" "racunit.plt" 3 1 "4.0")
("schematics" "racunit.plt" 3 0 "4.0")
("schematics" "racunit.plt" 2 11 "4.1.0.3")
("schematics" "racunit.plt" 2 10 "369.1")
("schematics" "racunit.plt" 2 9 "369.1")
("schematics" "racunit.plt" 2 8 "369.1")
("schematics" "racunit.plt" 2 7 "369.1")
("schematics" "racunit.plt" 2 6 "369.1")
("schematics" "racunit.plt" 2 5 "369.1")
("schematics" "racunit.plt" 2 4 "369.1")
("schematics" "racunit.plt" 2 3 #f)
("schematics" "racunit.plt" 2 2 #f)
("schematics" "racunit.plt" 2 1 #f)
("schematics" "racunit.plt" 2 0 #f)
("schematics" "racunit.plt" 1 2 #f)
("schematics" "racunit.plt" 1 1 #f)
("schematics" "racunit.plt" 1 0 #f)
("schematics" "si.plt" 1 0 #f)
("schematics" "spgsql.plt" 2 3 "371.3")
("schematics" "spgsql.plt" 2 2 "371.3")

View File

@ -1127,17 +1127,18 @@ path/s is either such a string or a list of them.
"collects/scheme/gui.rkt" drdr:command-line "mred-text -t ~s"
"collects/scheme/match" responsible (samth)
"collects/scheme/match.rkt" responsible (samth)
"collects/rktunit" responsible (jay noel ryanc)
"collects/racunit" responsible (jay noel ryanc)
"collects/schemeunit" responsible (jay)
"collects/rktunit/gui.rkt" responsible (ryanc) drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui" responsible (ryanc)
"collects/rktunit/private/gui/config.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui/controller.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui/gui.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui/model2rml.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui/rml.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/private/gui/view.rkt" drdr:command-line "mred-text -t ~s"
"collects/rktunit/tool.rkt" responsible (ryanc) drdr:command-line "mred-text -t ~s"
"collects/schemeunit/gui.rkt" responsible (jay) drdr:command-line "mred-text -t ~s"
"collects/racunit/gui.rkt" responsible (ryanc) drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui" responsible (ryanc)
"collects/racunit/private/gui/config.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui/controller.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui/gui.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui/model2rml.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui/rml.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/private/gui/view.rkt" drdr:command-line "mred-text -t ~s"
"collects/racunit/tool.rkt" responsible (ryanc) drdr:command-line "mred-text -t ~s"
"collects/scribble/run.rkt" drdr:command-line "mzc ~s"
"collects/scribble/tools/drscheme-buttons.rkt" drdr:command-line "mred-text ~s"
"collects/scribble/tools/private/mk-drs-bitmaps.rkt" drdr:command-line "mred-text ~s" drdr:timeout 240
@ -1584,7 +1585,7 @@ path/s is either such a string or a list of them.
"collects/tests/planet/examples/dummy-module.rkt" drdr:command-line ""
"collects/tests/plot/run-tests.rkt" drdr:command-line "mred-text -t ~s"
"collects/tests/run-automated-tests.rkt" drdr:command-line "mzc -k ~s" drdr:timeout 600
"collects/tests/rktunit" responsible (jay noel)
"collects/tests/racunit" responsible (jay noel)
"collects/tests/srfi/1/run-tests.rkt" drdr:command-line "mzscheme -f ~s"
"collects/tests/srfi/40/run-tests.rkt" drdr:command-line "mzscheme -f ~s"
"collects/tests/srfi/43/run-tests.rkt" drdr:command-line "mzscheme -f ~s"

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require (for-syntax scheme/base)
"../lex.ss"
rktunit)
racunit)
(define-syntax (catch-syn-error stx)
(syntax-case stx ()

View File

@ -22,7 +22,7 @@
(unpack-blame pos)
"<<unknown party>>"
#t
name)
"<<unknown party>>")
x
fmt
args))
@ -60,7 +60,7 @@
(unpack-blame (if original? pos neg))
(unpack-blame (if original? neg pos))
original?
name)))))
(unpack-blame (if original? neg pos)))))))
(define (legacy-property name)
(define-values [ prop pred get ]

View File

@ -5,13 +5,15 @@
racket/struct-info))
(provide (all-from-out "private/serialize.ss")
serializable-struct
serializable-struct/versions
define-serializable-struct
define-serializable-struct/versions)
(define-syntax (define-serializable-struct/versions/derived stx)
(syntax-case stx ()
;; First check `id/sup':
[(_ orig-stx id/sup . _)
[(_ orig-stx make-prefix? id/sup . _)
(not (or (identifier? #'id/sup)
(syntax-case #'id/sup ()
[(id sup) (and (identifier? #'id)
@ -22,11 +24,11 @@
;; Not valid, so let `define-struct/derived' complain:
#'(define-struct/derived orig-stx id/sup ())]
;; Check version:
[(_ orig-stx id/sup vers . _)
[(_ orig-stx make-prefix? id/sup vers . _)
(not (exact-nonnegative-integer? (syntax-e #'vers)))
(raise-syntax-error #f "expected a nonnegative exact integer for a version" #'orig-stx #'vers)]
;; Main case:
[(_ orig-stx id/sup vers (field ...) ([other-vers make-proc-expr cycle-make-proc-expr] ...)
[(_ orig-stx make-prefix? id/sup vers (field ...) ([other-vers make-proc-expr cycle-make-proc-expr] ...)
prop ...)
(let* ([id (if (identifier? #'id/sup)
#'id/sup
@ -35,10 +37,22 @@
#f
(extract-struct-info (syntax-local-value (cadr (syntax->list #'id/sup)))))]
[fields (syntax->list #'(field ...))]
[maker (datum->syntax id
[given-maker (let loop ([props (syntax->list #'(prop ...))])
(cond
[(null? props) #f]
[(null? (cdr props)) #f]
[(or (eq? (syntax-e (car props)) '#:constructor-name)
(eq? (syntax-e (car props)) '#:extra-constructor-name))
(and (identifier? (cadr props))
(cadr props))]
[else (loop (cdr props))]))]
[maker (or given-maker
(if (syntax-e #'make-prefix?)
(datum->syntax id
(string->symbol
(format "make-~a" (syntax-e id)))
id)]
id)
id))]
[getters (map (lambda (field)
(datum->syntax
id
@ -103,6 +117,10 @@
id/sup
(field ...)
prop ...
#,@(if (or given-maker
(syntax-e #'make-prefix?))
null
(list #'#:constructor-name id))
#:property prop:serializable
(make-serialize-info
;; The struct-to-vector function: --------------------
@ -203,14 +221,38 @@
(define-syntax (define-serializable-struct/versions stx)
(syntax-case stx ()
[(_ . rest)
#`(define-serializable-struct/versions/derived #,stx . rest)]))
#`(define-serializable-struct/versions/derived #,stx #t . rest)]))
(define-syntax (serializable-struct/versions stx)
(syntax-case stx ()
[(_ id super-id . rest)
(and (identifier? #'id)
(identifier? #'super-id))
#`(define-serializable-struct/versions/derived #,stx #f (id super-id) . rest)]
[(_ id vers (field ...) . rest)
(and (identifier? #'id)
(number? (syntax-e #'vers)))
#`(define-serializable-struct/versions/derived #,stx #f id vers (field ...) . rest)]))
(define-syntax (define-serializable-struct stx)
(syntax-case stx ()
[(_ id/sup (field ...) prop ...)
#`(define-serializable-struct/versions/derived #,stx
#`(define-serializable-struct/versions/derived #,stx #t
id/sup 0 (field ...) () prop ...)]
[(_ . rest)
#`(define-struct/derived #,stx . rest)]))
(define-syntax (serializable-struct stx)
(syntax-case stx ()
[(_ id super-id (field ...) prop ...)
(and (identifier? #'id)
(identifier? #'super-id))
#`(define-serializable-struct/versions/derived #,stx #f
(id super-id) 0 (field ...) () prop ...)]
[(_ id (field ...) prop ...)
(and (identifier? #'id)
(identifier? #'super-id))
#`(define-serializable-struct/versions/derived #,stx #f
id 0 (field ...) () prop ...)]))
)

View File

@ -6,7 +6,7 @@
(define (test/gui . tests)
(apply (make-gui-runner) tests))
(define test/c (or/c rktunit-test-case? rktunit-test-suite?))
(define test/c (or/c racunit-test-case? racunit-test-suite?))
(provide/contract
[test/gui

View File

@ -1,13 +1,13 @@
#lang setup/infotab
(define name "RktUnit")
(define name "RacUnit")
(define blurb '((p "RktUnit is a unit testing framework based on the "
(define blurb '((p "RacUnit is a unit testing framework based on the "
" Extreme Programming unit test frameworks")))
(define scribblings '(("scribblings/rktunit.scrbl" (multi-page) (tool))))
(define scribblings '(("scribblings/racunit.scrbl" (multi-page) (tool))))
(define tools '[("tool.rkt")])
(define tool-names '["RktUnit DrRacket integration"])
(define tool-names '["RacUnit DrRacket integration"])
(define homepage "http://schematics.sourceforge.net/")
(define url "http://schematics.sourceforge.net/")

View File

@ -4,10 +4,10 @@
;; struct test :
(define-struct test ())
;; struct (rktunit-test-case test) : (U string #f) thunk
(define-struct (rktunit-test-case test) (name action) #:transparent)
;; struct (rktunit-test-suite test) : string (fdown fup fhere seed -> (listof test-result)) thunk thunk
(define-struct (rktunit-test-suite test) (name tests before after) #:transparent)
;; struct (racunit-test-case test) : (U string #f) thunk
(define-struct (racunit-test-case test) (name action) #:transparent)
;; struct (racunit-test-suite test) : string (fdown fup fhere seed -> (listof test-result)) thunk thunk
(define-struct (racunit-test-suite test) (name tests before after) #:transparent)
;; struct exn:test exn : ()
;;
@ -33,10 +33,10 @@
(define-struct (test-success test-result) (result))
(provide/contract
(struct (rktunit-test-case test)
(struct (racunit-test-case test)
((name (or/c string? false/c))
(action (-> any))))
(struct (rktunit-test-suite test)
(struct (racunit-test-suite test)
((name string?)
(tests procedure?)
(before (-> any))

View File

@ -11,7 +11,7 @@
;; Infrastructure ----------------------------------------------
;; The continuation mark under which all check-info is keyed
(define check-info-mark (gensym 'rktunit))
(define check-info-mark (gensym 'racunit))
;; (continuation-mark-set -> (listof check-info))
(define (check-info-stack marks)

View File

@ -5,20 +5,20 @@
;; Frame size preferences
(preferences:set-default 'rktunit:frame:width 400 exact-positive-integer?)
(preferences:set-default 'rktunit:frame:height 400 exact-positive-integer?)
(define pref:width (pref:get/set 'rktunit:frame:width))
(define pref:height (pref:get/set 'rktunit:frame:height))
(preferences:set-default 'racunit:frame:width 400 exact-positive-integer?)
(preferences:set-default 'racunit:frame:height 400 exact-positive-integer?)
(define pref:width (pref:get/set 'racunit:frame:width))
(define pref:height (pref:get/set 'racunit:frame:height))
;; CONSTANTS
;; Some of these are obsolete, given the preferences above.
(define DETAILS-CANVAS-INIT-WIDTH 400)
(define FRAME-LABEL "RktUnit")
(define FRAME-LABEL "RacUnit")
(define FRAME-INIT-HEIGHT 400)
(define TREE-INIT-WIDTH 240)
(define TREE-COLORIZE-CASES #t)
(define DIALOG-ERROR-TITLE "RktUnit: Error")
(define DIALOG-ERROR-TITLE "RacUnit: Error")
(define STATUS-SUCCESS 'success)
(define STATUS-FAILURE 'failure)
(define STATUS-ERROR 'error)

View File

@ -25,18 +25,18 @@
;; create-model : test suite<%>/#f -> result<%>
(define/public (create-model test parent)
(define result
(cond [(rktunit-test-case? test)
(cond [(racunit-test-case? test)
(new case-result%
(controller this)
(test test)
(name (or (rktunit-test-case-name test)
(name (or (racunit-test-case-name test)
"<unnamed test-case>"))
(parent parent))]
[(rktunit-test-suite? test)
[(racunit-test-suite? test)
(new suite-result%
(controller this)
(test test)
(name (or (rktunit-test-suite-name test)
(name (or (racunit-test-suite-name test)
"<unnamed test-suite>"))
(parent parent))]))
(send/i view view<%> create-view-link result parent)

View File

@ -48,8 +48,8 @@
#|
(define/public (run)
(let ([custodian (make-custodian)]
[before (rktunit-test-suite-before test)]
[after (rktunit-test-suite-after test)])
[before (racunit-test-suite-before test)]
[after (racunit-test-suite-after test)])
(parameterize [(current-custodian custodian)]
(dynamic-wind
before
@ -112,8 +112,8 @@
(call-with-continuation-prompt
(lambda ()
(time-apply run-test-case
(list (rktunit-test-case-name test)
(rktunit-test-case-action test)))))])
(list (racunit-test-case-name test)
(racunit-test-case-action test)))))])
(values (car results) (list cputime realtime gctime))))
(define (make-output-ports)

View File

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 513 B

View File

@ -7,7 +7,7 @@
(provide insert-text
ext:text%
rktunit-style-map)
racunit-style-map)
;; insert-text : text% string style-delta% -> void
(define (insert-text e text style)
@ -20,7 +20,7 @@
(define ext:text-mixin
(mixin (text<%>) ()
(init-field (style-map rktunit-style-map))
(init-field (style-map racunit-style-map))
(inherit last-position
change-style
set-clickback
@ -139,7 +139,7 @@
[error . ,style:red]
[value . ,style:darkblue]))
(define rktunit-styles
(define racunit-styles
`([test-unexecuted . ,style:gray]
[test-success . ,style:green]
[test-failure . ,style:red]
@ -181,7 +181,7 @@
(extend-style-map empty-style-map
basic-styles))
;; rktunit-style-map : style-map<%>
(define rktunit-style-map
;; racunit-style-map : style-map<%>
(define racunit-style-map
(extend-style-map basic-style-map
rktunit-styles))
racunit-styles))

View File

@ -13,7 +13,7 @@
(provide make-view-frame
view%)
(define style-map rktunit-style-map)
(define style-map racunit-style-map)
#|
@ -50,7 +50,7 @@ still be there, just not visible?
controller)
(super-new)
(define editor (new ext:text% (style-map rktunit-style-map)))
(define editor (new ext:text% (style-map racunit-style-map)))
(define renderer
(new model-renderer%
(controller controller)
@ -146,7 +146,7 @@ still be there, just not visible?
;; If the view-link has not been created,
;; yield until it is.
(unless (yield)
(error 'rktunit-gui
(error 'racunit-gui
"internal error: no progress waiting for view-link"))
(do-model-update model)])))

View File

@ -51,12 +51,12 @@
;; data so FP is a bit ugly].
(define (foldts fdown fup fhere seed test)
(cond
((rktunit-test-case? test)
((racunit-test-case? test)
(fhere test
(rktunit-test-case-name test)
(rktunit-test-case-action test)
(racunit-test-case-name test)
(racunit-test-case-action test)
seed))
((rktunit-test-suite? test)
((racunit-test-suite? test)
(apply-test-suite test fdown fup fhere seed))
(else
(raise

View File

@ -27,14 +27,14 @@
(define (test-suite-test-case-around fhere)
(lambda (thunk)
(let* ([name (current-test-name)]
[test (make-rktunit-test-case name thunk)]
[test (make-racunit-test-case name thunk)]
[seed (current-seed)])
(current-seed (fhere test name thunk seed)))))
(define (test-suite-check-around fhere)
(lambda (thunk)
(let* ([name #f]
[test (make-rktunit-test-case name thunk)]
[test (make-racunit-test-case name thunk)]
[seed (current-seed)])
(current-seed (fhere test name thunk seed)))))
@ -42,12 +42,12 @@
(define delayed-test-case-around
(lambda (thunk)
(let ([name (current-test-name)])
(make-rktunit-test-case name thunk))))
(make-racunit-test-case name thunk))))
(define delayed-check-around
(lambda (thunk)
(let ([name #f])
(make-rktunit-test-case name thunk))))
(make-racunit-test-case name thunk))))
(define-syntax delay-test
(syntax-rules ()
@ -58,12 +58,12 @@
test test1 ...)]))
(define (apply-test-suite suite fdown fup fhere seed)
(let* ([name (rktunit-test-suite-name suite)]
[tests (rktunit-test-suite-tests suite)]
[before (rktunit-test-suite-before suite)]
[after (rktunit-test-suite-after suite)]
(let* ([name (racunit-test-suite-name suite)]
[tests (racunit-test-suite-tests suite)]
[before (racunit-test-suite-before suite)]
[after (racunit-test-suite-after suite)]
[kid-seed (fdown suite name before after seed)]
[kid-seed ((rktunit-test-suite-tests suite) fdown fup fhere kid-seed)])
[kid-seed ((racunit-test-suite-tests suite) fdown fup fhere kid-seed)])
(fup suite name before after seed kid-seed)))
;; test-suite : name [#:before thunk] [#:after thunk] test ...
@ -84,7 +84,7 @@
[the-tests
(lambda (fdown fup fhere seed)
(define (run/inner x)
(cond [(rktunit-test-suite? x)
(cond [(racunit-test-suite? x)
(current-seed
(apply-test-suite x fdown fup fhere (current-seed)))]
[(list? x)
@ -103,7 +103,7 @@
[(not (string? the-name))
(raise-type-error 'test-suite "test-suite name as string" the-name)]
[else
(make-rktunit-test-suite
(make-racunit-test-suite
the-name
the-tests
before-thunk
@ -138,13 +138,13 @@
(for-each
(lambda (t)
(cond
[(rktunit-test-suite? t)
[(racunit-test-suite? t)
(current-seed (apply-test-suite t fdown fup fhere (current-seed)))]
[(rktunit-test-case? t)
[(racunit-test-case? t)
(current-seed
(fhere t
(rktunit-test-case-name t)
(rktunit-test-case-action t)
(racunit-test-case-name t)
(racunit-test-case-action t)
(current-seed)))]
[else
(raise
@ -158,7 +158,7 @@
;;
;; Construct a test suite from a list of tests
(define (make-test-suite name #:before [before void-thunk] #:after [after void-thunk] tests)
(make-rktunit-test-suite name
(make-racunit-test-suite name
(tests->test-suite-action tests)
before
after))

View File

@ -15,8 +15,8 @@
(struct-out test-failure)
(struct-out test-error)
(struct-out test-success)
(struct-out rktunit-test-case)
(struct-out rktunit-test-suite)
(struct-out racunit-test-case)
(struct-out racunit-test-suite)
with-check-info
with-check-info*
@ -42,9 +42,9 @@
test-suite
make-test-suite
delay-test
(rename-out [make-rktunit-test-case make-test-case]
[rktunit-test-case? test-case?]
[rktunit-test-suite? test-suite?])
(rename-out [make-racunit-test-case make-test-case]
[racunit-test-case? test-case?]
[racunit-test-suite? test-suite?])
define-test-suite
define/provide-test-suite

View File

@ -3,7 +3,7 @@
@title{Acknowlegements}
The following people have contributed to RktUnit:
The following people have contributed to RacUnit:
@itemize[
@item{Robby Findler pushed me to release version 3}
@ -12,7 +12,7 @@ The following people have contributed to RktUnit:
suggested renaming @racket[test/text-ui]}
@item{Dave Gurnell reported a bug in check-not-exn and
suggested improvements to RktUnit}
suggested improvements to RacUnit}
@item{Danny Yoo reported a bug in and provided a fix for
trim-current-directory}
@ -30,7 +30,7 @@ The following people have contributed to RktUnit:
@item{Jose A. Ortega Ruiz alerted me a problem in the
packaging system and helped fix it.}
@item{Sebastian H. Seidel provided help packaging RktUnit
@item{Sebastian H. Seidel provided help packaging RacUnit
into a .plt}
@item{Don Blaheta provided the method for grabbing line number

View File

@ -1,10 +1,10 @@
#lang scribble/doc
@(require "base.rkt")
@title[#:tag "api"]{RktUnit API}
@title[#:tag "api"]{RacUnit API}
@defmodule[rktunit
#:use-sources (rktunit)]
@defmodule[racunit
#:use-sources (racunit)]
@include-section["overview.scrbl"]
@include-section["check.scrbl"]

View File

@ -6,15 +6,15 @@
(for-label scheme/base
scheme/contract
rktunit
rktunit/text-ui
rktunit/gui))
racunit
racunit/text-ui
racunit/gui))
(provide
(all-from-out scribble/eval
scribble/manual)
(for-label (all-from-out scheme/base
scheme/contract
rktunit
rktunit/text-ui
rktunit/gui)))
racunit
racunit/text-ui
racunit/gui)))

View File

@ -3,7 +3,7 @@
@title{Checks}
Checks are the basic building block of RktUnit. A check
Checks are the basic building block of RacUnit. A check
checks some condition. If the condition holds the check
evaluates to @racket[#t]. If the condition doesn't hold the
check raises an instance of @racket[exn:test:check] with
@ -16,7 +16,7 @@ their arguments. You can use check as first class
functions, though you will lose precision in the reported
source locations if you do so.
The following are the basic checks RktUnit provides. You
The following are the basic checks RacUnit provides. You
can create your own checks using @racket[define-check].
@defproc[(check (op (-> any any any))

View File

@ -147,7 +147,7 @@ creates test cases within the suite, with the given names and
body expressions.
As far I know no-one uses this macro, so it might disappear
in future versions of RktUnit.}
in future versions of RacUnit.}
}

View File

@ -48,5 +48,5 @@ file. The after action deletes it.
This somewhat curious macro evaluates the given tests in a
context where @racket[current-test-case-around] is
parameterized to @racket[test-suite-test-case-around]. This
has been useful in testing RktUnit. It might be useful
has been useful in testing RacUnit. It might be useful
for you if you create test cases that create test cases.}

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require rktunit
(require racunit
"file.rkt")
(check-equal? (my-+ 1 1) 2)

View File

@ -14,8 +14,8 @@ Note that @racket[require/expose] can be a bit fragile,
especially when mixed with compiled code. Use at your own risk!
}
This example gets @racket[make-failure-test], which is defined in a RktUnit test:
This example gets @racket[make-failure-test], which is defined in a RacUnit test:
@racketblock[
(require/expose rktunit/private/check-test (make-failure-test))
(require/expose racunit/private/check-test (make-failure-test))
]

View File

@ -1,9 +1,9 @@
#lang scribble/doc
@(require "base.rkt")
@title{Overview of RktUnit}
@title{Overview of RacUnit}
There are three basic data types in RktUnit:
There are three basic data types in RacUnit:
@itemize[

View File

@ -1,10 +1,10 @@
#lang scribble/doc
@(require "base.rkt")
@title[#:tag "philosophy"]{The Philosophy of RktUnit}
@title[#:tag "philosophy"]{The Philosophy of RacUnit}
RktUnit is designed to allow tests to evolve in step with
the evolution of the program under testing. RktUnit
RacUnit is designed to allow tests to evolve in step with
the evolution of the program under testing. RacUnit
scales from the unstructed checks suitable for simple
programs to the complex structure necessary for large
projects.
@ -25,9 +25,9 @@ checking are of the form:
(equal? (length '(a b)) 2)
]
RktUnit directly supports this style of testing. A check
RacUnit directly supports this style of testing. A check
on its own is a valid test. So the above examples may be
written in RktUnit as:
written in RacUnit as:
@racketblock[
(check-equal? (length null) 0)
@ -35,7 +35,7 @@ written in RktUnit as:
(check-equal? (length '(a b)) 2)
]
Simple programs now get all the benefits of RktUnit with
Simple programs now get all the benefits of RacUnit with
very little overhead.
There are limitations to this style of testing that more
@ -45,7 +45,7 @@ it does not make sense to evaluate some expressions if
earlier ones have failed. This type of program needs a way
to group expressions so that a failure in one group causes
evaluation of that group to stop and immediately proceed to
the next group. In RktUnit all that is required is to
the next group. In RacUnit all that is required is to
wrap a @racket[test-begin] expression around a group of
expressions:
@ -62,7 +62,7 @@ be evaluated.
Notice that all the previous tests written in the simple
style are still valid. Introducing grouping is a local
change only. This is a key feature of RktUnit's support
change only. This is a key feature of RacUnit's support
for the evolution of the program.
The programmer may wish to name a group of tests. This is
@ -79,7 +79,7 @@ Most programs will stick with this style. However,
programmers writing very complex programs may wish to
maintain separate groups of tests for different parts of the
program, or run their tests in different ways to the normal
RktUnit manner (for example, test results may be logged
RacUnit manner (for example, test results may be logged
for the purpose of improving software quality, or they may
be displayed on a website to indicate service quality). For
these programmers it is necessary to delay the execution of
@ -104,15 +104,15 @@ outside the suite continue to evaluate as before.
@section{Historical Context}
Most testing frameworks, including earlier versions of
RktUnit, support only the final form of testing. This is
RacUnit, support only the final form of testing. This is
likely due to the influence of the SUnit testing framework,
which is the ancestor of RktUnit and the most widely used
which is the ancestor of RacUnit and the most widely used
frameworks in Java, .Net, Python, and Ruby, and many other
languages. That this is insufficient for all users is
apparent if one considers the proliferation of ``simpler''
testing frameworks in Racket such as SRFI-78, or the
practice of beginner programmers. Unfortunately these
simpler methods are inadequate for testing larger
systems. To the best of my knowledge RktUnit is the only
systems. To the best of my knowledge RacUnit is the only
testing framework that makes a conscious effort to support
the testing style of all levels of programmer.

View File

@ -1,7 +1,7 @@
#lang scribble/doc
@(require "base.rkt")
@title[#:tag "quick-start"]{Quick Start Guide for RktUnit}
@title[#:tag "quick-start"]{Quick Start Guide for RacUnit}
Suppose we have code contained in @tt{file.rkt}, which
implements buggy versions of @racket[+] and @racket[-]
@ -24,15 +24,15 @@ racket/base
my-*)
]
We want to test this code with RktUnit. We start by
We want to test this code with RacUnit. We start by
creating a file called @tt{file-test.rkt} to contain our
tests. At the top of @tt{file-test.rkt} we import
RktUnit and @tt{file.rkt}:
RacUnit and @tt{file.rkt}:
@racketmod[
racket/base
(require rktunit
(require racunit
"file.rkt")
]
@ -43,7 +43,7 @@ Now we add some tests to check our library:
(check-equal? (my-* 1 2) 2 "Simple multiplication")
]
This is all it takes to define tests in RktUnit. Now
This is all it takes to define tests in RacUnit. Now
evaluate this file and see if the library is correct.
Here's the result I get:
@ -63,13 +63,13 @@ expected: 2
The first @racket[#t] indicates the first test passed. The
second test failed, as shown by the message.
Requiring RktUnit and writing checks is all you need to
Requiring RacUnit and writing checks is all you need to
get started testing, but let's take a little bit more time
to look at some features beyond the essentials.
Let's say we want to check that a number of properties hold.
How do we do this? So far we've only seen checks of a
single expression. In RktUnit a check is always a single
single expression. In RacUnit a check is always a single
expression, but we can group checks into units called test
cases. Here's a simple test case written using the
@racket[test-begin] form:
@ -91,7 +91,7 @@ Evalute this and you should see an error message like:
A test
... has a FAILURE
name: check-pred
location: (#<path:/Users/noel/programming/schematics/rktunit/branches/v3/doc/file-test.rkt> 14 6 252 22)
location: (#<path:/Users/noel/programming/schematics/racunit/branches/v3/doc/file-test.rkt> 14 6 252 22)
expression: (check-pred even? elt)
params: (#<procedure:even?> 9)
--------------------
@ -147,13 +147,13 @@ tests, allowing you to choose how you run your tests. You
might, for example, print the results to the screen or log
them to a file.
Let's run our tests, using RktUnit's simple textual user
Let's run our tests, using RacUnit's simple textual user
interface (there are fancier interfaces available but this
will do for our example). In @tt{file-test.rkt} add the
following lines:
@racketblock[
(require rktunit/text-ui)
(require racunit/text-ui)
(run-tests file-tests)
]
@ -161,6 +161,6 @@ following lines:
Now evaluate the file and you should see similar output
again.
These are the basics of RktUnit. Refer to the
These are the basics of RacUnit. Refer to the
documentation below for more advanced topics, such as
defining your own checks. Have fun!

View File

@ -1,12 +1,12 @@
#lang scribble/doc
@(require "base.rkt")
@title{@bold{RktUnit}: Unit Testing for Racket}
@title{@bold{RacUnit}: Unit Testing for Racket}
@author[(author+email "Noel Welsh" "noelwelsh@gmail.com")
(author+email "Ryan Culpepper" "ryan_sml@yahoo.com")]
RktUnit is a unit-testing framework for Racket. It
RacUnit is a unit-testing framework for Racket. It
is designed to handle the needs of all Racket programmers,
from novices to experts.

View File

@ -12,7 +12,7 @@ There are also miscellaneous Scribble fixes.
@section{Version 3}
This version of RktUnit is largely backwards compatible
This version of RacUnit is largely backwards compatible
with version 2 but there are significant changes to the
underlying model, justifying incrementing the major version
number. These changes are best explained in

View File

@ -3,14 +3,14 @@
@title[#:tag "running"]{Programmatically Running Tests and Inspecting Results}
RktUnit provides an API for running tests, from which
RacUnit provides an API for running tests, from which
custom UIs can be created.
@section{Result Types}
@defstruct[(exn:test exn) ()]{
The base structure for RktUnit exceptions. You should
The base structure for RacUnit exceptions. You should
never catch instances of this type, only the subtypes
documented below.}
@ -187,7 +187,7 @@ recorded, and so on. To do so the functions that run the
test cases need to know what type the test case has, and
hence is is necessary to provide this information.
If you've made it this far you truly are a master RktUnit
If you've made it this far you truly are a master RacUnit
hacker. As a bonus prize we'll just mention that the code
in hash-monad.rkt and monad.rkt might be of interest for
constructing user interfaces. The API is still in flux, so

View File

@ -3,13 +3,13 @@
@title[#:tag "ui"]{User Interfaces}
RktUnit provides a textual and a graphical user interface
RacUnit provides a textual and a graphical user interface
@section{Textual User Interface}
@defmodule[rktunit/text-ui]
@defmodule[racunit/text-ui]
The textual UI is in the @racketmodname[rktunit/text-ui] module.
The textual UI is in the @racketmodname[racunit/text-ui] module.
It is run via the @racket[run-tests] function.
@defproc[(run-tests (test (or/c test-case? test-suite?))
@ -33,15 +33,15 @@ information.
@section{Graphical User Interface}
@defmodule[rktunit/gui]
@defmodule[racunit/gui]
RktUnit also provides a GUI test runner, available from the
@racketmodname[rktunit/gui] module.
RacUnit also provides a GUI test runner, available from the
@racketmodname[racunit/gui] module.
@defproc[(test/gui [test (or/c test-case? test-suite?)] ...)
any]{
Creates a new RktUnit GUI window and runs each @racket[test]. The
Creates a new RacUnit GUI window and runs each @racket[test]. The
GUI is updated as tests complete.
}
@ -49,7 +49,7 @@ GUI is updated as tests complete.
@defproc[(make-gui-runner)
(-> (or/c test-case? test-suite?) ... any)]{
Creates a new RktUnit GUI window and returns a procedure that, when
Creates a new RacUnit GUI window and returns a procedure that, when
applied, runs the given tests and displays the results in the GUI.
}

View File

@ -11,7 +11,7 @@
;; CONSTANTS
(define BACKTRACE-NO-MESSAGE "No message.")
(define LINK-MODULE-SPEC 'rktunit/private/gui/drracket-link)
(define LINK-MODULE-SPEC 'racunit/private/gui/drracket-link)
(define-namespace-anchor drracket-ns-anchor)

View File

@ -1,3 +1,3 @@
#lang racket
(require rktunit/gui)
(provide (all-from-out rktunit/gui))
(require racunit/gui)
(provide (all-from-out racunit/gui))

View File

@ -1,3 +1,3 @@
#lang racket
(require rktunit)
(provide (all-from-out rktunit))
(require racunit)
(provide (all-from-out racunit))

View File

@ -1,3 +1,3 @@
#lang racket
(require rktunit/text-ui)
(provide (all-from-out rktunit/text-ui))
(require racunit/text-ui)
(provide (all-from-out racunit/text-ui))

View File

@ -7,7 +7,7 @@
racket/file
racket/sandbox
racket/promise
mzlib/string
racket/string
(for-syntax racket/base))
(provide interaction
@ -97,7 +97,12 @@
(map
(lambda (s)
(car (format-output s error-color)))
(filter
(lambda (s) (not (equal? s "")))
(let sloop ([s (caar val-list+outputs)])
(apply
append
(map (lambda (s)
(if ((string-length s) . > . maxlen)
;; break the error message into multiple lines:
(let loop ([pos (sub1 maxlen)])
@ -108,7 +113,8 @@
(cons (substring s 0 pos)
(sloop (substring s (add1 pos))))]
[else (loop (sub1 pos))]))
(list s))))
(list s)))
(regexp-split #rx"\n" s))))))
;; Normal result case:
(let ([val-list (caar val-list+outputs)])
(if (equal? val-list (list (void)))

File diff suppressed because it is too large Load Diff

View File

@ -4,57 +4,43 @@
@title[#:tag "compile"]{Compilation and Configuration}
So far, we have talked about three main PLT Scheme executables:
So far in this guide, we have mainly discussed DrRacket and
@exec{racket} (and @exec{gracket}). The main additional executable is
@exec{raco}, which is short for ``@bold{Ra}cket @bold{co}mmand.'' The
@exec{raco} program provides a command-line interface to many
additional tools for compiling Racket programs and maintaining a
Racket installation.
@itemize[
@item{DrScheme, which is the development environment.}
@item{@exec{raco make} compiles Racket source to bytecode.
@item{@exec{mzscheme}, which is the console-based virtual machine for
running PLT Scheme programs (and that can be used as a
development environment in interactive mode);}
@item{@exec{mred}, which is like @exec{mzscheme}, but for GUI
applications.}
]
Three more executables help in compiling PLT Scheme programs and in
maintaining a PLT Scheme installation:
@itemize[
@item{@exec{mzc} is a command-line tool for miscellaneous tasks, such
as compiling Scheme source to bytecode, generating executables, and
building distribution packages, and compiling C-implemented
extensions to work with the run-time system. The @exec{mzc} is
described in @other-manual['(lib
"scribblings/mzc/mzc.scrbl")].
For example, if you have a program @filepath{take-over-world.ss} and
For example, if you have a program @filepath{take-over-world.rkt} and
you'd like to compile it to bytecode, along with all of its
dependencies, so that it loads more quickly, then run
@commandline{mzc take-over-the-world.ss}}
@commandline{raco make take-over-the-world.rkt}}
@item{@exec{setup-plt} is a command-line tool for managing a PLT
Scheme installation, including manually installed packages. The
@exec{setup-plt} tool is described in @other-manual['(lib
"scribblings/setup-plt/setup-plt.scrbl")].
@item{@exec{raco setup} manages a Racket installation, including
manually installed packages.
For example, if you create your own library @techlink{collection}
called @filepath{take-over}, and you'd like to build all bytecode and
documentation for the collection, then run
@commandline{setup-plt -l take-over}}
@commandline{raco setup -l take-over}}
@item{@exec{planet} is a command-line tool for managing packages that
are normally downloaded automatically, on demand. The @exec{planet}
tool is described in @other-manual['(lib "planet/planet.scrbl")].
@item{@exec{raco planet} manages packages that are normally
downloaded automatically, on demand.
For example, if you'd like to see a list of @|PLaneT| packages that
are currently installed, then run
@commandline{planet show}}
@commandline{raco planet show}}
]
For more information on @exec{raco}, see @other-manual['(lib
"scribblings/mzc/mzc.scrbl")].

View File

@ -1,5 +1,5 @@
#lang scheme
(require rktunit rktunit/text-ui "1.ss" "1b.ss")
(require racunit racunit/text-ui "1.ss" "1b.ss")
(add (make-basic-customer 'mf "matthias" "brookstone"))
(add (make-basic-customer 'rf "robby" "beverly hills park"))

View File

@ -1,5 +1,5 @@
#lang scheme
(require rktunit rktunit/text-ui "2.ss")
(require racunit racunit/text-ui "2.ss")
(define s0 (initialize (flat-contract integer?) =))
(define s2 (push (push s0 2) 1))

View File

@ -1,5 +1,5 @@
#lang scheme
(require rktunit rktunit/text-ui "3.ss")
(require racunit racunit/text-ui "3.ss")
(define d0 (initialize (flat-contract integer?) =))
(define d (put (put (put d0 'a 2) 'b 2) 'c 1))

View File

@ -1,5 +1,5 @@
#lang scheme
(require rktunit rktunit/text-ui "5.ss")
(require racunit racunit/text-ui "5.ss")
(define s (put (put (initialize (flat-contract integer?) =) 2) 1))

View File

@ -7,7 +7,7 @@
@title[#:tag "control" #:style 'toc]{Exceptions and Control}
Scheme provides an especially rich set of control operations---not
Racket provides an especially rich set of control operations---not
only operations for raising and catching exceptions, but also
operations for grabbing and restoring portions of a computation.
@ -27,22 +27,22 @@ computation.
(car 17)
]
To catch an exception, use the @scheme[with-handlers] form:
To catch an exception, use the @racket[with-handlers] form:
@specform[
(with-handlers ([predicate-expr handler-expr] ...)
body ...+)
]{}
Each @scheme[_predicate-expr] in a handler determines a kind of
exception that is caught by the @scheme[with-handlers] form, and the
Each @racket[_predicate-expr] in a handler determines a kind of
exception that is caught by the @racket[with-handlers] form, and the
value representing the exception is passed to the handler procedure
produced by @scheme[_handler-expr]. The result of the
@scheme[_handler-expr] is the result of the @scheme[with-handlers]
produced by @racket[_handler-expr]. The result of the
@racket[_handler-expr] is the result of the @racket[with-handlers]
expression.
For example, a divide-by-zero error raises an instance of the
@scheme[exn:fail:contract:divide-by-zero] structure type:
@racket[exn:fail:contract:divide-by-zero] structure type:
@interaction[
(with-handlers ([exn:fail:contract:divide-by-zero?
@ -53,9 +53,9 @@ For example, a divide-by-zero error raises an instance of the
(car 17))
]
The @scheme[error] function is one way to raise your own exception. It
The @racket[error] function is one way to raise your own exception. It
packages an error message and other information into an
@scheme[exn:fail] structure:
@racket[exn:fail] structure:
@interaction[
(error "crash!")
@ -63,11 +63,11 @@ packages an error message and other information into an
(error "crash!"))
]
The @scheme[exn:fail:contract:divide-by-zero] and @scheme[exn:fail]
structure types are sub-types of the @scheme[exn] structure
The @racket[exn:fail:contract:divide-by-zero] and @racket[exn:fail]
structure types are sub-types of the @racket[exn] structure
type. Exceptions raised by core forms and functions always raise an
instance of @scheme[exn] or one of its sub-types, but an exception
does not have to be represented by a structure. The @scheme[raise]
instance of @racket[exn] or one of its sub-types, but an exception
does not have to be represented by a structure. The @racket[raise]
function lets you raise any value as an exception:
@interaction[
@ -78,7 +78,7 @@ function lets you raise any value as an exception:
(/ 1 0))
]
Multiple @scheme[_predicate-expr]s in a @scheme[with-handlers] form
Multiple @racket[_predicate-expr]s in a @racket[with-handlers] form
let you handle different kinds of exceptions in different ways. The
predicates are tried in order, and if none of them match, then the
exception is propagated to enclosing contexts.
@ -95,7 +95,7 @@ exception is propagated to enclosing contexts.
(always-fail -3))
]
Using @scheme[(lambda (v) #t)] as a predicate captures all exceptions, of course:
Using @racket[(lambda (v) #t)] as a predicate captures all exceptions, of course:
@interaction[
(with-handlers ([(lambda (v) #t) (lambda (v) 'oops)])
@ -104,9 +104,9 @@ Using @scheme[(lambda (v) #t)] as a predicate captures all exceptions, of course
Capturing all exceptions is usually a bad idea, however. If the user
types Ctl-C in a terminal window or clicks the @onscreen{Stop} button
in DrScheme to interrupt a computation, then normally the
@scheme[exn:break] exception should not be caught. To catch only
exceptions that represent errors, use @scheme[exn:fail?] as the
in DrRacket to interrupt a computation, then normally the
@racket[exn:break] exception should not be caught. To catch only
exceptions that represent errors, use @racket[exn:fail?] as the
predicate:
@interaction[
@ -134,7 +134,7 @@ the way out if the expression is never caught:
But if control escapes ``all the way out,'' why does the @tech{REPL}
keep going after an error is printed? You might think that it's
because the @tech{REPL} wraps every interaction in a
@scheme[with-handlers] form that catches all exceptions, but that's
@racket[with-handlers] form that catches all exceptions, but that's
not quite the reason.
The actual reason is that the @tech{REPL} wraps the interaction with a
@ -145,11 +145,11 @@ nearest enclosing prompt. More precisely, each prompt has a
@deftech{prompt tag}, and there is a designated @deftech{default
prompt tag} that the uncaught-exception handler uses to @tech{abort}.
The @scheme[call-with-continuation-prompt] function installs a prompt
The @racket[call-with-continuation-prompt] function installs a prompt
with a given @tech{prompt tag}, and then it evaluates a given thunk
under the prompt. The @scheme[default-continuation-prompt-tag]
under the prompt. The @racket[default-continuation-prompt-tag]
function returns the @tech{default prompt tag}. The
@scheme[abort-current-continuation] function escapes to the nearest
@racket[abort-current-continuation] function escapes to the nearest
enclosing prompt that has a given @tech{prompt tag}.
@interaction[
@ -165,13 +165,13 @@ enclosing prompt that has a given @tech{prompt tag}.
(default-continuation-prompt-tag)))
]
In @scheme[escape] above, the value @scheme[v] is wrapped in a
In @racket[escape] above, the value @racket[v] is wrapped in a
procedure that is called after escaping to the enclosing prompt.
@tech{Prompts} and @tech{aborts} look very much like exception
handling and raising. Indeed, prompts and aborts are essentially a
more primitive form of exceptions, and @scheme[with-handlers] and
@scheme[raise] are implemented in terms of prompts and aborts. The
more primitive form of exceptions, and @racket[with-handlers] and
@racket[raise] are implemented in terms of prompts and aborts. The
power of the more primitive forms is related to the word
``continuation'' in the operator names, as we discuss in the next
section.
@ -182,7 +182,7 @@ section.
A @deftech{continuation} is a value that encapsulates a piece of an
expression context. The @scheme[call-with-composable-continuation]
expression context. The @racket[call-with-composable-continuation]
function captures the @deftech{current continuation} starting outside
the current function call and running up to the nearest enclosing
prompt. (Keep in mind that each @tech{REPL} interaction is implicitly
@ -190,31 +190,31 @@ wrapped in a prompt.)
For example, in
@schemeblock[
@racketblock[
(+ 1 (+ 1 (+ 1 0)))
]
at the point where @scheme[0] is evaluated, the expression context
at the point where @racket[0] is evaluated, the expression context
includes three nested addition expressions. We can grab that context by
changing @scheme[0] to grab the continuation before returning 0:
changing @racket[0] to grab the continuation before returning 0:
@interaction[
#:eval cc-eval
(define saved-k #f)
(define (save-it!)
(call-with-composable-continuation
(lambda (k) (code:comment @#,t{@scheme[k] is the captured continuation})
(lambda (k) (code:comment @#,t{@racket[k] is the captured continuation})
(set! saved-k k)
0)))
(+ 1 (+ 1 (+ 1 (save-it!))))
]
The @tech{continuation} saved in @scheme[save-k] encapsulates the
program context @scheme[(+ 1 (+ 1 (+ 1 _?)))], where @scheme[_?]
The @tech{continuation} saved in @racket[save-k] encapsulates the
program context @racket[(+ 1 (+ 1 (+ 1 _?)))], where @racket[_?]
represents a place to plug in a result value---because that was the
expression context when @scheme[save-it!] was called. The
expression context when @racket[save-it!] was called. The
@tech{continuation} is encapsulated so that it behaves like the
function @scheme[(lambda (v) (+ 1 (+ 1 (+ 1 v))))]:
function @racket[(lambda (v) (+ 1 (+ 1 (+ 1 v))))]:
@interaction[
#:eval cc-eval
@ -224,7 +224,7 @@ function @scheme[(lambda (v) (+ 1 (+ 1 (+ 1 v))))]:
]
The continuation captured by
@scheme[call-with-composable-continuation] is determined dynamically,
@racket[call-with-composable-continuation] is determined dynamically,
not syntactically. For example, with
@interaction[
@ -236,7 +236,7 @@ not syntactically. For example, with
(sum 5)
]
the continuation in @scheme[saved-k] becomes @scheme[(lambda (x) (+ 5
the continuation in @racket[saved-k] becomes @racket[(lambda (x) (+ 5
(+ 4 (+ 3 (+ 2 (+ 1 x))))))]:
@interaction[
@ -245,25 +245,25 @@ the continuation in @scheme[saved-k] becomes @scheme[(lambda (x) (+ 5
(saved-k 10)
]
A more traditional continuation operator in Scheme is
@scheme[call-with-current-continuation], which is often abbreviated
@scheme[call/cc]. It is like
@scheme[call-with-composable-continuation], but applying the captured
A more traditional continuation operator in Racket is
@racket[call-with-current-continuation], which is often abbreviated
@racket[call/cc]. It is like
@racket[call-with-composable-continuation], but applying the captured
continuation first @tech{aborts} (to the current @tech{prompt}) before
restoring the saved continuation. In addition, Scheme systems
restoring the saved continuation. In addition, Racket systems
traditionally support a single prompt at the program start, instead of
allowing new prompts via
@scheme[call-with-continuation-prompt]. Continuations as in PLT Scheme
@racket[call-with-continuation-prompt]. Continuations as in Racket
are sometimes called @deftech{delimited continuations}, since a
program can introduce new delimiting prompts, and continuations as
captured by @scheme[call-with-composable-continuation] are sometimes
captured by @racket[call-with-composable-continuation] are sometimes
called @deftech{composable continuations}, because they do not have a
built-in @tech{abort}.
For an example of how @tech{continuations} are useful, see
@other-manual['(lib "scribblings/more/more.scrbl")]. For specific
control operators that have more convenient names than the primitives
described here, see @schememodname[scheme/control].
described here, see @racketmodname[racket/control].
@; ----------------------------------------------------------------------

View File

@ -1,28 +1,26 @@
#lang scribble/doc
#lang scribble/base
@(require scribble/manual
"guide-utils.ss")
@(define r6rs @elem{R@superscript{6}RS})
@(define r5rs @elem{R@superscript{5}RS})
@title[#:tag "dialects" #:style 'toc]{Dialects of Scheme}
@title[#:tag "dialects" #:style 'toc]{Dialects of Racket and Scheme}
PLT Scheme is one dialect of the Scheme programming language, and
there are many others. Indeed, ``Scheme'' is perhaps more of an idea
than a specific language.
We use ``Racket'' to refer to a specific dialect of the Lisp language,
and one that is based on the Scheme branch of the Lisp family.
Despite Racket's similarly to Scheme, the @hash-lang[] prefix on
modules is a particular feature of Racket, and programs that start
with @hash-lang[] are unlikely to run in other implementations of
Scheme. At the same time, programs that do not start with @hash-lang[]
do not work with the default mode of most Racket tools.
The @hash-lang[] prefix on modules is a particular feature of PLT
Scheme, and programs that start with @hash-lang[] are unlikely to run
in other implementations of Scheme. At the same time, programs that do
not start with @hash-lang[] (or another PLT Scheme module form) do not
work with the default mode of most PLT Scheme tools.
``PLT Scheme'' is not, however, the only dialect of Scheme that is supported
by PLT Scheme tools. On the contrary, PLT Scheme tools are designed to
support multiple dialects of Scheme and even multiple languages, which
allows the PLT Scheme tool suite to serve multiple communities. PLT
Scheme also gives programmers and researchers the tools they need to
explore and create new languages.
``Racket'' is not, however, the only dialect of Lisp that is supported
by Racket tools. On the contrary, Racket tools are designed to support
multiple dialects of Lisp and even multiple languages, which allows
the Racket tool suite to serve multiple communities. Racket also gives
programmers and researchers the tools they need to explore and create
new languages.
@local-table-of-contents[]
@ -39,10 +37,10 @@ Standard dialects of Scheme include the ones defined by @|r5rs| and
Revised@superscript{5} Report on the Algorithmic Language Scheme}, and
it is currently the most widely implemented Scheme standard.
PLT Scheme tools in their default modes do not conform to @|r5rs|,
mainly because PLT Scheme tools generally expect modules, and @|r5rs|
Racket tools in their default modes do not conform to @|r5rs|,
mainly because Racket tools generally expect modules, and @|r5rs|
does not define a module system. Typical single-file @|r5rs| programs
can be converted to PLT Scheme programs by prefixing them with
can be converted to Racket programs by prefixing them with
@scheme[@#,hash-lang[] @#,schememodname[r5rs]], but other Scheme
systems do not recognize @scheme[@#,hash-lang[]
@#,schememodname[r5rs]]. The @exec{plt-r5rs} executable (see
@ -50,106 +48,106 @@ systems do not recognize @scheme[@#,hash-lang[]
conforms to the @|r5rs| standard.
Aside from the module system, the syntactic forms and functions of
@|r5rs| and PLT Scheme differ. Only simple @|r5rs| become PLT Scheme
programs when prefixed with @scheme[@#,hash-lang[] scheme], and
relatively few PLT Scheme programs become @|r5rs| programs when a
@|r5rs| and Racket differ. Only simple @|r5rs| become Racket
programs when prefixed with @scheme[@#,hash-lang[] racket], and
relatively few Racket programs become @|r5rs| programs when a
@hash-lang[] line is removed. Also, when mixing ``@|r5rs| modules''
with PLT Scheme modules, beware that @|r5rs| pairs correspond to PLT
Scheme mutable pairs (as constructed with @scheme[mcons]).
with Racket modules, beware that @|r5rs| pairs correspond to
Racket mutable pairs (as constructed with @scheme[mcons]).
See @other-manual['(lib "r5rs/r5rs.scrbl")] for more
information about running @|r5rs| programs with PLT Scheme.
information about running @|r5rs| programs with Racket.
@subsection{@|r6rs|}
``@|r6rs|'' stands for @link["../r6rs-std/index.html"]{The
Revised@superscript{6} Report on the Algorithmic Language Scheme},
which extends @|r5rs| with a module system that is similar to the PLT
Scheme module system.
which extends @|r5rs| with a module system that is similar to the
Racket module system.
When an @|r6rs| library or top-level program is prefixed with
@schememetafont{#!}@schememodname[r6rs] (which is valid @|r6rs|
syntax), then it can also be used as a PLT Scheme program. This works
because @schememetafont{#!} in PLT Scheme is treated as a shorthand
syntax), then it can also be used as a Racket program. This works
because @schememetafont{#!} in Racket is treated as a shorthand
for @hash-lang[] followed by a space, so
@schememetafont{#!}@schememodname[r6rs] selects the
@schememodname[r6rs] module language. As with @|r5rs|, however, beware
that the syntactic forms and functions of @|r6rs| differ from PLT
Scheme, and @|r6rs| pairs are mutable pairs.
that the syntactic forms and functions of @|r6rs| differ from
Racket, and @|r6rs| pairs are mutable pairs.
See @other-manual['(lib "r6rs/scribblings/r6rs.scrbl")] for more
information about running @|r6rs| programs with PLT Scheme.
information about running @|r6rs| programs with Racket.
@; --------------------------------------------------
@section[#:tag "more-hash-lang"]{More PLT Schemes}
@section[#:tag "more-hash-lang"]{More Rackets}
Like ``Scheme'' itself, even ``PLT Scheme'' is more of an idea about
Like ``Scheme,'' even ``Racket'' is more of an idea about
programming languages than a language in the usual sense. Macros can
extend a base language (as described in @secref["macros"]), but macros
and alternate parsers can construct an entirely new language from the
ground up.
The @hash-lang[] line that starts a PLT Scheme module declares the
base language of the module. By ``PLT Scheme,'' we usually mean
@hash-lang[] followed by the base language @schememodname[scheme] or
@schememodname[scheme/base] (of which @schememodname[scheme] is an
extension). The PLT Scheme distribution provides additional languages,
The @hash-lang[] line that starts a Racket module declares the
base language of the module. By ``Racket,'' we usually mean
@hash-lang[] followed by the base language @racketmodname[racket] or
@racketmodname[racket/base] (of which @racketmodname[racket] is an
extension). The Racket distribution provides additional languages,
including the following:
@itemize[
@item{@schememodname[typed/scheme] --- like
@schememodname[scheme], but statically typed; see
@item{@racketmodname[typed/scheme] --- like
@racketmodname[racket], but statically typed; see
@other-manual['(lib "typed-scheme/scribblings/ts-guide.scrbl")]}
@item{@schememodname[lazy] --- like @schememodname[scheme/base], but
@item{@racketmodname[lazy] --- like @racketmodname[racket/base], but
avoids evaluating an expression until its value is needed; see
@other-manual['(lib "lazy/lazy.scrbl")]}
@item{@schememodname[frtime] --- changes evaluation in an even more
@item{@racketmodname[frtime] --- changes evaluation in an even more
radical way to support reactive programming; see
@other-manual['(lib "frtime/scribblings/frtime.scrbl")]}
@item{@schememodname[scribble/doc] --- a language, which looks more
like Latex than Scheme, for writing documentation; see
@item{@racketmodname[scribble/base] --- a language, which looks more
like Latex than Racket, for writing documentation; see
@other-manual['(lib "scribblings/scribble/scribble.scrbl")]}
]
Each of these languages is used by starting module with the language
name after @hash-lang[]. For example, this source of this
document starts with @scheme[@#,hash-lang[] scribble/doc].
document starts with @racket[@#,hash-lang[] scribble/base].
PLT Scheme users can define their own languages. A language name maps
Racket users can define their own languages. A language name maps
to its implementation through a module path by adding
@schemeidfont{/lang/reader}. For example, the language name
@schememodname[scribble/doc] is expanded to
@scheme[scribble/doc/lang/reader], which is the module that implements
@racketidfont{/lang/reader}. For example, the language name
@racketmodname[scribble/doc] is expanded to
@racket[scribble/doc/lang/reader], which is the module that implements
the surface-syntax parser. The parser, in turn, generates a
@scheme[module] form, which determines the base language at the level
@racket[module] form, which determines the base language at the level
of syntactic forms an functions.
Some language names act as language loaders. For example,
@schememodname[s-exp] as a language uses the usual PLT Scheme parser
@racketmodname[s-exp] as a language uses the usual Racket parser
for surface-syntax reading, and then it uses the module path after
@schememodname[s-exp] for the language's syntactic forms. Thus,
@scheme[@#,hash-lang[] @#,schememodname[s-exp] "mylang.ss"] parses
the module body using the normal PLT Scheme reader, by then imports
@racketmodname[s-exp] for the language's syntactic forms. Thus,
@racket[@#,hash-lang[] @#,racketmodname[s-exp] "mylang.rkt"] parses
the module body using the normal Racket reader, by then imports
the initial syntax and functions for the module body from
@scheme["mylang.ss"]. Similarly, @scheme[@#,hash-lang[]
@#,schememodname[planet] _planet-path] loads a language via
@racket["mylang.rkt"]. Similarly, @racket[@#,hash-lang[]
@#,racketmodname[planet] _planet-path] loads a language via
@seclink["top" #:doc '(lib "planet/planet.scrbl")]{@|PLaneT|}.
@; --------------------------------------------------
@section[#:tag "teaching-langs"]{Teaching}
The @|HtDP| textbook relies on pedagogic variants of Scheme that
The @|HtDP| textbook relies on pedagogic variants of Racket that
smooth the introduction of programming concepts for new programmers.
The languages are documented in @other-manual['(lib
"scribblings/htdp-langs/htdp-langs.scrbl")].
The @|HtDP| languages are typically not used with @hash-lang[]
prefixes, but are instead used within DrScheme by selecting the
prefixes, but are instead used within DrRacket by selecting the
language from the @onscreen{Choose Language...} dialog.

View File

@ -5,24 +5,24 @@
@title[#:tag "for"]{Iterations and Comprehensions}
The @scheme[for] family of syntactic forms support iteration over
The @racket[for] family of syntactic forms support iteration over
@defterm{sequences}. Lists, vectors, strings, byte strings, input
ports, and hash tables can all be used as sequences, and constructors
like @scheme[in-range] offer even more kinds of sequences.
like @racket[in-range] offer even more kinds of sequences.
Variants of @scheme[for] accumulate iteration results in different
Variants of @racket[for] accumulate iteration results in different
ways, but they all have the same syntactic shape. Simplifying for
now, the syntax of @scheme[for] is
now, the syntax of @racket[for] is
@specform[
(for ([id sequence-expr] ...)
body ...+)
]{}
A @scheme[for] loop iterates through the sequence produced by the
@scheme[_sequence-expr]. For each element of the sequence,
@scheme[for] binds the element to @scheme[_id], and then it evaluates
the @scheme[_body]s for side effects.
A @racket[for] loop iterates through the sequence produced by the
@racket[_sequence-expr]. For each element of the sequence,
@racket[for] binds the element to @racket[_id], and then it evaluates
the @racket[_body]s for side effects.
@examples[
(for ([i '(1 2 3)])
@ -31,10 +31,10 @@ the @scheme[_body]s for side effects.
(printf "~a..." i))
]
The @scheme[for/list] variant of @scheme[for] is more Scheme-like. It
accumulates @scheme[_body] results into a list, instead of
evaluating @scheme[_body] only for side effects. In more
technical terms, @scheme[for/list] implements a @defterm{list
The @racket[for/list] variant of @racket[for] is more Racket-like. It
accumulates @racket[_body] results into a list, instead of
evaluating @racket[_body] only for side effects. In more
technical terms, @racket[for/list] implements a @defterm{list
comprehension}.
@examples[
@ -44,22 +44,22 @@ comprehension}.
i)
]
The full syntax of @scheme[for] accommodates multiple sequences to
iterate in parallel, and the @scheme[for*] variant nests the
The full syntax of @racket[for] accommodates multiple sequences to
iterate in parallel, and the @racket[for*] variant nests the
iterations instead of running them in parallel. More variants of
@scheme[for] and @scheme[for*] accumulate @scheme[_body] results
@racket[for] and @racket[for*] accumulate @racket[_body] results
in different ways. In all of these variants, predicates that prune
iterations can be included along with bindings.
Before details on the variations of @scheme[for], though, it's best to
Before details on the variations of @racket[for], though, it's best to
see the kinds of sequence generators that make interesting examples.
@section[#:tag "sequences"]{Sequence Constructors}
The @scheme[in-range] function generates a sequence of numbers, given
an optional starting number (which defaults to @scheme[0]), a number
The @racket[in-range] function generates a sequence of numbers, given
an optional starting number (which defaults to @racket[0]), a number
before which the sequences ends, and an optional step (which defaults
to @scheme[1]).
to @racket[1]).
@examples[
(for ([i (in-range 3)])
@ -74,10 +74,10 @@ to @scheme[1]).
(printf " ~a " i))
]
The @scheme[in-naturals] function is similar, except that the
The @racket[in-naturals] function is similar, except that the
starting number must be an exact non-negative integer (which defaults
to @scheme[0]), the step is always @scheme[1], and there is no upper
limit. A @scheme[for] loop using just @scheme[in-naturals] will never
to @racket[0]), the step is always @racket[1], and there is no upper
limit. A @racket[for] loop using just @racket[in-naturals] will never
terminate unless a body expression raises an exception or otherwise
escapes.
@ -88,7 +88,7 @@ escapes.
(display i)))
]
The @scheme[stop-before] and @scheme[stop-after] functions construct
The @racket[stop-before] and @racket[stop-after] functions construct
a new sequence given a sequence and a predicate. The new sequence is
like the given sequence, but truncated either immediately before or
immediately after the first element for which the predicate returns
@ -100,8 +100,8 @@ true.
(display i))
]
Sequence constructors like @scheme[in-list], @scheme[in-vector] and
@scheme[in-string] simply make explicit the use of a list, vector, or
Sequence constructors like @racket[in-list], @racket[in-vector] and
@racket[in-string] simply make explicit the use of a list, vector, or
string as a sequence. Since they raise an exception when given the
wrong kind of value, and since they otherwise avoid a run-time
dispatch to determine the sequence type, they enable more efficient
@ -116,9 +116,9 @@ code generation; see @secref["for-performance"] for more information.
@refdetails["sequences"]{sequences}
@section{@scheme[for] and @scheme[for*]}
@section{@racket[for] and @racket[for*]}
A more complete syntax of @scheme[for] is
A more complete syntax of @racket[for] is
@specform/subs[
(for (clause ...)
@ -127,8 +127,8 @@ A more complete syntax of @scheme[for] is
(code:line #:when boolean-expr)])
]{}
When multiple @scheme[[_id _sequence-expr]] clauses are provided
in a @scheme[for] form, the corresponding sequences are traversed in
When multiple @racket[[_id _sequence-expr]] clauses are provided
in a @racket[for] form, the corresponding sequences are traversed in
parallel:
@interaction[
@ -137,8 +137,8 @@ parallel:
(printf "Chapter ~a. ~a\n" i chapter))
]
With parallel sequences, the @scheme[for] expression stops iterating
when any sequence ends. This behavior allows @scheme[in-naturals],
With parallel sequences, the @racket[for] expression stops iterating
when any sequence ends. This behavior allows @racket[in-naturals],
which creates an infinite sequence of numbers, to be used for
indexing:
@ -148,7 +148,7 @@ indexing:
(printf "Chapter ~a. ~a\n" i chapter))
]
The @scheme[for*] form, which has the same syntax as @scheme[for],
The @racket[for*] form, which has the same syntax as @racket[for],
nests multiple sequences instead of running them in parallel:
@interaction[
@ -157,12 +157,12 @@ nests multiple sequences instead of running them in parallel:
(printf "~a ~a\n" book chapter))
]
Thus, @scheme[for*] is a shorthand for nested @scheme[for]s in the
same way that @scheme[let*] is a shorthand for nested @scheme[let]s.
Thus, @racket[for*] is a shorthand for nested @racket[for]s in the
same way that @racket[let*] is a shorthand for nested @racket[let]s.
The @scheme[#:when _boolean-expr] form of a @scheme[_clause] is
another shorthand. It allows the @scheme[_body]s to evaluate only
when the @scheme[_boolean-expr] produces a true value:
The @racket[#:when _boolean-expr] form of a @racket[_clause] is
another shorthand. It allows the @racket[_body]s to evaluate only
when the @racket[_boolean-expr] produces a true value:
@interaction[
(for* ([book '("Guide" "Reference")]
@ -171,11 +171,11 @@ when the @scheme[_boolean-expr] produces a true value:
(printf "~a ~a\n" book chapter))
]
A @scheme[_boolean-expr] with @scheme[#:when] can refer to any of the
preceding iteration bindings. In a @scheme[for] form, this scoping
A @racket[_boolean-expr] with @racket[#:when] can refer to any of the
preceding iteration bindings. In a @racket[for] form, this scoping
makes sense only if the test is nested in the iteration of the
preceding bindings; thus, bindings separated by @scheme[#:when] are
mutually nested, instead of in parallel, even with @scheme[for].
preceding bindings; thus, bindings separated by @racket[#:when] are
mutually nested, instead of in parallel, even with @racket[for].
@interaction[
(for ([book '("Guide" "Reference" "Notes")]
@ -186,10 +186,10 @@ mutually nested, instead of in parallel, even with @scheme[for].
(printf "~a Chapter ~a. ~a\n" book i chapter))
]
@section{@scheme[for/list] and @scheme[for*/list]}
@section{@racket[for/list] and @racket[for*/list]}
The @scheme[for/list] form, which has the same syntax as @scheme[for],
evaluates the @scheme[_body]s to obtain values that go into a
The @racket[for/list] form, which has the same syntax as @racket[for],
evaluates the @racket[_body]s to obtain values that go into a
newly constructed list:
@interaction[
@ -198,8 +198,8 @@ newly constructed list:
(string-append (number->string i) ". " chapter))
]
A @scheme[#:when] clause in a @scheme[for-list] form prunes the result
list along with evaluations of the @scheme[_body]s:
A @racket[#:when] clause in a @racket[for-list] form prunes the result
list along with evaluations of the @racket[_body]s:
@interaction[
(for/list ([i (in-naturals 1)]
@ -208,13 +208,13 @@ list along with evaluations of the @scheme[_body]s:
chapter)
]
This pruning behavior of @scheme[#:when] is more useful with
@scheme[for/list] than @scheme[for]. Whereas a plain @scheme[when]
form normally suffices with @scheme[for], a @scheme[when] expression
form in a @scheme[for/list] would cause the result list to contain
This pruning behavior of @racket[#:when] is more useful with
@racket[for/list] than @racket[for]. Whereas a plain @racket[when]
form normally suffices with @racket[for], a @racket[when] expression
form in a @racket[for/list] would cause the result list to contain
@|void-const|s instead of omitting list elements.
The @scheme[for*/list] is like @scheme[for*], nesting multiple
The @racket[for*/list] is like @racket[for*], nesting multiple
iterations:
@interaction[
@ -223,23 +223,23 @@ iterations:
(string-append book " " chapter))
]
A @scheme[for*/list] form is not quite the same thing as nested
@scheme[for/list] forms. Nested @scheme[for/list]s would produce a
A @racket[for*/list] form is not quite the same thing as nested
@racket[for/list] forms. Nested @racket[for/list]s would produce a
list of lists, instead of one flattened list. Much like
@scheme[#:when], then, the nesting of @scheme[for*/list] is more
useful than the nesting of @scheme[for*].
@racket[#:when], then, the nesting of @racket[for*/list] is more
useful than the nesting of @racket[for*].
@section{@scheme[for/and] and @scheme[for/or]}
@section{@racket[for/and] and @racket[for/or]}
The @scheme[for/and] form combines iteration results with
@scheme[and], stopping as soon as it encounters @scheme[#f]:
The @racket[for/and] form combines iteration results with
@racket[and], stopping as soon as it encounters @racket[#f]:
@interaction[
(for/and ([chapter '("Intro" "Details" "Conclusion")])
(equal? chapter "Intro"))
]
The @scheme[for/or] form combines iteration results with @scheme[or],
The @racket[for/or] form combines iteration results with @racket[or],
stopping as soon as it encounters a true value:
@interaction[
@ -247,14 +247,14 @@ stopping as soon as it encounters a true value:
(equal? chapter "Intro"))
]
As usual, the @scheme[for*/and] and @scheme[for*/or] forms provide the
As usual, the @racket[for*/and] and @racket[for*/or] forms provide the
same facility with nested iterations.
@section{@scheme[for/first] and @scheme[for/last]}
@section{@racket[for/first] and @racket[for/last]}
The @scheme[for/first] form returns the result of the first time that
the @scheme[_body]s are evaluated, skipping further iterations.
This form is most useful with a @scheme[#:when] clause.
The @racket[for/first] form returns the result of the first time that
the @racket[_body]s are evaluated, skipping further iterations.
This form is most useful with a @racket[#:when] clause.
@interaction[
(for/first ([chapter '("Intro" "Details" "Conclusion" "Index")]
@ -262,11 +262,11 @@ This form is most useful with a @scheme[#:when] clause.
chapter)
]
If the @scheme[_body]s are evaluated zero times, then the result
is @scheme[#f].
If the @racket[_body]s are evaluated zero times, then the result
is @racket[#f].
The @scheme[for/last] form runs all iterations, returning the value of
the last iteration (or @scheme[#f] if no iterations are run):
The @racket[for/last] form runs all iterations, returning the value of
the last iteration (or @racket[#f] if no iterations are run):
@interaction[
(for/last ([chapter '("Intro" "Details" "Conclusion" "Index")]
@ -274,7 +274,7 @@ the last iteration (or @scheme[#f] if no iterations are run):
chapter)
]
As usual, the @scheme[for*/first] and @scheme[for*/last] forms provide
As usual, the @racket[for*/first] and @racket[for*/last] forms provide
the same facility with nested iterations:
@interaction[
@ -289,26 +289,26 @@ the same facility with nested iterations:
(list book chapter))
]
@section[#:tag "for/fold"]{@scheme[for/fold] and @scheme[for*/fold]}
@section[#:tag "for/fold"]{@racket[for/fold] and @racket[for*/fold]}
The @scheme[for/fold] form is a very general way to combine iteration
The @racket[for/fold] form is a very general way to combine iteration
results. Its syntax is slightly different than the syntax of
@scheme[for], because accumulation variables must be declared at the
@racket[for], because accumulation variables must be declared at the
beginning:
@schemeblock[
@racketblock[
(for/fold ([_accum-id _init-expr] ...)
(_clause ...)
_body ...+)
]
In the simple case, only one @scheme[[_accum-id _init-expr]] is
provided, and the result of the @scheme[for/fold] is the final value
for @scheme[_accum-id], which starts out with the value of
@scheme[_init-expr]. In the @scheme[_clause]s and
@scheme[_body]s, @scheme[_accum-id] can be referenced to get its
current value, and the last @scheme[_body] provides the value of
@scheme[_accum-id] for the next iteration.
In the simple case, only one @racket[[_accum-id _init-expr]] is
provided, and the result of the @racket[for/fold] is the final value
for @racket[_accum-id], which starts out with the value of
@racket[_init-expr]. In the @racket[_clause]s and
@racket[_body]s, @racket[_accum-id] can be referenced to get its
current value, and the last @racket[_body] provides the value of
@racket[_accum-id] for the next iteration.
@examples[
(for/fold ([len 0])
@ -322,9 +322,9 @@ current value, and the last @scheme[_body] provides the value of
chapter)
]
When multiple @scheme[_accum-id]s are specified, then the last
@scheme[_body] must produce multiple values, one for each
@scheme[_accum-id]. The @scheme[for/fold] expression itself produces
When multiple @racket[_accum-id]s are specified, then the last
@racket[_body] must produce multiple values, one for each
@racket[_accum-id]. The @racket[for/fold] expression itself produces
multiple values for the results.
@examples[
@ -344,12 +344,12 @@ values, individual iterations of a sequence can produce multiple
elements. For example, a hash table as a sequence generates two
values for each iteration: a key and a value.
In the same way that @scheme[let-values] binds multiple results to
multiple identifiers, @scheme[for] can bind multiple sequence elements
In the same way that @racket[let-values] binds multiple results to
multiple identifiers, @racket[for] can bind multiple sequence elements
to multiple iteration identifiers:
@margin-note{While @scheme[let] must be changed to @scheme[let-values]
to bind multiple identifier, @scheme[for] simply allows a
@margin-note{While @racket[let] must be changed to @racket[let-values]
to bind multiple identifier, @racket[for] simply allows a
parenthesized list of identifiers instead of a single
identifier in any clause.}
@ -358,8 +358,8 @@ to multiple iteration identifiers:
(printf "~a count: ~a\n" k v))
]
This extension to multiple-value bindings works for all @scheme[for]
variants. For example, @scheme[for*/list] nests iterations, builds a
This extension to multiple-value bindings works for all @racket[for]
variants. For example, @racket[for*/list] nests iterations, builds a
list, and also works with multiple-valued sequences:
@interaction[
@ -371,26 +371,26 @@ list, and also works with multiple-valued sequences:
@section[#:tag "for-performance"]{Iteration Performance}
Ideally, a @scheme[for] iteration should run as fast as a loop that
Ideally, a @racket[for] iteration should run as fast as a loop that
you write by hand as a recursive-function invocation. A hand-written
loop, however, is normally specific to a particular kind of data, such
as lists. In that case, the hand-written loop uses selectors like
@scheme[car] and @scheme[cdr] directly, instead of handling all forms
@racket[car] and @racket[cdr] directly, instead of handling all forms
of sequences and dispatching to an appropriate iterator.
The @scheme[for] forms can provide the performance of hand-written
The @racket[for] forms can provide the performance of hand-written
loops when enough information is apparent about the sequences to
iterate. Specifically, the clause should have one of the following
@scheme[_fast-clause] forms:
@racket[_fast-clause] forms:
@schemegrammar[
@racketgrammar[
fast-clause [id fast-seq]
[(id) fast-seq]
[(id id) fast-indexed-seq]
[(id ...) fast-parallel-seq]
]
@schemegrammar[
@racketgrammar[
#:literals [in-range in-naturals in-list in-vector in-string in-bytes in-value stop-before stop-after]
fast-seq (in-range expr expr)
(in-range expr expr expr)
@ -405,14 +405,14 @@ fast-seq (in-range expr expr)
(stop-after fast-seq predicate-expr)
]
@schemegrammar[
@racketgrammar[
#:literals [in-indexed stop-before stop-after]
fast-indexed-seq (in-indexed fast-seq)
(stop-before fast-indexed-seq predicate-expr)
(stop-after fast-indexed-seq predicate-expr)
]
@schemegrammar[
@racketgrammar[
#:literals [in-parallel stop-before stop-after]
fast-parallel-seq (in-parallel fast-seq ...)
(stop-before fast-parallel-seq predicate-expr)
@ -436,6 +436,6 @@ The grammars above are not complete, because the set of syntactic
patterns that provide good performance is extensible, just like the
set of sequence values. The documentation for a sequence constructor
should indicate the performance benefits of using it directly in
a @scheme[for] @scheme[_clause].
a @racket[for] @racket[_clause].
@refdetails["for"]{iterations and comprehensions}

View File

@ -4,22 +4,24 @@
scribble/eval
mzlib/process
"guide-utils.ss"
(for-label scheme/tcp
scheme/serialize
scheme/port))
(for-label racket/tcp
racket/serialize
racket/port))
@(define io-eval (make-base-eval))
@(define (twocolumn a b)
@(define (threecolumn a b c)
(make-table #f
(list (list (make-flow (list a))
(make-flow (list (make-paragraph (list (hspace 1)))))
(make-flow (list b))))))
(make-flow (list b))
(make-flow (list (make-paragraph (list (hspace 1)))))
(make-flow (list c))))))
@(interaction-eval #:eval io-eval (print-hash-table #t))
@title[#:tag "i/o" #:style 'toc]{Input and Output}
A Scheme @deftech{port} represents an input or output stream, such as
A Racket @deftech{port} represents an input or output stream, such as
a file, a terminal, a TCP connection, or an in-memory string. More
specifically, an @defterm{input port} represents a stream from which a
program can read data, and an @defterm{output port} represents a
@ -28,7 +30,7 @@ stream for writing data.
@local-table-of-contents[]
@;------------------------------------------------------------------------
@section{Varieties of Ports}
@section[#:tag "ports"]{Varieties of Ports}
Various functions create various kinds of ports. Here are a few
examples:
@ -36,8 +38,8 @@ examples:
@itemize[
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@item{@bold{Files:} The @scheme[open-output-file] function opens a
file for writing, and @scheme[open-input-file] opens a file for
@item{@bold{Files:} The @racket[open-output-file] function opens a
file for writing, and @racket[open-input-file] opens a file for
reading.
@(interaction-eval #:eval io-eval (define old-dir (current-directory)))
@ -54,9 +56,9 @@ examples:
(close-input-port in)
]
If a file exists already, then @scheme[open-output-file] raises an
exception by default. Supply an option like @scheme[#:exists
'truncate] or @scheme[#:exists 'update] to re-write or update the
If a file exists already, then @racket[open-output-file] raises an
exception by default. Supply an option like @racket[#:exists
'truncate] or @racket[#:exists 'update] to re-write or update the
file:
@examples[
@ -66,9 +68,9 @@ file:
(close-output-port out)
]
Instead of having to match @scheme[open-input-file] and
@scheme[open-output-file] calls, most Scheme programmers will instead
use @scheme[call-with-output-file], which takes a function to call
Instead of having to match @racket[open-input-file] and
@racket[open-output-file] calls, most Racket programmers will instead
use @racket[call-with-output-file], which takes a function to call
with the output port; when the function returns, the port is closed.
@examples[
@ -86,9 +88,9 @@ with the output port; when the function returns, the port is closed.
@(interaction-eval #:eval io-eval (current-directory old-dir))}
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@item{@bold{Strings:} The @scheme[open-output-string] function creates
a port that accumulates data into a string, and @scheme[get-output-string]
extracts the accumulated string. The @scheme[open-input-string] function
@item{@bold{Strings:} The @racket[open-output-string] function creates
a port that accumulates data into a string, and @racket[get-output-string]
extracts the accumulated string. The @racket[open-input-string] function
creates a port to read from a string.
@examples[
@ -101,10 +103,10 @@ with the output port; when the function returns, the port is closed.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@item{@bold{TCP Connections:} The @scheme[tcp-connect] function
@item{@bold{TCP Connections:} The @racket[tcp-connect] function
creates both an input port and an output port for the client side of
a TCP communication. The @scheme[tcp-listen] function creates a
server, which accepts connections via @scheme[tcp-accept].
a TCP communication. The @racket[tcp-listen] function creates a
server, which accepts connections via @racket[tcp-accept].
@examples[
#:eval io-eval
@ -121,7 +123,7 @@ with the output port; when the function returns, the port is closed.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@item{@bold{Process Pipes:} The @scheme[subprocess] function runs a new
@item{@bold{Process Pipes:} The @racket[subprocess] function runs a new
process at the OS level and returns ports that correspond to the
subprocess's stdin, stdout, and stderr. (The first three arguments
can be certain kinds of existing ports to connect directly to the
@ -143,9 +145,9 @@ with the output port; when the function returns, the port is closed.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@item{@bold{Internal Pipes:} The @scheme[make-pipe] function returns
@item{@bold{Internal Pipes:} The @racket[make-pipe] function returns
two ports that are ends of a pipe. This kind of pipe is internal to
Scheme, and not related to OS-level pipes for communicating between
Racket, and not related to OS-level pipes for communicating between
different processes.
@examples[
@ -159,14 +161,14 @@ with the output port; when the function returns, the port is closed.
]
@;------------------------------------------------------------------------
@section{Default Ports}
@section[#:tag "default-ports"]{Default Ports}
For most simple I/O functions, the target port is an optional
argument, and the default is the @defterm{current input port} or
@defterm{current output port}. Furthermore, error messages are written
to the @defterm{current error port}, which is an output port. The
@scheme[current-input-port], @scheme[current-output-port], and
@scheme[current-error-port] functions return the corresponding current
@racket[current-input-port], @racket[current-output-port], and
@racket[current-error-port] functions return the corresponding current
ports.
@examples[
@ -175,7 +177,7 @@ ports.
(code:line (display "Hi" (current-output-port)) (code:comment @#,t{the same}))
]
If you start the @exec{mzscheme} program in a terminal, then the
If you start the @exec{racket} program in a terminal, then the
current input, output, and error ports are all connected to the
terminal. More generally, they are connected to the OS-level stdin,
stdout, and stderr. In this guide, the examples show output written to
@ -188,8 +190,10 @@ stdout in purple, and output written to stderr in red italics.
(swing-hammer)
]
The current-port functions are actually parameters, which means that
their values can be set with @scheme[parameterize].
The current-port functions are actually @tech{parameters}, which means
that their values can be set with @racket[parameterize].
@margin-note{See @secref["parameterize"] for an introduction to parameters.}
@examples[
#:eval io-eval
@ -202,34 +206,47 @@ their values can be set with @scheme[parameterize].
]
@; ----------------------------------------------------------------------
@section{Reading and Writing Scheme Data}
@section[#:tag "read-write"]{Reading and Writing Racket Data}
As noted throughout @secref["datatypes"], Scheme provides two
As noted throughout @secref["datatypes"], Racket provides three
ways to print an instance of a built-in value:
@itemize[
@item{ @scheme[write], which prints a value in the same way that is it
@item{@racket[print], which prints a value in the same way that is it
printed for a @tech{REPL} result; and }
@item{@scheme[display], which tends to reduce a value to just its
@item{@racket[write], which prints a value in such a way that
@racket[read] on the output produces the value back; and }
@item{@racket[display], which tends to reduce a value to just its
character or byte content---at least for those datatypes that
are primarily about characters or bytes, otherwise it falls
back to the same output as @scheme[write].}
back to the same output as @racket[write].}
]
Here are some examples using each:
@twocolumn[
@threecolumn[
@interaction[
(print 1/2)
(print #\x)
(print "hello")
(print #"goodbye")
(print '|pea pod|)
(print '("i" pod))
(print write)
]
@interaction[
(write 1/2)
(write #\x)
(write "hello")
(write #"goodbye")
(write '|dollar sign|)
(write '("alphabet" soup))
(write '|pea pod|)
(write '("i" pod))
(write write)
]
@ -238,27 +255,35 @@ Here are some examples using each:
(display #\x)
(display "hello")
(display #"goodbye")
(display '|dollar sign|)
(display '("alphabet" soup))
(display '|pea pod|)
(display '("i" pod))
(display write)
]
]
The @scheme[printf] function supports simple formatting of data and
text. In the format string supplied to @scheme[printf], @litchar{~a}
@scheme[display]s the next argument, while @litchar{~s}
@scheme[write]s the next argument.
Overall, @racket[print] as corresponds to the expression layer of
Racket syntax, @racket[write] corresponds to the reader layer, and
@racket[display] roughly corresponds to the character layer.
The @racket[printf] function supports simple formatting of data and
text. In the format string supplied to @racket[printf], @litchar{~a}
@racket[display]s the next argument, @litchar{~s}
@racket[write]s the next argument, and @litchar{~v}
@racket[print]s the next argument.
@defexamples[
#:eval io-eval
(define (deliver who what)
(printf "Value for ~a: ~s" who what))
(deliver "John" "string")
(define (deliver who when what)
(printf "Items ~a for shopper ~s: ~v" who when what))
(deliver '("list") '("John") '("milk"))
]
An advantage of @scheme[write], as opposed to @scheme[display], is
that many forms of data can be read back in using @scheme[read].
After using @racket[write], as opposed to @racket[display] or
@racket[print], many forms of data can be read back in using
@racket[read]. The same values @racket[print]ed can also be parsed by
@scheme[read], but the result may have extra quote forms, since a
@racket[print]ed form is meant to be read like an expression.
@examples[
#:eval io-eval
@ -269,6 +294,8 @@ that many forms of data can be read back in using @scheme[read].
(read in)
(write #hash((a . "apple") (b . "banana")) out)
(read in)
(write '("alphabet" soup) out)
(read in)
]
@; ----------------------------------------------------------------------
@ -284,100 +311,99 @@ an output stream, and a copy can be read back in from an input stream:
(read in)
]
Other structure types created by @scheme[define-struct], which offer
Other structure types created by @racket[struct], which offer
more abstraction than @tech{prefab} structure types, normally
@scheme[write] either using @schemeresultfont{#<....>} notation (for
opaque structure types) or using @schemeresultfont{#(....)} vector
@racket[write] either using @racketresultfont{#<....>} notation (for
opaque structure types) or using @racketresultfont{#(....)} vector
notation (for transparent structure types). In neither can can the
result be read back in as an instance of the structure type:
@interaction[
(define-struct posn (x y))
(write (make-posn 1 2))
(struct posn (x y))
(write (posn 1 2))
(define-values (in out) (make-pipe))
(write (make-posn 1 2) out)
(write (posn 1 2) out)
(read in)
]
@interaction[
(define-struct posn (x y) #:transparent)
(write (make-posn 1 2))
(struct posn (x y) #:transparent)
(write (posn 1 2))
(define-values (in out) (make-pipe))
(write (make-posn 1 2) out)
(write (posn 1 2) out)
(define v (read in))
v
(posn? v)
(vector? v)
]
The @scheme[define-serializable-struct] form defines a structure type
that can be @scheme[serialize]d to a value that can be printed using
@scheme[write] and restored via @scheme[read]. The @scheme[serialize]d
result can be @scheme[deserialize]d to get back an instance of the
The @racket[serializable-struct] form defines a structure type
that can be @racket[serialize]d to a value that can be printed using
@racket[write] and restored via @racket[read]. The @racket[serialize]d
result can be @racket[deserialize]d to get back an instance of the
original structure type. The serialization form and functions are
provided by the @schememodname[scheme/serialize] library.
provided by the @racketmodname[racket/serialize] library.
@examples[
(require scheme/serialize)
(define-serializable-struct posn (x y) #:transparent)
(deserialize (serialize (make-posn 1 2)))
(write (serialize (make-posn 1 2)))
(require racket/serialize)
(serializable-struct posn (x y) #:transparent)
(deserialize (serialize (posn 1 2)))
(write (serialize (posn 1 2)))
(define-values (in out) (make-pipe))
(write (serialize (make-posn 1 2)) out)
(write (serialize (posn 1 2)) out)
(deserialize (read in))
]
In addition to the names bound by @scheme[define-struct],
@scheme[define-serializable-struct] binds an identifier with
deserialization information, and it automatically @scheme[provide]s
the deserialization identifier from a module context. This
deserialization identifier is accessed reflectively when a value is
deserialized.
In addition to the names bound by @racket[struct],
@racket[serializable-struct] binds an identifier with deserialization
information, and it automatically @racket[provide]s the
deserialization identifier from a module context. This deserialization
identifier is accessed reflectively when a value is deserialized.
@; ----------------------------------------------------------------------
@section{Bytes, Characters, and Encodings}
@section[#:tag "encodings"]{Bytes, Characters, and Encodings}
Functions like @scheme[read-line], @scheme[read], @scheme[display],
and @scheme[write] all work in terms of @tech{characters} (which
Functions like @racket[read-line], @racket[read], @racket[display],
and @racket[write] all work in terms of @tech{characters} (which
correspond to Unicode scalar values). Conceptually, they are
implemented in terms of @scheme[read-char] and @scheme[write-char].
implemented in terms of @racket[read-char] and @racket[write-char].
More primitively, ports read and write @tech{bytes}, instead of
@tech{characters}. The functions @scheme[read-byte] and
@scheme[write-byte] read and write raw bytes. Other functions, such as
@scheme[read-bytes-line], build on top of byte operations instead of
@tech{characters}. The functions @racket[read-byte] and
@racket[write-byte] read and write raw bytes. Other functions, such as
@racket[read-bytes-line], build on top of byte operations instead of
character operations.
In fact, the @scheme[read-char] and @scheme[write-char] functions are
conceptually implemented in terms of @scheme[read-byte] and
@scheme[write-byte]. When a single byte's value is less than 128, then
In fact, the @racket[read-char] and @racket[write-char] functions are
conceptually implemented in terms of @racket[read-byte] and
@racket[write-byte]. When a single byte's value is less than 128, then
it corresponds to an ASCII character. Any other byte is treated as
part of a UTF-8 sequence, where UTF-8 is a particular standard way of
encoding Unicode scalar values in bytes (which has the nice property
that ASCII characters are encoded as themselves). Thus, a single
@scheme[read-char] may call @scheme[read-byte] multiple times, and a
single @scheme[write-char] may generate multiple output bytes.
@racket[read-char] may call @racket[read-byte] multiple times, and a
single @racket[write-char] may generate multiple output bytes.
The @scheme[read-char] and @scheme[write-char] operations
The @racket[read-char] and @racket[write-char] operations
@emph{always} use a UTF-8 encoding. If you have a text stream that
uses a different encoding, or if you want to generate a text stream in
a different encoding, use @scheme[reencode-input-port] or
@scheme[reencode-output-port]. The @scheme[reencode-input-port]
a different encoding, use @racket[reencode-input-port] or
@racket[reencode-output-port]. The @racket[reencode-input-port]
function converts an input stream from an encoding that you specify
into a UTF-8 stream; that way, @scheme[read-char] sees UTF-8
into a UTF-8 stream; that way, @racket[read-char] sees UTF-8
encodings, even though the original used a different encoding. Beware,
however, that @scheme[read-byte] also sees the re-encoded data,
however, that @racket[read-byte] also sees the re-encoded data,
instead of the original byte stream.
@; ----------------------------------------------------------------------
@section{I/O Patterns}
@section[#:tag "io-patterns"]{I/O Patterns}
@(begin
(define port-eval (make-base-eval))
(interaction-eval #:eval port-eval (require scheme/port)))
(interaction-eval #:eval port-eval (require racket/port)))
If you want to process individual lines of a file, then you can use
@scheme[for] with @scheme[in-lines]:
@racket[for] with @racket[in-lines]:
@interaction[
(define (upcase-all in)
@ -401,8 +427,8 @@ regular expression (see @secref["regexp"]) to the stream:
(has-hello? (open-input-string "goodbye"))
]
If you want to copy one port into another, use @scheme[copy-port] from
@schememodname[scheme/port], which efficiently transfers large blocks
If you want to copy one port into another, use @racket[copy-port] from
@racketmodname[racket/port], which efficiently transfers large blocks
when lots of data is available, but also transfers small blocks
immediately if that's all that is available:

View File

@ -8,14 +8,14 @@
A @deftech{macro} is a syntactic form with an associated
@deftech{transformer} that @deftech{expands} the original form
into existing forms. To put it another way, a macro is an
extension to the Scheme compiler. Most of the syntactic forms of
@schememodname[scheme/base] and @schememodname[scheme] are
extension to the Racket compiler. Most of the syntactic forms of
@racketmodname[racket/base] and @racketmodname[racket] are
actually macros that expand into a small set of core constructs.
Like many languages, Scheme provides pattern-based macros that
Like many languages, Racket provides pattern-based macros that
make simple transformations easy to implement and reliable to
use. Scheme also supports arbitrary macro transformers that are
implemented in Scheme---or in a macro-extended variant of Scheme.
use. Racket also supports arbitrary macro transformers that are
implemented in Racket---or in a macro-extended variant of Racket.
@local-table-of-contents[]

View File

@ -2,16 +2,16 @@
@(require scribble/manual
scribble/eval
"guide-utils.ss"
(for-label scheme/match))
(for-label racket/match))
@(begin
(define match-eval (make-base-eval))
(interaction-eval #:eval match-eval (require scheme/match)))
(interaction-eval #:eval match-eval (require racket/match)))
@title[#:tag "match"]{Pattern Matching}
The @scheme[match] form supports pattern matching on arbitrary Scheme
values, as opposed to functions like @scheme[regexp-match] that
The @racket[match] form supports pattern matching on arbitrary Racket
values, as opposed to functions like @racket[regexp-match] that
compare regular expressions to byte and character sequences (see
@secref["regexp"]).
@ -20,15 +20,15 @@ compare regular expressions to byte and character sequences (see
[pattern expr ...+] ...)
]
The @scheme[match] form takes the result of @scheme[target-expr] and
tries to match each @scheme[_pattern] in order. As soon as it finds a
match, it evaluates the corresponding @scheme[_expr] sequence to
obtain the result for the @scheme[match] form. If @scheme[_pattern]
The @racket[match] form takes the result of @racket[target-expr] and
tries to match each @racket[_pattern] in order. As soon as it finds a
match, it evaluates the corresponding @racket[_expr] sequence to
obtain the result for the @racket[match] form. If @racket[_pattern]
includes @deftech{pattern variables}, they are treated like wildcards,
and each variable is bound in the @scheme[_expr] to the input
and each variable is bound in the @racket[_expr] to the input
fragments that it matched.
Most Scheme literal expressions can be used as patterns:
Most Racket literal expressions can be used as patterns:
@interaction[
#:eval match-eval
@ -45,7 +45,7 @@ Most Scheme literal expressions can be used as patterns:
[#f 'boolean])
]
Constructors like @scheme[cons], @scheme[list], and @scheme[vector]
Constructors like @racket[cons], @racket[list], and @racket[vector]
can be used to create patterns that match pairs, lists, and vectors:
@interaction[
@ -61,16 +61,16 @@ can be used to create patterns that match pairs, lists, and vectors:
[(vector 1 2) 'vector])
]
The @scheme[struct] construct matches an instance of a particular
structure type:
A constructor bound with @scheme[struct] also can be used as a pattern
constructor:
@interaction[
#:eval match-eval
(define-struct shoe (size color))
(define-struct hat (size style))
(match (make-hat 23 'bowler)
[(struct shoe (10 'white)) "bottom"]
[(struct hat (23 'bowler)) "top"])
(struct shoe (size color))
(struct hat (size style))
(match (hat 23 'bowler)
[(shoe 10 'white) "bottom"]
[(hat 23 'bowler) "top"])
]
Unquoted, non-constructor identifiers in a pattern are @tech{pattern
@ -106,8 +106,8 @@ result expression to a list of matches:
[else 'other])
(match '(1 2 3 4)
[(list 1 x ... 4) x])
(match (list (make-hat 23 'bowler) (make-hat 22 'pork-pie))
[(list (struct hat (sz styl)) ...) (apply + sz)])
(match (list (hat 23 'bowler) (hat 22 'pork-pie))
[(list (hat sz styl) ...) (apply + sz)])
]
Ellipses can be nested to match nested repetitions, and in that case,
@ -119,11 +119,11 @@ pattern variables can be bound to lists of lists of matches:
[(list (list '! x ...) ...) x])
]
For information on many more pattern forms, see @schememodname[scheme/match].
For information on many more pattern forms, see @racketmodname[racket/match].
Forms like @scheme[match-let] and @scheme[match-lambda] support
Forms like @racket[match-let] and @racket[match-lambda] support
patterns in positions that otherwise must be identifiers. For example,
@scheme[match-let] generalizes @scheme[let] to a @as-index{destructing
@racket[match-let] generalizes @racket[let] to a @as-index{destructing
bind}:
@interaction[
@ -132,7 +132,7 @@ bind}:
(list z y x))
]
For information on these additional forms, see @schememodname[scheme/match].
For information on these additional forms, see @racketmodname[racket/match].
@refdetails["match"]{pattern matching}

View File

@ -1,12 +1,12 @@
#lang scribble/doc
@(require scribble/manual
scribble/eval
scheme/class
racket/class
"guide-utils.ss")
@title[#:tag "reflection" #:style 'toc]{Reflection and Dynamic Evaluation}
Scheme is a @italic{dynamic} language. It offers numerous facilities
Racket is a @italic{dynamic} language. It offers numerous facilities
for loading, compiling, and even constructing new code at run
time.
@ -14,16 +14,16 @@ time.
@; ----------------------------------------------------------------------
@section[#:tag "eval"]{@scheme[eval]}
@section[#:tag "eval"]{@racket[eval]}
The @scheme[eval] function takes a ``quoted'' expression or definition
The @racket[eval] function takes a ``quoted'' expression or definition
and evaluates it:
@interaction[
(eval '(+ 1 2))
]
The power of @scheme[eval] that is that an expression can be
The power of @racket[eval] that is that an expression can be
constructed dynamically:
@interaction[
@ -36,7 +36,7 @@ constructed dynamically:
]
Of course, if we just wanted to evaluate expressions with given values
for @scheme[x] and @scheme[y], we do not need @scheme[eval]. A more
for @racket[x] and @racket[y], we do not need @racket[eval]. A more
direct approach is to use first-class functions:
@interaction[
@ -46,25 +46,25 @@ direct approach is to use first-class functions:
(apply-formula (lambda (x y) (+ (* x y) y)))
]
However, if expressions like @scheme[(+ x y)] and @scheme[(+ (* x y)
However, if expressions like @racket[(+ x y)] and @racket[(+ (* x y)
y)] are read from a file supplied by a user, for example, then
@scheme[eval] might be appropriate. Simialrly, the @tech{REPL} reads
expressions that are typed by a user and uses @scheme[eval] to
@racket[eval] might be appropriate. Simialrly, the @tech{REPL} reads
expressions that are typed by a user and uses @racket[eval] to
evaluate them.
Also, @scheme[eval] is often used directly or indirectly on whole
Also, @racket[eval] is often used directly or indirectly on whole
modules. For example, a program might load a module on demand using
@scheme[dynamic-require], which is essentially a wrapper around
@scheme[eval] to dynamically load the module code.
@racket[dynamic-require], which is essentially a wrapper around
@racket[eval] to dynamically load the module code.
@; ----------------------------------------
@subsection{Local Scopes}
The @scheme[eval] function cannot see local bindings in the context
where it is called. For example, calling @scheme[eval] inside an
unquoted @scheme[let] form to evaluate a formula does not make values
visible for @scheme[x] and @scheme[y]:
The @racket[eval] function cannot see local bindings in the context
where it is called. For example, calling @racket[eval] inside an
unquoted @racket[let] form to evaluate a formula does not make values
visible for @racket[x] and @racket[y]:
@interaction[
(define (broken-eval-formula formula)
@ -74,29 +74,29 @@ visible for @scheme[x] and @scheme[y]:
(broken-eval-formula '(+ x y))
]
The @scheme[eval] function cannot see the @scheme[x] and @scheme[y]
bindings precisely because it is a function, and Scheme is a lexically
scoped language. Imagine if @scheme[eval] were implemented as
The @racket[eval] function cannot see the @racket[x] and @racket[y]
bindings precisely because it is a function, and Racket is a lexically
scoped language. Imagine if @racket[eval] were implemented as
@schemeblock[
@racketblock[
(define (eval x)
(eval-expanded (macro-expand x)))
]
then at the point when @scheme[eval-expanded] is called, the most
recent binding of @scheme[x] is to the expression to evaluate, not the
@scheme[let] binding in @scheme[broken-eval-formula]. Lexical scope
then at the point when @racket[eval-expanded] is called, the most
recent binding of @racket[x] is to the expression to evaluate, not the
@racket[let] binding in @racket[broken-eval-formula]. Lexical scope
prevents such confusing and fragile behavior, and consequently
prevents @scheme[eval] from seeing local bindings in the context where
prevents @racket[eval] from seeing local bindings in the context where
it is called.
You might imagine that even though @scheme[eval] cannot see the local
bindings in @scheme[broken-eval-formula], there must actually be a
data structure mapping @scheme[x] to @scheme[2] and @scheme[y] to
@scheme[3], and you would like a way to get that data structure. In
You might imagine that even though @racket[eval] cannot see the local
bindings in @racket[broken-eval-formula], there must actually be a
data structure mapping @racket[x] to @racket[2] and @racket[y] to
@racket[3], and you would like a way to get that data structure. In
fact, no such data structure exists; the compiler is free to replace
every use of @scheme[x] with @scheme[2] at compile time, so that the
local binding of @scheme[x] does not exist in any concrete sense at
every use of @racket[x] with @racket[2] at compile time, so that the
local binding of @racket[x] does not exist in any concrete sense at
run-time. Even when variables cannot be eliminated by
constant-folding, normally the names of the variables can be
eliminated, and the data structures that hold local values do not
@ -106,26 +106,29 @@ resemble a mapping from names to values.
@subsection[#:tag "namespaces"]{Namespaces}
Since @scheme[eval] cannot see the bindings from the context where it
Since @racket[eval] cannot see the bindings from the context where it
is called, another mechanism is needed to determine dynamically
available bindings. A @deftech{namespace} is a first-class value that
encapsulates the bindings available for dynamic evaluation.
@margin-note{Informally, the term @defterm{namespace} is sometimes
used interchangeably with @defterm{environment} or
@defterm{scope}. In PLT Scheme, the term @defterm{namespace} has the
@defterm{scope}. In Racket, the term @defterm{namespace} has the
more specific, dynamic meaning given above, and it should not be
confused with static lexical concepts.}
Some functions, such as @scheme[eval], accept an optional namespace
Some functions, such as @racket[eval], accept an optional namespace
argument. More often, the namespace used by a dynamic operation is the
@deftech{current namespace} as determined by the
@scheme[current-namespace] parameter.
@racket[current-namespace] @tech{parameter}.
When @scheme[eval] is used in a @tech{REPL}, the current is the one
@margin-note{See @secref["parameterize"] for an introduction to
parameters.}
When @racket[eval] is used in a @tech{REPL}, the current is the one
that the @tech{REPL} uses for evaluating expressions. That's why the
following interaction successfully accesses @scheme[x] via
@scheme[eval]:
following interaction successfully accesses @racket[x] via
@racket[eval]:
@interaction[
(define x 3)
@ -133,34 +136,34 @@ following interaction successfully accesses @scheme[x] via
]
In contrast, try the following a simple module and running in directly
in DrScheme's @onscreen{Module} language or supplying the file as a
command-line argument to @exec{mzscheme}:
in DrRacket or supplying the file as a command-line argument to
@exec{racket}:
@schememod[
scheme
@racketmod[
racket
(eval '(cons 1 2))
]
This fails because the initial current namespace is empty. When you
run @exec{mzscheme} in interactive mode (see
run @exec{racket} in interactive mode (see
@secref["start-interactive-mode"]), the initial namespace is
initialized with the exports of the @scheme[scheme] module, but when
initialized with the exports of the @racket[racket] module, but when
you run a module directly, the initial namespace starts empty.
In general, it's a bad idea to use @scheme[eval] with whatever
In general, it's a bad idea to use @racket[eval] with whatever
namespace happens to be installed. Instead, create a namespace
explicitly and install it for the call to eval:
@schememod[
scheme
@racketmod[
racket
(define ns (make-base-namespace))
(eval '(cons 1 2) ns) (code:comment @#,t{works})
]
The @scheme[make-base-namespace] function creates a namespace that is
initialized with the exports of @scheme[scheme/base]. The later
The @racket[make-base-namespace] function creates a namespace that is
initialized with the exports of @racket[racket/base]. The later
section @secref["mk-namespace"] provides more information on creating
and configuring namespaces.
@ -168,40 +171,40 @@ and configuring namespaces.
@subsection{Namespaces and Modules}
As with @scheme[let] bindings, lexical scope means that @scheme[eval]
cannot automatically see the definitions of a @scheme[module] in which
it is called. Unlike @scheme[let] bindings, however, Scheme provides a
As with @racket[let] bindings, lexical scope means that @racket[eval]
cannot automatically see the definitions of a @racket[module] in which
it is called. Unlike @racket[let] bindings, however, Racket provides a
way to reflect a module into a @tech{namespace}.
The @scheme[module->namespace] function takes a quoted @tech{module
The @racket[module->namespace] function takes a quoted @tech{module
path} and produces a namespace for evaluating expressions and
definitions as if they appears in the @scheme[module] body:
definitions as if they appears in the @racket[module] body:
@interaction[
(module m scheme/base
(module m racket/base
(define x 11))
(require 'm)
(define ns (module->namespace ''m))
(eval 'x ns)
]
@margin-note{The double quoting in @scheme[''m] is because @scheme['m]
@margin-note{The double quoting in @racket[''m] is because @racket['m]
is a module path that refers to an interactively declared module, and
so @scheme[''m] is the quoted form of the path.}
so @racket[''m] is the quoted form of the path.}
The @scheme[module->namespace] function is mostly useful from outside
The @racket[module->namespace] function is mostly useful from outside
a module, where the module's full name is known. Inside a
@scheme[module] form, however, the full name of a module may not be
@racket[module] form, however, the full name of a module may not be
known, because it may depend on where the module source is location
when it is eventually loaded.
From within a @scheme[module], use @scheme[define-namespace-anchor] to
From within a @racket[module], use @racket[define-namespace-anchor] to
declare a reflection hook on the module, and use
@scheme[namespace-anchor->namespace] to reel in the module's
@racket[namespace-anchor->namespace] to reel in the module's
namespace:
@schememod[
scheme
@racketmod[
racket
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
@ -209,7 +212,7 @@ scheme
(define x 1)
(define y 2)
(eval '(cons x y) ns) (code:comment @#,t{produces @schemeresult[(1 . 2)]})
(eval '(cons x y) ns) (code:comment @#,t{produces @racketresult[(1 . 2)]})
]
@ -222,8 +225,8 @@ A @tech{namespace} encapsulates two pieces of information:
@itemize[
@item{A mapping from identifiers to bindings. For example, a
namespace might map the identifier @schemeidfont{lambda} to the
@scheme[lambda] form. An ``empty'' namespace is one that maps
namespace might map the identifier @racketidfont{lambda} to the
@racket[lambda] form. An ``empty'' namespace is one that maps
every identifier to an uninitialized top-level variable.}
@item{A mapping from module names to module declarations and
@ -232,39 +235,39 @@ A @tech{namespace} encapsulates two pieces of information:
]
The first mapping is used for evaluating expressions in a top-level
context, as in @scheme[(eval '(lambda (x) (+ x 1)))]. The second
mapping is used, for example, by @scheme[dynamic-require] to locate a
module. The call @scheme[(eval '(require scheme/base))] normally uses
context, as in @racket[(eval '(lambda (x) (+ x 1)))]. The second
mapping is used, for example, by @racket[dynamic-require] to locate a
module. The call @racket[(eval '(require racket/base))] normally uses
both pieces: the identifier mapping determines the binding of
@schemeidfont{require}; if it turns out to mean @scheme[require], then
the module mapping is used to locate the @schememodname[scheme/base]
@racketidfont{require}; if it turns out to mean @racket[require], then
the module mapping is used to locate the @racketmodname[racket/base]
module.
From the perspective of the core Scheme run-time system, all
From the perspective of the core Racket run-time system, all
evaluation is reflective. Execution starts with an initial namespace
that contains a few primitive modules, and that is further populated
by loading files and modules as specified on the command line or as
supplied in the @tech{REPL}. Top-level @scheme[require] and
@scheme[define] forms adjusts the identifier mapping, and module
declarations (typically loaded on demand for a @scheme[require] form)
supplied in the @tech{REPL}. Top-level @racket[require] and
@racket[define] forms adjusts the identifier mapping, and module
declarations (typically loaded on demand for a @racket[require] form)
adjust the module mapping.
@; ----------------------------------------
@subsection{Creating and Installing Namespaces}
The function @scheme[make-empty-namespace] creates a new, empty
The function @racket[make-empty-namespace] creates a new, empty
@tech{namespace}. Since the namespace is truly empty, it cannot at
first be used to evaluate any top-level expression---not even
@scheme[(require scheme)]. In particular,
@racket[(require racket)]. In particular,
@schemeblock[
@racketblock[
(parameterize ([current-namespace (make-empty-namespace)])
(namespace-require 'scheme))
(namespace-require 'racket))
]
fails, because the namespace does not include the primitive modules on
which @scheme[scheme] is built.
which @racket[racket] is built.
To make a namespace useful, some modules much be @deftech{attached}
from an existing namespace. Attaching a module adjusts the mapping of
@ -272,47 +275,47 @@ module names to instances by transitively copying entries (the module
and all its imports) from an existing namespace's mapping. Normally,
instead of just attaching the primitive modules---whose names and
organization are subject to change---a higher-level module is
attached, such as @schememodname[scheme] or
@schememodname[scheme/base].
attached, such as @racketmodname[racket] or
@racketmodname[racket/base].
The @scheme[make-base-empty-namespace] function provides a namespace
that is empty, except that @schememodname[scheme/base] is
The @racket[make-base-empty-namespace] function provides a namespace
that is empty, except that @racketmodname[racket/base] is
attached. The resulting namespace is still ``empty'' in the sense that
the identifiers-to-bindings part of the namespace has no mappings;
only the module mapping has been populated. Nevertheless, with an
initial module mapping, further modules can be loaded.
A namespace created with @scheme[make-base-empty-namespace] is
A namespace created with @racket[make-base-empty-namespace] is
suitable for many basic dynamic tasks. For example, suppose that a
@schememodfont{my-dsl} library implements a domain-specific language
@racketmodfont{my-dsl} library implements a domain-specific language
in which you want to execute commands from a user-specified file. A
namespace created with @scheme[make-base-empty-namespace] is enough to
namespace created with @racket[make-base-empty-namespace] is enough to
get started:
@schemeblock[
@racketblock[
(define (run-dsl file)
(parameterize ([current-namespace (make-base-empty-namespace)])
(namespace-require 'my-dsl)
(load file)))
]
Note that the @scheme[parameterize] of @scheme[current-namespace] does
not affect the meaning of identifiers like @scheme[namespace-require]
within the @scheme[parameterize] body. Those identifiers obtain their
Note that the @racket[parameterize] of @racket[current-namespace] does
not affect the meaning of identifiers like @racket[namespace-require]
within the @racket[parameterize] body. Those identifiers obtain their
meaning from the enclosing context (probably a module). Only
expressions that are dynamic with respect to this code, such as the
content of @scheme[load]ed files, are affected by the
@scheme[parameterize].
content of @racket[load]ed files, are affected by the
@racket[parameterize].
Another subtle point in the above example is the use of
@scheme[(namespace-require 'my-dsl)] instead of @scheme[(eval
'(require my-dsl))]. The latter would not work, because @scheme[eval]
needs to obtain a meaning for @scheme[require] in the namespace, and
@racket[(namespace-require 'my-dsl)] instead of @racket[(eval
'(require my-dsl))]. The latter would not work, because @racket[eval]
needs to obtain a meaning for @racket[require] in the namespace, and
the namespace's identifier mapping is initially empty. The
@scheme[namespace-require] function, in contrast, directly imports the
@racket[namespace-require] function, in contrast, directly imports the
given module into the current namespace. Starting with
@scheme[(namespace-require 'scheme/base)] would introduce a binding
for @schemeidfont{require} and make a subsequent @scheme[(eval
@racket[(namespace-require 'racket/base)] would introduce a binding
for @racketidfont{require} and make a subsequent @racket[(eval
'(require my-dsl))] work. The above is better, not only because it is
more compact, but also because it avoids introducing bindings that are
not part of the domain-specific languages.
@ -323,88 +326,88 @@ not part of the domain-specific languages.
Modules not attached to a new namespace will be loaded and
instantiated afresh if they are demanded by evaluation. For example,
@schememodname[scheme/base] does not include
@schememodname[scheme/class], and loading @schememodname[scheme/class]
@racketmodname[racket/base] does not include
@racketmodname[racket/class], and loading @racketmodname[racket/class]
again will create a distinct class datatype:
@interaction[
(require scheme/class)
(require racket/class)
(class? object%)
(class?
(parameterize ([current-namespace (make-base-empty-namespace)])
(namespace-require 'scheme/class) (code:comment @#,t{loads again})
(namespace-require 'racket/class) (code:comment @#,t{loads again})
(eval 'object%)))
]
For cases when dynamically loaded code needs to share more code and
data with its context, use the @scheme[namespace-attach-module]
function. The first argument to @scheme[namespace-attach-module] is a
data with its context, use the @racket[namespace-attach-module]
function. The first argument to @racket[namespace-attach-module] is a
source namespace from which to draw a module instance; in some cases,
the current namespace is known to include the module that needs to be
shared:
@interaction[
(require scheme/class)
(require racket/class)
(class?
(let ([ns (make-base-empty-namespace)])
(namespace-attach-module (current-namespace)
'scheme/class
'racket/class
ns)
(parameterize ([current-namespace ns])
(namespace-require 'scheme/class) (code:comment @#,t{uses attached})
(namespace-require 'racket/class) (code:comment @#,t{uses attached})
(eval 'object%))))
]
Within a module, however, the combination of
@scheme[define-namespace-anchor] and
@scheme[namespace-anchor->empty-namespace] offers a more reliable
@racket[define-namespace-anchor] and
@racket[namespace-anchor->empty-namespace] offers a more reliable
method for obtaining a source namespace:
@schememod[
scheme/base
@racketmod[
racket/base
(require scheme/class)
(require racket/class)
(define-namespace-anchor a)
(define (load-plug-in file)
(let ([ns (make-base-empty-namespace)])
(namespace-attach-module (namespace-anchor->empty-namespace a)
'scheme/class
'racket/class
ns)
(parameterize ([current-namespace ns])
(dynamic-require file 'plug-in%))))
]
The anchor bound by @scheme[namespace-attach-module] connects the
The anchor bound by @racket[namespace-attach-module] connects the
run time of a module with the namespace in which a module is loaded
(which might differ from the current namespace). In the above
example, since the enclosing module requires
@schememodname[scheme/class], the namespace produced by
@scheme[namespace-anchor->empty-namespace] certainly contains an
instance of @schememodname[scheme/class]. Moreover, that instance is
@racketmodname[racket/class], the namespace produced by
@racket[namespace-anchor->empty-namespace] certainly contains an
instance of @racketmodname[racket/class]. Moreover, that instance is
the same as the one imported into the module, so the class datatype is
shared.
@; ----------------------------------------------------------------------
@section[#:tag "load"]{Scripting Evaluation and Using @scheme[load]}
@section[#:tag "load"]{Scripting Evaluation and Using @racket[load]}
Historically, Scheme and Lisp systems did not offer module
Historically, Lisp implementations did not offer module
systems. Instead, large programs were built by essentially scripting
the @tech{REPL} to evaluate program fragments in a particular order.
While @tech{REPL} scripting turns out to be a bad way to structure
programs and libraries, it is still sometimes a useful capability.
@margin-note{Describing a program via @scheme[load] interacts
@margin-note{Describing a program via @racket[load] interacts
especially badly with macro-defined language extensions
@cite["Flatt02"].}
The @scheme[load] function runs a @tech{REPL} script by
@scheme[read]ing S-expressions from a file, one by one, and passing
them to @scheme[eval]. If a file @filepath{place.scm} contains
The @racket[load] function runs a @tech{REPL} script by
@racket[read]ing S-expressions from a file, one by one, and passing
them to @racket[eval]. If a file @filepath{place.rkts} contains
@schemeblock[
@racketblock[
(define city "Salt Lake City")
(define state "Utah")
(printf "~a, ~a\n" city state)
@ -413,86 +416,86 @@ them to @scheme[eval]. If a file @filepath{place.scm} contains
then it can be loaded in a @tech{REPL}:
@interaction[
(eval:alts (load "place.scm") (begin (define city "Salt Lake City")
(eval:alts (load "place.rkts") (begin (define city "Salt Lake City")
(printf "~a, Utah\n" city)))
city
]
Since @scheme[load] uses @scheme[eval], however, a module like the
Since @racket[load] uses @racket[eval], however, a module like the
following generally will not work---for the same reasons described in
@secref["namespaces"]:
@schememod[
scheme
@racketmod[
racket
(define there "Utopia")
(load "here.scm")
(load "here.rkts")
]
The current namespace for evaluating the content of
@filepath{here.scm} is likely to be empty; in any case, you cannot get
@scheme[there] from @filepath{here.scm}. Also, any definitions in
@filepath{here.scm} will not become visible for use within the module;
after all, the @scheme[load] happens dynamically, while references to
@filepath{here.rkts} is likely to be empty; in any case, you cannot get
@racket[there] from @filepath{here.rkts}. Also, any definitions in
@filepath{here.rkts} will not become visible for use within the module;
after all, the @racket[load] happens dynamically, while references to
identifiers within the module are resolved lexically, and therefore
statically.
Unlike @scheme[eval], @scheme[load] does not accept a namespace
argument. To supply a namespace to @scheme[load], set the
@scheme[current-namespace] parameter. The following example evaluates
the expressions in @filepath{here.scm} using the bindings of the
@schememodname[scheme/base] module:
Unlike @racket[eval], @racket[load] does not accept a namespace
argument. To supply a namespace to @racket[load], set the
@racket[current-namespace] @tech{parameter}. The following example evaluates
the expressions in @filepath{here.rkts} using the bindings of the
@racketmodname[racket/base] module:
@schememod[
scheme
@racketmod[
racket
(parameterize ([current-namespace (make-base-namespace)])
(load "here.scm"))
(load "here.rkts"))
]
You can even use @scheme[namespace-anchor->namespace] to make the
You can even use @racket[namespace-anchor->namespace] to make the
bindings of the enclosing module accessible for dynamic evaluation. In
the following example, when @filepath{here.scm} is @scheme[load]ed, it
can refer to @scheme[there] as well as the bindings of
@schememodname[scheme]:
the following example, when @filepath{here.rkts} is @racket[load]ed, it
can refer to @racket[there] as well as the bindings of
@racketmodname[racket]:
@schememod[
scheme
@racketmod[
racket
(define there "Utopia")
(define-namespace-anchor a)
(parameterize ([current-namespace (namespace-anchor->namespace a)])
(load "here.scm"))
(load "here.rkts"))
]
Still, if @filepath{here.scm} defines any identifiers, the definitions
Still, if @filepath{here.rkts} defines any identifiers, the definitions
cannot be directly (i.e., statically) referenced by in the enclosing
module.
The @schememodname[scheme/load] module language is different from
@schememodname[scheme] or @schememodname[scheme/base]. A module using
@schememodname[scheme/load] treats all of its content as dynamic,
passing each form in the module body to @scheme[eval] (using a
namespace that is initialized with @schememodname[scheme]). As a
result, uses of @scheme[eval] and @scheme[load] in the module body see
The @racketmodname[racket/load] module language is different from
@racketmodname[racket] or @racketmodname[racket/base]. A module using
@racketmodname[racket/load] treats all of its content as dynamic,
passing each form in the module body to @racket[eval] (using a
namespace that is initialized with @racketmodname[racket]). As a
result, uses of @racket[eval] and @racket[load] in the module body see
the same dynamic namespace as immediate body forms. For example, if
@filepath{here.scm} contains
@filepath{here.rkts} contains
@schemeblock[
@racketblock[
(define here "Morporkia")
(define (go!) (set! here there))
]
then running
@schememod[
scheme/load
@racketmod[
racket/load
(define there "Utopia")
(load "here.scm")
(load "here.rkts")
(go!)
(printf "~a\n" here)
@ -500,12 +503,12 @@ scheme/load
prints ``Utopia''.
Drawbacks of using @schememodname[scheme/load] include reduced
Drawbacks of using @racketmodname[racket/load] include reduced
error checking, tool support, and performance. For example, with the
program
@schememod[
scheme/load
@racketmod[
racket/load
(define good 5)
(printf "running\n")
@ -513,7 +516,7 @@ good
bad
]
DrScheme's @onscreen{Check Syntax} tool cannot tell that the second
@scheme[good] is a reference to the first, and the unbound reference
to @scheme[bad] is reported only at run time instead of rejected
DrRacket's @onscreen{Check Syntax} tool cannot tell that the second
@racket[good] is a reference to the first, and the unbound reference
to @racket[bad] is reported only at run time instead of rejected
syntactically.

View File

@ -4,22 +4,22 @@
@title{More Libraries}
@other-manual['(lib "scribblings/gui/gui.scrbl")] describes the PLT
Scheme graphics toolbox, whose core is implemented by the @exec{mred}
@other-manual['(lib "scribblings/gui/gui.scrbl")] describes the Racket
graphics toolbox, whose core is implemented by the @exec{gracket}
executable.
@other-manual['(lib "scribblings/foreign/foreign.scrbl")] describes
tools for using Scheme to access libraries that are normally used by C
tools for using Racket to access libraries that are normally used by C
programs.
@other-manual['(lib "web-server/scribblings/web-server.scrbl")]
describes the PLT Scheme web server, which supports servlets
implemented in Scheme.
describes the Racket web server, which supports servlets implemented
in Racket.
@link["../index.html"]{PLT Scheme Documentation} lists documentation
for many other installed libraries. Run @exec{plt-help} to find
@link["../index.html"]{Racket Documentation} lists documentation for
many other installed libraries. Run @exec{raco docs} to find
documentation for libraries that are installed on your system and
specific to your user account.
@link["http://planet.plt-scheme.org/"]{@|PLaneT|} offers even more
downloadable packages contributed by PLT Scheme users.
@link["http://planet.plt-racket.org/"]{@|PLaneT|} offers even more
downloadable packages contributed by Racketeers.

View File

@ -11,52 +11,52 @@ match parts of the pattern.
@; ----------------------------------------
@section{@scheme[define-syntax-rule]}
@section{@racket[define-syntax-rule]}
The simplest way to create a macro is to use
@scheme[define-syntax-rule]:
@racket[define-syntax-rule]:
@specform[(define-syntax-rule pattern template)]
As a running example, consider the @scheme[swap] macro, which swaps
As a running example, consider the @racket[swap] macro, which swaps
the values stored in two variables. It can be implemented using
@scheme[define-syntax-rule] as follows:
@racket[define-syntax-rule] as follows:
@margin-note{The macro is ``un-Schemely'' in the sense that it
@margin-note{The macro is ``un-Rackety'' in the sense that it
involves side effects on variables---but the point of macros is to let
you add syntactic forms that some other language designer might not
approve.}
@schemeblock[
@racketblock[
(define-syntax-rule (swap x y)
(let ([tmp x])
(set! x y)
(set! y tmp)))
]
The @scheme[define-syntax-rule] form binds a macro that matches a
The @racket[define-syntax-rule] form binds a macro that matches a
single pattern. The pattern must always start with an open parenthesis
followed by an identifier, which is @scheme[swap] in this case. After
followed by an identifier, which is @racket[swap] in this case. After
the initial identifier, other identifiers are @deftech{macro pattern
variables} that can match anything in a use of the macro. Thus, this
macro matches the for @scheme[(swap _form_1 _form_2)] for any
@scheme[_form_1] and @scheme[_form_2].
macro matches the form @racket[(swap _form1 _form2)] for any
@racket[_form_1] and @racket[_form_2].
@margin-note{Macro pattern variables similar to pattern variables for
@scheme[match]. See @secref["match"].}
@racket[match]. See @secref["match"].}
After the pattern in @scheme[define-syntax-rule] is the
After the pattern in @racket[define-syntax-rule] is the
@deftech{template}. The template is used in place of a form that
matches the pattern, except that each instance of a pattern variable
in the template is replaced with the part of the macro use the pattern
variable matched. For example, in
@schemeblock[(swap first last)]
@racketblock[(swap first last)]
the pattern variable @scheme[x] matches @scheme[first] and @scheme[y]
matches @scheme[last], so that the expansion is
the pattern variable @racket[x] matches @racket[first] and @racket[y]
matches @racket[last], so that the expansion is
@schemeblock[
@racketblock[
(let ([tmp first])
(set! first last)
(set! last tmp))
@ -66,20 +66,20 @@ matches @scheme[last], so that the expansion is
@section{Lexical Scope}
Suppose that we use the @scheme[swap] macro to swap variables named
@scheme[tmp] and @scheme[other]:
Suppose that we use the @racket[swap] macro to swap variables named
@racket[tmp] and @racket[other]:
@schemeblock[
@racketblock[
(let ([tmp 5]
[other 6])
(swap tmp other)
(list tmp other))
]
The result of the above expression should be @schemeresult[(6 5)]. The
naive expansion of this use of @scheme[swap], however, is
The result of the above expression should be @racketresult[(6 5)]. The
naive expansion of this use of @racket[swap], however, is
@schemeblock[
@racketblock[
(let ([tmp 5]
[other 6])
(let ([tmp tmp])
@ -88,14 +88,14 @@ naive expansion of this use of @scheme[swap], however, is
(list tmp other))
]
whose result is @schemeresult[(5 6)]. The problem is that the naive
expansion confuses the @scheme[tmp] in the context where @scheme[swap]
is used with the @scheme[tmp] that is in the macro template.
whose result is @racketresult[(5 6)]. The problem is that the naive
expansion confuses the @racket[tmp] in the context where @racket[swap]
is used with the @racket[tmp] that is in the macro template.
Scheme doesn't produce the naive expansion for the above use of
@scheme[swap]. Instead, it produces
Racket doesn't produce the naive expansion for the above use of
@racket[swap]. Instead, it produces
@schemeblock[
@racketblock[
(let ([tmp 5]
[other 6])
(let ([tmp_1 tmp])
@ -104,10 +104,10 @@ Scheme doesn't produce the naive expansion for the above use of
(list tmp other))
]
with the correct result in @schemeresult[(6 5)]. Similarly, in the
with the correct result in @racketresult[(6 5)]. Similarly, in the
example
@schemeblock[
@racketblock[
(let ([set! 5]
[other 6])
(swap set! other)
@ -116,7 +116,7 @@ example
the expansion is
@schemeblock[
@racketblock[
(let ([set!_1 5]
[other 6])
(let ([tmp_1 tmp])
@ -125,23 +125,23 @@ the expansion is
(list set!_1 other))
]
so that the local @scheme[set!] binding doesn't interfere with the
so that the local @racket[set!] binding doesn't interfere with the
assignments introduced by the macro template.
In other words, Scheme's pattern-based macros automatically maintain
In other words, Racket's pattern-based macros automatically maintain
lexical scope, so macro implementors can reason about variable
reference in macros and macro uses in the same way as for functions
and function calls.
@; ----------------------------------------
@section{@scheme[define-syntax] and @scheme[syntax-rules]}
@section{@racket[define-syntax] and @racket[syntax-rules]}
The @scheme[define-syntax-rule] form binds a macro that matches a
single pattern, but Scheme's macro system supports transformers that
The @racket[define-syntax-rule] form binds a macro that matches a
single pattern, but Racket's macro system supports transformers that
match multiple patterns starting with the same identifier. To write
such macros, the programmer much use the more general
@scheme[define-syntax] form along with the @scheme[syntax-rules]
@racket[define-syntax] form along with the @racket[syntax-rules]
transformer form:
@specform[#:literals (syntax-rules)
@ -150,25 +150,25 @@ transformer form:
[pattern template]
...))]
@margin-note{The @scheme[define-syntax-rule] form is itself a macro
that expands into @scheme[define-syntax] with a @scheme[syntax-rules]
@margin-note{The @racket[define-syntax-rule] form is itself a macro
that expands into @racket[define-syntax] with a @racket[syntax-rules]
form that contains only one pattern and template.}
For example, suppose we would like a @scheme[rotate] macro that
generalizes @scheme[swap] to work on either two or three identifiers,
For example, suppose we would like a @racket[rotate] macro that
generalizes @racket[swap] to work on either two or three identifiers,
so that
@schemeblock[
@racketblock[
(let ([red 1] [green 2] [blue 3])
(rotate red green) (code:comment @#,t{swaps})
(rotate red green blue) (code:comment @#,t{rotates left})
(list red green blue))
]
produces @schemeresult[(1 3 2)]. We can implement @scheme[rotate]
using @scheme[syntax-rules]:
produces @racketresult[(1 3 2)]. We can implement @racket[rotate]
using @racket[syntax-rules]:
@schemeblock[
@racketblock[
(define-syntax rotate
(syntax-rules ()
[(rotate a b) (swap a b)]
@ -177,27 +177,27 @@ using @scheme[syntax-rules]:
(swap b c))]))
]
The expression @scheme[(rotate red green)] matches the first pattern
in the @scheme[syntax-rules] form, so it expands to @scheme[(swap red
green)]. The expression @scheme[(rotate a b c)] matches the second
pattern, so it expands to @scheme[(begin (swap red green) (swap green
The expression @racket[(rotate red green)] matches the first pattern
in the @racket[syntax-rules] form, so it expands to @racket[(swap red
green)]. The expression @racket[(rotate a b c)] matches the second
pattern, so it expands to @racket[(begin (swap red green) (swap green
blue))].
@; ----------------------------------------
@section{Matching Sequences}
A better @scheme[rotate] macro would allow any number of identifiers,
instead of just two or three. To match a use of @scheme[rotate] with
A better @racket[rotate] macro would allow any number of identifiers,
instead of just two or three. To match a use of @racket[rotate] with
any number of identifiers, we need a pattern form that has something
like a Kleene star. In a Scheme macro pattern, a star is written as
@scheme[...].
like a Kleene star. In a Racket macro pattern, a star is written as
@racket[...].
To implement @scheme[rotate] with @scheme[...], we need a base case to
To implement @racket[rotate] with @racket[...], we need a base case to
handle a single identifier, and an inductive case to handle more than
one identifier:
@schemeblock[
@racketblock[
(define-syntax rotate
(syntax-rules ()
[(rotate a) (void)]
@ -206,19 +206,19 @@ one identifier:
(rotate b c ...))]))
]
When a pattern variable like @scheme[c] is followed by @scheme[...] in
a pattern, then it must be followed by @scheme[...] in a template,
When a pattern variable like @racket[c] is followed by @racket[...] in
a pattern, then it must be followed by @racket[...] in a template,
too. The pattern variable effectively matches a sequence of zero or
more forms, and it is replaced in the template by the same sequence.
Both versions of @scheme[rotate] so far are a bit inefficient, since
Both versions of @racket[rotate] so far are a bit inefficient, since
pairwise swapping keeps moving the value from the first variable into
every variable in the sequence until it arrives at the last one. A
more efficient @scheme[rotate] would move the first value directly to
the last variable. We can use @scheme[...] patterns to implement the
more efficient @racket[rotate] would move the first value directly to
the last variable. We can use @racket[...] patterns to implement the
more efficient variant using a helper macro:
@schemeblock[
@racketblock[
(define-syntax rotate
(syntax-rules ()
[(rotate a c ...)
@ -232,18 +232,18 @@ more efficient variant using a helper macro:
(set! to0 tmp))]))
]
In the @scheme[shift-to] macro, @scheme[...] in the template follows
@scheme[(set! to from)], which causes the @scheme[(set! to from)]
In the @racket[shift-to] macro, @racket[...] in the template follows
@racket[(set! to from)], which causes the @racket[(set! to from)]
expression to be duplicated as many times as necessary to use each
identifier matched in the @scheme[to] and @scheme[from]
sequences. (The number of @scheme[to] and @scheme[from] matches must
identifier matched in the @racket[to] and @racket[from]
sequences. (The number of @racket[to] and @racket[from] matches must
be the same, otherwise the macro expansion fails with an error.)
@; ----------------------------------------
@section{Identifier Macros}
Given our macro definitions, the @scheme[swap] or @scheme[rotate]
Given our macro definitions, the @racket[swap] or @racket[rotate]
identifiers must be used after an open parenthesis, otherwise a syntax
error is reported:
@ -252,13 +252,13 @@ error is reported:
@interaction[(+ swap 3)]
An @deftech{identifier macro} works in any expression. For example, we
can define @scheme[clock] as an identifier macro that expands to
@scheme[(get-clock)], so @scheme[(+ clock 3)] would expand to
@scheme[(+ (get-clock) 3)]. An identifier macro also cooperates with
@scheme[set!], and we can define @scheme[clock] so that @scheme[(set!
clock 3)] expands to @scheme[(put-clock! 3)].
can define @racket[clock] as an identifier macro that expands to
@racket[(get-clock)], so @racket[(+ clock 3)] would expand to
@racket[(+ (get-clock) 3)]. An identifier macro also cooperates with
@racket[set!], and we can define @racket[clock] so that @racket[(set!
clock 3)] expands to @racket[(put-clock! 3)].
The @scheme[syntax-id-rules] form is like @scheme[syntax-rules], but
The @racket[syntax-id-rules] form is like @racket[syntax-rules], but
it creates a transformer that acts as an identifier macro:
@specform[#:literals (syntax-id-rules)
@ -267,12 +267,12 @@ it creates a transformer that acts as an identifier macro:
[pattern template]
...))]
Unlike a @scheme[syntax-rules] form, the @scheme[_pattern]s are not
required to start with an open parenthesis. Also, @scheme[set!] is
typically used as a literal to match a use of @scheme[set!] in the
Unlike a @racket[syntax-rules] form, the @racket[_pattern]s are not
required to start with an open parenthesis. Also, @racket[set!] is
typically used as a literal to match a use of @racket[set!] in the
pattern (as opposed to being a pattern variable.
@schemeblock[
@racketblock[
(define-syntax clock
(syntax-id-rules (set!)
[(set! clock e) (put-clock! e)]
@ -280,29 +280,29 @@ pattern (as opposed to being a pattern variable.
[clock (get-clock)]))
]
The @scheme[(clock a ...)] pattern is needed because, when an
The @racket[(clock a ...)] pattern is needed because, when an
identifier macro is used after an open parenthesis, the macro
transformer is given the whole form, like with a non-identifier macro.
Put another way, the @scheme[syntax-rules] form is essentially a
special case of the @scheme[syntax-id-rules] form with errors in the
@scheme[set!] and lone-identifier cases.
Put another way, the @racket[syntax-rules] form is essentially a
special case of the @racket[syntax-id-rules] form with errors in the
@racket[set!] and lone-identifier cases.
@; ----------------------------------------
@section{Macro-Generating Macros}
Suppose that we have many identifier like @scheme[clock] that we'd
Suppose that we have many identifier like @racket[clock] that we'd
like to redirect to accessor and mutator functions like
@scheme[get-clock] and @scheme[put-clock!]. We'd like to be able to
@racket[get-clock] and @racket[put-clock!]. We'd like to be able to
just write
@schemeblock[
@racketblock[
(define-get/put-id clock get-clock put-clock!)
]
Naturally, we can implement @scheme[define-get/put-id] as a macro:
Naturally, we can implement @racket[define-get/put-id] as a macro:
@schemeblock[
@racketblock[
(define-syntax-rule (define-get/put-id id get put!)
(define-syntax id
(syntax-id-rules (set!)
@ -311,25 +311,25 @@ Naturally, we can implement @scheme[define-get/put-id] as a macro:
[id (get)])))
]
The @scheme[define-get/put-id] macro is a @deftech{macro-generating
The @racket[define-get/put-id] macro is a @deftech{macro-generating
macro}. The only non-obvious part of its definition is the
@scheme[(... ...)], which ``quotes'' @scheme[...] so that it takes its
@racket[(... ...)], which ``quotes'' @racket[...] so that it takes its
usual role in the generated macro, instead of the generating macro.
@; ----------------------------------------
@section[#:tag "pattern-macro-example"]{Extended Example: Call-by-Reference Functions}
We can use pattern-matching macros to add a form to Scheme
We can use pattern-matching macros to add a form to Racket
for defining first-order @deftech{call-by-reference} functions. When a
call-by-reference function body mutates its formal argument, the
mutation applies to variables that are supplied as actual arguments in
a call to the function.
For example, if @scheme[define-cbr] is like @scheme[define] except
For example, if @racket[define-cbr] is like @racket[define] except
that it defines a call-by-reference function, then
@schemeblock[
@racketblock[
(define-cbr (f a b)
(swap a b))
@ -338,35 +338,35 @@ that it defines a call-by-reference function, then
(list x y))
]
produces @schemeresult[(2 1)].
produces @racketresult[(2 1)].
We will implement call-by-reference functions by having function calls
supply accessor and mutators for the arguments, instead of supplying
argument values directly. In particular, for the function @scheme[f]
argument values directly. In particular, for the function @racket[f]
above, we'll generate
@schemeblock[
@racketblock[
(define (do-f get-a get-b put-a! put-b!)
(define-get/put-id a get-a put-a!)
(define-get/put-id b get-b put-b!)
(swap a b))
]
and redirect a function call @scheme[(f x y)] to
and redirect a function call @racket[(f x y)] to
@schemeblock[
@racketblock[
(do-f (lambda () x)
(lambda () y)
(lambda (v) (set! x v))
(lambda (v) (set! y v)))
]
Clearly, then @scheme[define-cbr] is a macro-generating macro, which
binds @scheme[f] to a macro that expands to a call of @scheme[do-f].
That is, @scheme[(define-cbr (f a b) (swap ab))] needs to generate the
Clearly, then @racket[define-cbr] is a macro-generating macro, which
binds @racket[f] to a macro that expands to a call of @racket[do-f].
That is, @racket[(define-cbr (f a b) (swap ab))] needs to generate the
definition
@schemeblock[
@racketblock[
(define-syntax f
(syntax-rules ()
[(id actual ...)
@ -377,13 +377,13 @@ definition
...)]))
]
At the same time, @scheme[define-cbr] needs to define @scheme[do-f]
using the body of @scheme[f], this second part is slightly more
complex, so we defer most it to a @scheme[define-for-cbr] helper
module, which lets us write @scheme[define-cbr] easily enough:
At the same time, @racket[define-cbr] needs to define @racket[do-f]
using the body of @racket[f], this second part is slightly more
complex, so we defer most it to a @racket[define-for-cbr] helper
module, which lets us write @racket[define-cbr] easily enough:
@schemeblock[
@racketblock[
(define-syntax-rule (define-cbr (id arg ...) body)
(begin
(define-syntax id
@ -399,34 +399,34 @@ module, which lets us write @scheme[define-cbr] easily enough:
body)))
]
Our remaining task is to define @scheme[define-for-cbr] so that it
Our remaining task is to define @racket[define-for-cbr] so that it
converts
@schemeblock[
@racketblock[
(define-for-cbr do-f (a b) () (swap a b))
]
to the function definition @scheme[do-f] above. Most of the work is
generating a @scheme[define-get/put-id] declaration for each argument,
@scheme[a] ad @scheme[b], and putting them before the body. Normally,
that's an easy task for @scheme[...] in a pattern and template, but
to the function definition @racket[do-f] above. Most of the work is
generating a @racket[define-get/put-id] declaration for each argument,
@racket[a] ad @racket[b], and putting them before the body. Normally,
that's an easy task for @racket[...] in a pattern and template, but
this time there's a catch: we need to generate the names
@scheme[get-a] and @scheme[put-a!] as well as @scheme[get-b] and
@scheme[put-b!], and the pattern language provides no way to
@racket[get-a] and @racket[put-a!] as well as @racket[get-b] and
@racket[put-b!], and the pattern language provides no way to
synthesize identifiers based on existing identifiers.
As it turns out, lexical scope gives us a way around this problem. The
trick is to iterate expansions of @scheme[define-for-cbr] once for
each argument in the function, and that's why @scheme[define-cbr]
starts with an apparently useless @scheme[()] after the argument
trick is to iterate expansions of @racket[define-for-cbr] once for
each argument in the function, and that's why @racket[define-cbr]
starts with an apparently useless @racket[()] after the argument
list. We need to keep track of all the arguments seen so far and the
@scheme[get] and @scheme[put] names generated for each, in addition to
@racket[get] and @racket[put] names generated for each, in addition to
the arguments left to process. After we've processed all the
identifiers, then we have all the names we need.
Here is the definition of @scheme[define-for-cbr]:
Here is the definition of @racket[define-for-cbr]:
@schemeblock[
@racketblock[
(define-syntax define-for-cbr
(syntax-rules ()
[(define-for-cbr do-f (id0 id ...)
@ -442,7 +442,7 @@ Here is the definition of @scheme[define-for-cbr]:
Step-by-step, expansion proceeds as follows:
@schemeblock[
@racketblock[
(define-for-cbr do-f (a b)
() (swap a b))
=> (define-for-cbr do-f (b)
@ -455,11 +455,11 @@ Step-by-step, expansion proceeds as follows:
(swap a b))
]
The ``subscripts'' on @scheme[get_1], @scheme[get_2],
@scheme[put_1], and @scheme[put_2] are inserted by the macro
expander to preserve lexical scope, since the @scheme[get]
generated by each iteration of @scheme[define-for-cbr] should not
bind the @scheme[get] generated by a different iteration. In
The ``subscripts'' on @racket[get_1], @racket[get_2],
@racket[put_1], and @racket[put_2] are inserted by the macro
expander to preserve lexical scope, since the @racket[get]
generated by each iteration of @racket[define-for-cbr] should not
bind the @racket[get] generated by a different iteration. In
other words, we are essentially tricking the macro expander into
generating fresh names for us, but the technique illustrates some
of the surprising power of pattern-based macros with automatic
@ -467,17 +467,17 @@ lexical scope.
The last expression eventually expands to just
@schemeblock[
@racketblock[
(define (do-f get_1 get_2 put_1 put_2)
(let ([tmp (get_1)])
(put_1 (get_2))
(put_2 tmp)))
]
which implements the call-by-name function @scheme[f].
which implements the call-by-name function @racket[f].
To summarize, then, we can add call-by-reference functions to
Scheme with just three small pattern-based macros:
@scheme[define-cbr], @scheme[define-for-cbr], and
@scheme[define-get/put-id].
Racket with just three small pattern-based macros:
@racket[define-cbr], @racket[define-for-cbr], and
@racket[define-get/put-id].

View File

@ -1,31 +1,31 @@
#lang scribble/doc
@(require scribble/manual
"guide-utils.ss"
(for-label scheme/flonum scheme/unsafe/ops))
(for-label racket/flonum racket/unsafe/ops))
@title[#:tag "performance"]{Performance}
Alan Perlis famously quipped ``Lisp programmers know the value of
everything and the cost of nothing.'' A Scheme programmer knows, for
example, that a @scheme[lambda] anywhere in a program produces a value
everything and the cost of nothing.'' A Racket programmer knows, for
example, that a @racket[lambda] anywhere in a program produces a value
that is closed over it lexical environment---but how much does
allocating that value cost? While most programmers have a reasonable
grasp of the cost of various operations and data structures at the
machine level, the gap between the Scheme language model and the
machine level, the gap between the Racket language model and the
underlying computing machinery can be quite large.
In this chapter, we narrow the gap by explaining details of the PLT
Scheme compiler and run-time system and how they affect the run-time
and memory performance of Scheme code.
In this chapter, we narrow the gap by explaining details of the
Racket compiler and run-time system and how they affect the run-time
and memory performance of Racket code.
@; ----------------------------------------------------------------------
@section[#:tag "JIT"]{The Bytecode and Just-in-Time (JIT) Compilers}
Every definition or expression to be evaluated by Scheme is compiled
Every definition or expression to be evaluated by Racket is compiled
to an internal bytecode format. In interactive mode, this compilation
occurs automatically and on-the-fly. Tools like @exec{mzc} and
@exec{setup-plt} marshal compiled bytecode to a file, so that you do
occurs automatically and on-the-fly. Tools like @exec{raco make} and
@exec{raco setup} marshal compiled bytecode to a file, so that you do
not have to compile from source every time that you run a
program. (Most of the time required to compile a file is actually in
macro expansion; generating bytecode from fully expanded code is
@ -34,9 +34,9 @@ generating bytecode files.
The bytecode compiler applies all standard optimizations, such as
constant propagation, constant folding, inlining, and dead-code
elimination. For example, in an environment where @scheme[+] has its
usual binding, the expression @scheme[(let ([x 1][y (lambda () 4)]) (+
1 (y)))] is compiled the same as the constant @scheme[5].
elimination. For example, in an environment where @racket[+] has its
usual binding, the expression @racket[(let ([x 1][y (lambda () 4)]) (+
1 (y)))] is compiled the same as the constant @racket[5].
On some platforms, bytecode is further compiled to native code via a
@deftech{just-in-time} or @deftech{JIT} compiler. The @tech{JIT}
@ -44,13 +44,13 @@ compiler substantially speeds programs that execute tight loops,
arithmetic on small integers, and arithmetic on inexact real
numbers. Currently, @tech{JIT} compilation is supported for x86,
x86_64 (a.k.a. AMD64), and 32-bit PowerPC processors. The @tech{JIT}
compiler can be disabled via the @scheme[eval-jit-enabled] parameter
or the @DFlag{no-jit}/@Flag{j} command-line flag for @exec{mzscheme}.
compiler can be disabled via the @racket[eval-jit-enabled] parameter
or the @DFlag{no-jit}/@Flag{j} command-line flag for @exec{racket}.
The @tech{JIT} compiler works incrementally as functions are applied,
but the @tech{JIT} compiler makes only limited use of run-time
information when compiling procedures, since the code for a given
module body or @scheme[lambda] abstraction is compiled only once. The
module body or @racket[lambda] abstraction is compiled only once. The
@tech{JIT}'s granularity of compilation is a single procedure body,
not counting the bodies of any lexically nested procedures. The
overhead for @tech{JIT} compilation is normally so small that it is
@ -61,33 +61,33 @@ difficult to detect.
@section{Modules and Performance}
The module system aids optimization by helping to ensure that
identifiers have the usual bindings. That is, the @scheme[+] provided
by @schememodname[scheme/base] can be recognized by the compiler and
identifiers have the usual bindings. That is, the @racket[+] provided
by @racketmodname[racket/base] can be recognized by the compiler and
inlined, which is especially important for @tech{JIT}-compiled code.
In contrast, in a traditional interactive Scheme system, the top-level
@scheme[+] binding might be redefined, so the compiler cannot assume a
fixed @scheme[+] binding (unless special flags or declarations
In contrast, in a traditional interactive Racket system, the top-level
@racket[+] binding might be redefined, so the compiler cannot assume a
fixed @racket[+] binding (unless special flags or declarations
act as a poor-man's module system to indicate otherwise).
Even in the top-level environment, importing with @scheme[require]
enables some inlining optimizations. Although a @scheme[+] definition
at the top level might shadow an imported @scheme[+], the shadowing
Even in the top-level environment, importing with @racket[require]
enables some inlining optimizations. Although a @racket[+] definition
at the top level might shadow an imported @racket[+], the shadowing
definition applies only to expressions evaluated later.
Within a module, inlining and constant-propagation optimizations take
additional advantage of the fact that definitions within a module
cannot be mutated when no @scheme[set!] is visable at compile
cannot be mutated when no @racket[set!] is visable at compile
time. Such optimizations are unavailable in the top-level
environment. Although this optimization within modules is important
for performance, it hinders some forms of interactive development and
exploration. The @scheme[compile-enforce-module-constants] parameter
exploration. The @racket[compile-enforce-module-constants] parameter
disables the @tech{JIT} compiler's assumptions about module
definitions when interactive exploration is more important. See
@secref["module-set"] for more information.
Currently, the compiler does not attempt to inline or propagate
constants across module boundary, except for exports of the built-in
modules (such as the one that originally provides @scheme[+]).
constants across module boundaries, except for exports of the built-in
modules (such as the one that originally provides @racket[+]).
The later section @secref["letrec-performance"] provides some
additional caveats concerning inlining of module bindings.
@ -100,7 +100,7 @@ When the compiler detects a function call to an immediately visible
function, it generates more efficient code than for a generic call,
especially for tail calls. For example, given the program
@schemeblock[
@racketblock[
(letrec ([odd (lambda (x)
(if (zero? x)
#f
@ -112,23 +112,23 @@ especially for tail calls. For example, given the program
(odd 40000000))
]
the compiler can detect the @scheme[odd]--@scheme[even] loop and
the compiler can detect the @racket[odd]--@racket[even] loop and
produce code that runs much faster via loop unrolling and related
optimizations.
Within a module form, @scheme[define]d variables are lexically scoped
like @scheme[letrec] bindings, and definitions within a module
Within a module form, @racket[define]d variables are lexically scoped
like @racket[letrec] bindings, and definitions within a module
therefore permit call optimizations, so
@schemeblock[
@racketblock[
(define (odd x) ....)
(define (even x) ....)
]
within a module would perform the same as the @scheme[letrec] version.
within a module would perform the same as the @racket[letrec] version.
Primitive operations like @scheme[pair?], @scheme[car], and
@scheme[cdr] are inlined at the machine-code level by the @tech{JIT}
Primitive operations like @racket[pair?], @racket[car], and
@racket[cdr] are inlined at the machine-code level by the @tech{JIT}
compiler. See also the later section @secref["fixnums+flonums"] for
information about inlined arithmetic operations.
@ -136,11 +136,11 @@ information about inlined arithmetic operations.
@section{Mutation and Performance}
Using @scheme[set!] to mutate a variable can lead to bad
Using @racket[set!] to mutate a variable can lead to bad
performance. For example, the microbenchmark
@schememod[
scheme/base
@racketmod[
racket/base
(define (subtract-one x)
(set! x (sub1 x))
@ -155,8 +155,8 @@ scheme/base
runs much more slowly than the equivalent
@schememod[
scheme/base
@racketmod[
racket/base
(define (subtract-one x)
(sub1 x))
@ -168,16 +168,16 @@ scheme/base
(loop (subtract-one n)))))
]
In the first variant, a new location is allocated for @scheme[x] on
In the first variant, a new location is allocated for @racket[x] on
every iteration, leading to poor performance. A more clever compiler
could unravel the use of @scheme[set!] in the first example, but since
could unravel the use of @racket[set!] in the first example, but since
mutation is discouraged (see @secref["using-set!"]), the compiler's
effort is spent elsewhere.
More significantly, mutation can obscure bindings where inlining and
constant-propagation might otherwise apply. For example, in
@schemeblock[
@racketblock[
(let ([minus1 #f])
(set! minus1 sub1)
(let loop ([n 4000000])
@ -186,14 +186,14 @@ constant-propagation might otherwise apply. For example, in
(loop (minus1 n)))))
]
the @scheme[set!] obscures the fact that @scheme[minus1] is just
another name for the built-in @scheme[sub1].
the @racket[set!] obscures the fact that @racket[minus1] is just
another name for the built-in @racket[sub1].
@; ----------------------------------------------------------------------
@section[#:tag "letrec-performance"]{@scheme[letrec] Performance}
@section[#:tag "letrec-performance"]{@racket[letrec] Performance}
When @scheme[letrec] is used to bind only procedures and literals,
When @racket[letrec] is used to bind only procedures and literals,
then the compiler can treat the bindings in an optimal manner,
compiling uses of the bindings efficiently. When other kinds of
bindings are mixed with procedures, the compiler may be less able to
@ -201,7 +201,7 @@ determine the control flow.
For example,
@schemeblock[
@racketblock[
(letrec ([loop (lambda (x)
(if (zero? x)
'done
@ -213,7 +213,7 @@ For example,
likely compiles to less efficient code than
@schemeblock[
@racketblock[
(letrec ([loop (lambda (x)
(if (zero? x)
'done
@ -223,13 +223,13 @@ likely compiles to less efficient code than
]
In the first case, the compiler likely does not know that
@scheme[display] does not call @scheme[loop]. If it did, then
@scheme[loop] might refer to @scheme[next] before the binding is
@racket[display] does not call @racket[loop]. If it did, then
@racket[loop] might refer to @racket[next] before the binding is
available.
This caveat about @scheme[letrec] also applies to definitions of
This caveat about @racket[letrec] also applies to definitions of
functions and constants within modules. A definition sequence in a
module body is analogous to a sequence of @scheme[letrec] bindings,
module body is analogous to a sequence of @racket[letrec] bindings,
and non-constant expressions in a module body can interfere with the
optimization of references to later bindings.
@ -247,14 +247,14 @@ correspond to 64-bit IEEE floating-point numbers on all platforms.
Inlined fixnum and flonum arithmetic operations are among the most
important advantages of the @tech{JIT} compiler. For example, when
@scheme[+] is applied to two arguments, the generated machine code
@racket[+] is applied to two arguments, the generated machine code
tests whether the two arguments are fixnums, and if so, it uses the
machine's instruction to add the numbers (and check for overflow). If
the two numbers are not fixnums, then the next check whether whether
the two numbers are not fixnums, then it checks whether whether
both are flonums; in that case, the machine's floating-point
operations are used directly. For functions that take any number of
arguments, such as @scheme[+], inlining works for two or more
arguments (except for @scheme[-], whose one-argument case is also
arguments, such as @racket[+], inlining works for two or more
arguments (except for @racket[-], whose one-argument case is also
inlined) when the arguments are either all fixnums or all flonums.
Flonums are typically @defterm{boxed}, which means that memory is
@ -267,23 +267,23 @@ typically cheap to use.
@margin-note{See @secref["effective-futures"] for an example use of
@tech{flonum}-specific operations.}
The @schememodname[scheme/flonum] library provides flonum-specific
The @racketmodname[racket/flonum] library provides flonum-specific
operations, and combinations of flonum operations allow the @tech{JIT}
compiler to generate code that avoids boxing and unboxing intermediate
results. Besides results within immediate combinations,
flonum-specific results that are bound with @scheme[let] and consumed
flonum-specific results that are bound with @racket[let] and consumed
by a later flonum-specific operation are unboxed within temporary
storage. Finally, the compiler can detect some flonum-valued loop
accumulators and avoid boxing of the accumulator. The bytecode
decompiler (see @secref[#:doc '(lib "scribblings/mzc/mzc.scrbl")
"decompile"]) annotates combinations where the JIT can avoid boxes with
@schemeidfont{#%flonum}, @schemeidfont{#%as-flonum}, and
@schemeidfont{#%from-flonum}.
@racketidfont{#%flonum}, @racketidfont{#%as-flonum}, and
@racketidfont{#%from-flonum}.
@margin-note{Unboxing of local bindings and accumualtors is not
supported by the JIT for PowerPC.}
The @schememodname[scheme/unsafe/ops] library provides unchecked
The @racketmodname[racket/unsafe/ops] library provides unchecked
fixnum- and flonum-specific operations. Unchecked flonum-specific
operations allow unboxing, and sometimes they allow the compiler to
reorder expressions to improve performance. See also
@ -293,10 +293,10 @@ reorder expressions to improve performance. See also
@section[#:tag "unchecked-unsafe"]{Unchecked, Unsafe Operations}
The @schememodname[scheme/unsafe/ops] library provides functions that
are like other functions in @schememodname[scheme/base], but they
The @racketmodname[racket/unsafe/ops] library provides functions that
are like other functions in @racketmodname[racket/base], but they
assume (instead of checking) that provided arguments are of the right
type. For example, @scheme[unsafe-vector-ref] accesses an element from
type. For example, @racket[unsafe-vector-ref] accesses an element from
a vector without checking that its first argument is actually a vector
and without checking that the given index is in bounds. For tight
loops that use these functions, avoiding checks can sometimes speed
@ -304,20 +304,20 @@ the computation, though the benefits vary for different unchecked
functions and different contexts.
Beware that, as ``unsafe'' in the library and function names suggest,
misusing the exports of @schememodname[scheme/unsafe/ops] can lead to
misusing the exports of @racketmodname[racket/unsafe/ops] can lead to
crashes or memory corruption.
@; ----------------------------------------------------------------------
@section[#:tag "gc-perf"]{Memory Management}
PLT Scheme is available in two variants: @deftech{3m} and
The Racket implementation is available in two variants: @deftech{3m} and
@deftech{CGC}. The @tech{3m} variant uses a modern,
@deftech{generational garbage collector} that makes allocation
relatively cheap for short-lived objects. The @tech{CGC} variant uses
a @deftech{conservative garbage collector} which facilitates
interaction with C code at the expense of both precision and speed for
Scheme memory management. The 3m variant is the standard one.
Racket memory management. The 3m variant is the standard one.
Although memory allocation is reasonably cheap, avoiding allocation
altogether is normally faster. One particular place where allocation
@ -325,7 +325,7 @@ can be avoided sometimes is in @deftech{closures}, which are the
run-time representation of functions that contain free variables.
For example,
@schemeblock[
@racketblock[
(let loop ([n 40000000][prev-thunk (lambda () #f)])
(if (zero? n)
(prev-thunk)
@ -333,13 +333,13 @@ For example,
(lambda () n))))
]
allocates a closure on every iteration, since @scheme[(lambda () n)]
effectively saves @scheme[n].
allocates a closure on every iteration, since @racket[(lambda () n)]
effectively saves @racket[n].
The compiler can eliminate many closures automatically. For example,
in
@schemeblock[
@racketblock[
(let loop ([n 40000000][prev-val #f])
(let ([prev-thunk (lambda () n)])
(if (zero? n)
@ -347,10 +347,10 @@ in
(loop (sub1 n) (prev-thunk)))))
]
no closure is ever allocated for @scheme[prev-thunk], because its only
no closure is ever allocated for @racket[prev-thunk], because its only
application is visible, and so it is inlined. Similarly, in
@schemeblock[
@racketblock[
(let n-loop ([n 400000])
(if (zero? n)
'done
@ -360,9 +360,9 @@ application is visible, and so it is inlined. Similarly, in
(m-loop (sub1 m))))))
]
then the expansion of the @scheme[let] form to implement
@scheme[m-loop] involves a closure over @scheme[n], but the compiler
automatically converts the closure to pass itself @scheme[n] as an
then the expansion of the @racket[let] form to implement
@racket[m-loop] involves a closure over @racket[n], but the compiler
automatically converts the closure to pass itself @racket[n] as an
argument instead.
@; ----------------------------------------------------------------------

View File

@ -4,34 +4,34 @@
"guide-utils.ss")
@(define check-eval (make-base-eval))
@(interaction-eval #:eval check-eval (require (for-syntax scheme/base)))
@(interaction-eval #:eval check-eval (require (for-syntax racket/base)))
@(define-syntax-rule (schemeblock/eval #:eval e body ...)
@(define-syntax-rule (racketblock/eval #:eval e body ...)
(begin
(interaction-eval #:eval e body) ...
(schemeblock body ...)))
(racketblock body ...)))
@title[#:tag "proc-macros" #:style 'toc]{General Macro Transformers}
The @scheme[define-syntax] form creates a @deftech{transformer
The @racket[define-syntax] form creates a @deftech{transformer
binding} for an identifier, which is a binding that can be used at
compile time while expanding expressions to be evaluated at run time.
The compile-time value associated with a transformer binding can be
anything; if it is a procedure of one argument, then the binding is
used as a macro, and the procedure is the @deftech{macro transformer}.
The @scheme[syntax-rules] and @scheme[syntax-id-rules] forms are
The @racket[syntax-rules] and @racket[syntax-id-rules] forms are
macros that expand to procedure forms. For example, if you evaluate a
@scheme[syntax-rules] form directly (instead of placing on the
right-hand of a @scheme[define-syntax] form), the result is a
@racket[syntax-rules] form directly (instead of placing on the
right-hand of a @racket[define-syntax] form), the result is a
procedure:
@interaction[
(syntax-rules () [(nothing) something])
]
Instead of using @scheme[syntax-rules], you can write your own macro
transformer procedure directly using @scheme[lambda]. The argument to
Instead of using @racket[syntax-rules], you can write your own macro
transformer procedure directly using @racket[lambda]. The argument to
the procedure is a values that represents the source form, and the
result of the procedure must be a value that represents the
replacement form.
@ -45,37 +45,37 @@ replacement form.
The input and output of a macro transformer (i.e., source and
replacement forms) are represented as @deftech{syntax objects}. A
syntax object contains symbols, lists, and constant values (such as
numbers) that essentially correspond to the @scheme[quote]d form of
numbers) that essentially correspond to the @racket[quote]d form of
the expression. For example, a representation of the expression
@scheme[(+ 1 2)] contains the symbol @scheme['+] and the numbers
@scheme[1] and @scheme[2], all in a list. In addition to this quoted
@racket[(+ 1 2)] contains the symbol @racket['+] and the numbers
@racket[1] and @racket[2], all in a list. In addition to this quoted
content, a syntax object associates source-location and
lexical-binding information with each part of the form. The
source-location information is used when reporting syntax errors (for
example), and the lexical-biding information allows the macro system
to maintain lexical scope. To accommodate this extra information, the
represention of the expression @scheme[(+ 1 2)] is not merely
@scheme['(+ 1 2)], but a packaging of @scheme['(+ 1 2)] into a syntax
represention of the expression @racket[(+ 1 2)] is not merely
@racket['(+ 1 2)], but a packaging of @racket['(+ 1 2)] into a syntax
object.
To create a literal syntax object, use the @scheme[syntax] form:
To create a literal syntax object, use the @racket[syntax] form:
@interaction[
(eval:alts (#,(scheme syntax) (+ 1 2)) (syntax (+ 1 2)))
(eval:alts (#,(racket syntax) (+ 1 2)) (syntax (+ 1 2)))
]
In the same way that @litchar{'} abbreviates @scheme[quote],
@litchar{#'} abbreviates @scheme[syntax]:
In the same way that @litchar{'} abbreviates @racket[quote],
@litchar{#'} abbreviates @racket[syntax]:
@interaction[
#'(+ 1 2)
]
A syntax object that contains just a symbol is an @deftech{identifier
syntax object}. Scheme provides some additional operations specific to
identifier syntax objects, including the @scheme[identifier?]
syntax object}. Racket provides some additional operations specific to
identifier syntax objects, including the @racket[identifier?]
operation to detect identifiers. Most notably,
@scheme[free-identifier=?] determines whether two identifiers refer
@racket[free-identifier=?] determines whether two identifiers refer
to the same binding:
@interaction[
@ -83,7 +83,7 @@ to the same binding:
(identifier? #'(+ 1 2))
(free-identifier=? #'car #'cdr)
(free-identifier=? #'car #'car)
(require (only-in scheme/base [car also-car]))
(require (only-in racket/base [car also-car]))
(free-identifier=? #'car #'also-car)
(free-identifier=? #'car (let ([car 8])
#'car))
@ -93,13 +93,13 @@ The last example above, in particular, illustrates how syntax objects
preserve lexical-context information.
To see the lists, symbols, numbers, @|etc| within a syntax object, use
@scheme[syntax->datum]:
@racket[syntax->datum]:
@interaction[
(syntax->datum #'(+ 1 2))
]
The @scheme[syntax-e] function is similar to @scheme[syntax->datum],
The @racket[syntax-e] function is similar to @racket[syntax->datum],
but it unwraps a single layer of source-location and lexical-context
information, leaving sub-forms that have their own information wrapped
as syntax objects:
@ -108,16 +108,16 @@ as syntax objects:
(syntax-e #'(+ 1 2))
]
The @scheme[syntax-e] function always leaves syntax-object wrappers
The @racket[syntax-e] function always leaves syntax-object wrappers
around sub-forms that are represented via symbols, numbers, and other
literal values. The only time it unwraps extra sub-forms is when
unwrapping a pair, in which case the @scheme[cdr] of the pair may be
unwrapping a pair, in which case the @racket[cdr] of the pair may be
recursively unwrapped, depending on how the syntax object was
constructed.
The opposite of @scheme[syntax->datum] is, of course,
@scheme[datum->syntax]. In addition to a datum like @scheme['(+ 1
2)], @scheme[datum->syntax] needs an existing syntax object to donate
The opposite of @racket[syntax->datum] is, of course,
@racket[datum->syntax]. In addition to a datum like @racket['(+ 1
2)], @racket[datum->syntax] needs an existing syntax object to donate
its lexical context, and optionally another syntax object to donate
its source location:
@ -127,44 +127,44 @@ its source location:
#'srcloc)
]
In the above example, the lexical context of @scheme[#'lex] is used
In the above example, the lexical context of @racket[#'lex] is used
for the new syntax object, while the source location of
@scheme[#'srcloc] is used.
@racket[#'srcloc] is used.
When the second (i.e., the ``datum'') argument to
@scheme[datum->syntax] includes syntax objects, those syntax objects
@racket[datum->syntax] includes syntax objects, those syntax objects
are preserved intact in the result. That is, deconstructing the result
with @scheme[syntax-e] eventually produces the syntax objects that
were given to @scheme[datum->syntax].
with @racket[syntax-e] eventually produces the syntax objects that
were given to @racket[datum->syntax].
@; ----------------------------------------
@section[#:tag "syntax-case"]{Mixing Patterns and Expressions: @scheme[syntax-case]}
@section[#:tag "syntax-case"]{Mixing Patterns and Expressions: @racket[syntax-case]}
The procedure generated by @scheme[syntax-rules] internally uses
@scheme[syntax-e] to deconstruct the given syntax object, and it uses
@scheme[datum->syntax] to construct the result. The
@scheme[syntax-rules] form doesn't provide a way to escape from
The procedure generated by @racket[syntax-rules] internally uses
@racket[syntax-e] to deconstruct the given syntax object, and it uses
@racket[datum->syntax] to construct the result. The
@racket[syntax-rules] form doesn't provide a way to escape from
pattern-matching and template-construction mode into an arbitrary
Scheme expression.
Racket expression.
The @scheme[syntax-case] form lets you mix pattern matching, template
The @racket[syntax-case] form lets you mix pattern matching, template
construction, and arbitrary expressions:
@specform[(syntax-case stx-expr (literal-id ...)
[pattern expr]
...)]
Unlike @scheme[syntax-rules], the @scheme[syntax-case] form does not
produce a procedure. Instead, it starts with a @scheme[_stx-expr]
Unlike @racket[syntax-rules], the @racket[syntax-case] form does not
produce a procedure. Instead, it starts with a @racket[_stx-expr]
expression that determines the syntax object to match against the
@scheme[_pattern]s. Also, each @scheme[syntax-case] clause has a
@scheme[_pattern] and @scheme[_expr], instead of a @scheme[_pattern]
and @scheme[_template]. Within an @scheme[_expr], the @scheme[syntax]
@racket[_pattern]s. Also, each @racket[syntax-case] clause has a
@racket[_pattern] and @racket[_expr], instead of a @racket[_pattern]
and @racket[_template]. Within an @racket[_expr], the @racket[syntax]
form---usually abbreviated with @litchar{#'}---shifts into
template-construction mode; if the @scheme[_expr] of a clause starts
with @litchar{#'}, then we have something like a @scheme[syntax-rules]
template-construction mode; if the @racket[_expr] of a clause starts
with @litchar{#'}, then we have something like a @racket[syntax-rules]
form:
@interaction[
@ -173,10 +173,10 @@ form:
[(op n1 n2) #'(- n1 n2)]))
]
We could write the @scheme[swap] macro using @scheme[syntax-case]
instead of @scheme[define-syntax-rule] or @scheme[syntax-rules]:
We could write the @racket[swap] macro using @racket[syntax-case]
instead of @racket[define-syntax-rule] or @racket[syntax-rules]:
@schemeblock[
@racketblock[
(define-syntax swap
(lambda (stx)
(syntax-case stx ()
@ -185,15 +185,15 @@ instead of @scheme[define-syntax-rule] or @scheme[syntax-rules]:
(set! y tmp))])))
]
One advantage of using @scheme[syntax-case] is that we can provide
better error reporting for @scheme[swap]. For example, with the
@scheme[define-syntax-rule] definition of @scheme[swap], then
@scheme[(swap x 2)] produces a syntax error in terms of @scheme[set!],
because @scheme[2] is not an identifier. We can refine our
@scheme[syntax-case] implementation of @scheme[swap] to explicitly
One advantage of using @racket[syntax-case] is that we can provide
better error reporting for @racket[swap]. For example, with the
@racket[define-syntax-rule] definition of @racket[swap], then
@racket[(swap x 2)] produces a syntax error in terms of @racket[set!],
because @racket[2] is not an identifier. We can refine our
@racket[syntax-case] implementation of @racket[swap] to explicitly
check the sub-forms:
@schemeblock[
@racketblock[
(define-syntax swap
(lambda (stx)
(syntax-case stx ()
@ -211,29 +211,29 @@ check the sub-forms:
#'x)))])))
]
With this definition, @scheme[(swap x 2)] provides a syntax error
originating from @scheme[swap] instead of @scheme[set!].
With this definition, @racket[(swap x 2)] provides a syntax error
originating from @racket[swap] instead of @racket[set!].
In the above definition of @scheme[swap], @scheme[#'x] and
@scheme[#'y] are templates, even though they are not used as the
In the above definition of @racket[swap], @racket[#'x] and
@racket[#'y] are templates, even though they are not used as the
result of the macro transformer. This example illustrates how
templates can be used to access pieces of the input syntax, in this
case for checking the form of the pieces. Also, the match for
@scheme[#'x] or @scheme[#'y] is used in the call to
@scheme[raise-syntax-error], so that the syntax-error message can
@racket[#'x] or @racket[#'y] is used in the call to
@racket[raise-syntax-error], so that the syntax-error message can
point directly to the source location of the non-identifier.
@; ----------------------------------------
@section[#:tag "with-syntax"]{@scheme[with-syntax] and @scheme[generate-temporaries]}
@section[#:tag "with-syntax"]{@racket[with-syntax] and @racket[generate-temporaries]}
Since @scheme[syntax-case] lets us compute with arbitrary Scheme
Since @racket[syntax-case] lets us compute with arbitrary Racket
expression, we can more simply solve a problem that we had in
writing @scheme[define-for-cbr] (see
writing @racket[define-for-cbr] (see
@secref["pattern-macro-example"]), where we needed to generate a
set of names based on a sequence @scheme[id ...]:
set of names based on a sequence @racket[id ...]:
@schemeblock[
@racketblock[
(define-syntax (define-for-cbr stx)
(syntax-case stx ()
[(_ do-f (id ...) body)
@ -243,17 +243,17 @@ set of names based on a sequence @scheme[id ...]:
body) ....]))
]
@margin-note{This example uses @scheme[(define-syntax (_id _arg) _body ...+)],
which is equivalent to @scheme[(define-syntax _id (lambda (_arg) _body ...+))].}
@margin-note{This example uses @racket[(define-syntax (_id _arg) _body ...+)],
which is equivalent to @racket[(define-syntax _id (lambda (_arg) _body ...+))].}
In place of the @scheme[....]s above, we need to bind @scheme[get
...] and @scheme[put ...] to lists of generated identifiers. We
cannot use @scheme[let] to bind @scheme[get] and @scheme[put],
In place of the @racket[....]s above, we need to bind @racket[get
...] and @racket[put ...] to lists of generated identifiers. We
cannot use @racket[let] to bind @racket[get] and @racket[put],
because we need bindings that count as pattern variables, instead
of normal local variables. The @scheme[with-syntax] form lets us
of normal local variables. The @racket[with-syntax] form lets us
bind pattern variables:
@schemeblock[
@racketblock[
(define-syntax (define-for-cbr stx)
(syntax-case stx ()
[(_ do-f (id ...) body)
@ -264,14 +264,14 @@ bind pattern variables:
body))]))
]
Now we need an expression in place of @scheme[....] that
generates as many identifiers as there are @scheme[id] matches in
the original pattern. Since this is a common task, Scheme
provides a helper function, @scheme[generate-temporaries], that
Now we need an expression in place of @racket[....] that
generates as many identifiers as there are @racket[id] matches in
the original pattern. Since this is a common task, Racket
provides a helper function, @racket[generate-temporaries], that
takes a sequece of identifiers and returns a sequence of
generated identifiers:
@schemeblock[
@racketblock[
(define-syntax (define-for-cbr stx)
(syntax-case stx ()
[(_ do-f (id ...) body)
@ -286,9 +286,9 @@ This way of generating identifiers is normally easier to think
about than tricking the macro expander into generating names with
purely pattern-based macros.
In general, the right-hand side of a @scheme[with-syntax]
binding is a pattern, just like in @scheme[syntax-case]. In fact,
a @scheme[with-syntax] form is just a @scheme[syntax-case] form
In general, the right-hand side of a @racket[with-syntax]
binding is a pattern, just like in @racket[syntax-case]. In fact,
a @racket[with-syntax] form is just a @racket[syntax-case] form
turned partially inside-out.
@; ----------------------------------------
@ -297,13 +297,13 @@ turned partially inside-out.
As sets of macros get more complicated, you might want to write
your own helper functions, like
@scheme[generate-temporaries]. For example, to provide good
syntax-error messsage, @scheme[swap], @scheme[rotate], and
@scheme[define-cbr] all should check that certain sub-forms in
@racket[generate-temporaries]. For example, to provide good
syntax-error messsage, @racket[swap], @racket[rotate], and
@racket[define-cbr] all should check that certain sub-forms in
the source form are identifiers. We could use a
@scheme[check-ids] to perform this checking everywhere:
@racket[check-ids] to perform this checking everywhere:
@schemeblock/eval[
@racketblock/eval[
#:eval check-eval
(define-syntax (swap stx)
(syntax-case stx ()
@ -321,11 +321,11 @@ the source form are identifiers. We could use a
#'(shift-to (c ... a) (a c ...)))]))
]
The @scheme[check-ids] function can use the @scheme[syntax->list]
The @racket[check-ids] function can use the @racket[syntax->list]
function to convert a syntax-object wrapping a list into a list
of syntax objects:
@schemeblock[
@racketblock[
(define (check-ids stx forms)
(for-each
(lambda (form)
@ -337,7 +337,7 @@ of syntax objects:
(syntax->list forms)))
]
If you define @scheme[swap] and @scheme[check-ids] in this way,
If you define @racket[swap] and @racket[check-ids] in this way,
however, it doesn't work:
@interaction[
@ -345,18 +345,18 @@ however, it doesn't work:
(let ([a 1] [b 2]) (swap a b))
]
The problem is that @scheme[check-ids] is defined as a run-time
expression, but @scheme[swap] is trying to use it at compile time. In
The problem is that @racket[check-ids] is defined as a run-time
expression, but @racket[swap] is trying to use it at compile time. In
interactive mode, compile time and run time are interleaved, but they
are not interleaved within the body of a module, and they are not
interleaved or across modules that are compiled ahead-of-time. To help
make all of these modes treat code consistently, Scheme separates the
make all of these modes treat code consistently, Racket separates the
binding spaces for different phases.
To define a @scheme[check-ids] function that can be referenced at
compile time, use @scheme[define-for-syntax]:
To define a @racket[check-ids] function that can be referenced at
compile time, use @racket[define-for-syntax]:
@schemeblock/eval[
@racketblock/eval[
#:eval check-eval
(define-for-syntax (check-ids stx forms)
(for-each
@ -369,7 +369,7 @@ compile time, use @scheme[define-for-syntax]:
(syntax->list forms)))
]
With this for-syntax definition, then @scheme[swap] works:
With this for-syntax definition, then @racket[swap] works:
@interaction[
#:eval check-eval
@ -380,11 +380,11 @@ With this for-syntax definition, then @scheme[swap] works:
When organizing a program into modules, you may want to put helper
functions in one module to be used by macros that reside on other
modules. In that case, you can write the helper function using
@scheme[define]:
@racket[define]:
@schememod[#:file
@racketmod[#:file
"utils.ss"
scheme
racket
(provide check-ids)
@ -400,11 +400,11 @@ scheme
]
Then, in the module that implements macros, import the helper function
using @scheme[(require (for-syntax "utils.ss"))] instead of
@scheme[(require "utils.ss")]:
using @racket[(require (for-syntax "utils.ss"))] instead of
@racket[(require "utils.ss")]:
@schememod[
scheme
@racketmod[
racket
(require (for-syntax "utils.ss"))
@ -420,38 +420,38 @@ scheme
Since modules are separately compiled and cannot have circular
dependencies, the @filepath["utils.ss"] module's run-time body can be
compiled before the compiling the module that implements
@scheme[swap]. Thus, the run-time definitions in
@filepath["utils.ss"] can be used to implement @scheme[swap], as long
as they are explicitly shifted into compile time by @scheme[(require
@racket[swap]. Thus, the run-time definitions in
@filepath["utils.ss"] can be used to implement @racket[swap], as long
as they are explicitly shifted into compile time by @racket[(require
(for-syntax ....))].
The @schememodname[scheme] module provides @scheme[syntax-case],
@scheme[generate-temporaries], @scheme[lambda], @scheme[if], and more
The @racketmodname[racket] module provides @racket[syntax-case],
@racket[generate-temporaries], @racket[lambda], @racket[if], and more
for use in both the run-time and compile-time phases. That is why we
can use @scheme[syntax-case] in the @scheme[mzscheme] @tech{REPL} both
directly and in the right-hand side of a @scheme[define-syntax]
can use @racket[syntax-case] in the @exec{racket} @tech{REPL} both
directly and in the right-hand side of a @racket[define-syntax]
form.
The @schememodname[scheme/base] module, in contrast, exports those
The @racketmodname[racket/base] module, in contrast, exports those
bindings only in the run-time phase. If you change the module above
that defines @scheme[swap] so that it uses the
@schememodname[scheme/base] language instead of
@schememodname[scheme], then it no longer works. Adding
@scheme[(require (for-syntax scheme/base))] imports
@scheme[syntax-case] and more into the compile-time phase, so that the
that defines @racket[swap] so that it uses the
@racketmodname[racket/base] language instead of
@racketmodname[racket], then it no longer works. Adding
@racket[(require (for-syntax racket/base))] imports
@racket[syntax-case] and more into the compile-time phase, so that the
module works again.
Suppose that @scheme[define-syntax] is used to define a local macro in
the right-hand side of a @scheme[define-syntax] form. In that case,
the right-hand side of the inner @scheme[define-syntax] is in the
Suppose that @racket[define-syntax] is used to define a local macro in
the right-hand side of a @racket[define-syntax] form. In that case,
the right-hand side of the inner @racket[define-syntax] is in the
@deftech{meta-compile phase level}, also known as @deftech{phase level
2}. To import @scheme[syntax-case] into that phase level, you would
have to use @scheme[(require (for-syntax (for-syntax scheme/base)))]
or, equivalently, @scheme[(require (for-meta 2 scheme/base))].
2}. To import @racket[syntax-case] into that phase level, you would
have to use @racket[(require (for-syntax (for-syntax racket/base)))]
or, equivalently, @racket[(require (for-meta 2 racket/base))].
Negative phase levels also exist. If a macro uses a helper function
that is imported @scheme[for-syntax], and if the helper function
returns syntax-object constants generated by @scheme[syntax], then
that is imported @racket[for-syntax], and if the helper function
returns syntax-object constants generated by @racket[syntax], then
identifiers in the syntax will need bindings at @deftech{phase level
-1}, also known as the @deftech{template phase level}, to have any
binding at the run-time phase level relative to the module that

View File

@ -12,7 +12,7 @@ A @deftech{regexp} value encapsulates a pattern that is described by a
string or @tech{byte string}. The regexp matcher tries to match this
pattern against (a portion of) another string or byte string, which we
will call the @deftech{text string}, when you call functions like
@scheme[regexp-match]. The text string is treated as raw text, and
@racket[regexp-match]. The text string is treated as raw text, and
not as a pattern.
@local-table-of-contents[]
@ -25,30 +25,30 @@ not as a pattern.
A string or @tech{byte string} can be used directly as a @tech{regexp}
pattern, or it can be prefixed with @litchar{#rx} to form a literal
@tech{regexp} value. For example, @scheme[#rx"abc"] is a string-based
@tech{regexp} value, and @scheme[#rx#"abc"] is a @tech{byte
@tech{regexp} value. For example, @racket[#rx"abc"] is a string-based
@tech{regexp} value, and @racket[#rx#"abc"] is a @tech{byte
string}-based @tech{regexp} value. Alternately, a string or byte
string can be prefixed with @litchar{#px}, as in @scheme[#px"abc"],
string can be prefixed with @litchar{#px}, as in @racket[#px"abc"],
for a slightly extended syntax of patterns within the string.
Most of the characters in a @tech{regexp} pattern are meant to match
occurrences of themselves in the @tech{text string}. Thus, the pattern
@scheme[#rx"abc"] matches a string that contains the characters
@racket[#rx"abc"] matches a string that contains the characters
@litchar{a}, @litchar{b}, and @litchar{c} in succession. Other
characters act as @deftech{metacharacters}, and some character
sequences act as @deftech{metasequences}. That is, they specify
something other than their literal selves. For example, in the
pattern @scheme[#rx"a.c"], the characters @litchar{a} and @litchar{c}
pattern @racket[#rx"a.c"], the characters @litchar{a} and @litchar{c}
stand for themselves, but the @tech{metacharacter} @litchar{.} can
match @emph{any} character. Therefore, the pattern @scheme[#rx"a.c"]
match @emph{any} character. Therefore, the pattern @racket[#rx"a.c"]
matches an @litchar{a}, any character, and @litchar{c} in succession.
@margin-note{When we want a literal @litchar{\} inside a Scheme string
@margin-note{When we want a literal @litchar{\} inside a Racket string
or regexp literal, we must escape it so that it shows up in the string
at all. Scheme strings use @litchar{\} as the escape character, so we
end up with two @litchar{\}s: one Scheme-string @litchar{\} to escape
at all. Racket strings use @litchar{\} as the escape character, so we
end up with two @litchar{\}s: one Racket-string @litchar{\} to escape
the regexp @litchar{\}, which then escapes the @litchar{.}. Another
character that would need escaping inside a Scheme string is
character that would need escaping inside a Racket string is
@litchar{"}.}
If we needed to match the character @litchar{.} itself, we can escape
@ -56,19 +56,19 @@ it by precede it with a @litchar{\}. The character sequence
@litchar{\.} is thus a @tech{metasequence}, since it doesn't match
itself but rather just @litchar{.}. So, to match @litchar{a},
@litchar{.}, and @litchar{c} in succession, we use the regexp pattern
@scheme[#rx"a\\.c"]; the double @litchar{\} is an artifact of Scheme
@racket[#rx"a\\.c"]; the double @litchar{\} is an artifact of Racket
strings, not the @tech{regexp} pattern itself.
The @scheme[regexp] function takes a string or byte string and
produces a @tech{regexp} value. Use @scheme[regexp] when you construct
The @racket[regexp] function takes a string or byte string and
produces a @tech{regexp} value. Use @racket[regexp] when you construct
a pattern to be matched against multiple strings, since a pattern is
compiled to a @tech{regexp} value before it can be used in a match.
The @scheme[pregexp] function is like @scheme[regexp], but using the
The @racket[pregexp] function is like @racket[regexp], but using the
extended syntax. Regexp values as literals with @litchar{#rx} or
@litchar{#px} are compiled once and for all when they are read.
The @scheme[regexp-quote] function takes an arbitrary string and
The @racket[regexp-quote] function takes an arbitrary string and
returns a string for a pattern that matches exactly the original
string. In particular, characters in the input string that could serve
as regexp metacharacters are escaped with a backslash, so that they
@ -79,7 +79,7 @@ safely match only themselves.
(regexp-quote "list?")
]
The @scheme[regexp-quote] function is useful when building a composite
The @racket[regexp-quote] function is useful when building a composite
@tech{regexp} from a mix of @tech{regexp} strings and verbatim strings.
@ -87,9 +87,9 @@ The @scheme[regexp-quote] function is useful when building a composite
@section[#:tag "regexp-match"]{Matching Regexp Patterns}
The @scheme[regexp-match-positions] function takes a @tech{regexp}
The @racket[regexp-match-positions] function takes a @tech{regexp}
pattern and a @tech{text string}, and it returns a match if the regexp
matches (some part of) the @tech{text string}, or @scheme[#f] if the regexp
matches (some part of) the @tech{text string}, or @racket[#f] if the regexp
did not match the string. A successful match produces a list of
@deftech{index pairs}.
@ -98,22 +98,22 @@ did not match the string. A successful match produces a list of
(regexp-match-positions #rx"needle" "hay needle stack")
]
In the second example, the integers @scheme[4] and @scheme[10]
identify the substring that was matched. The @scheme[4] is the
starting (inclusive) index, and @scheme[10] the ending (exclusive)
In the second example, the integers @racket[4] and @racket[10]
identify the substring that was matched. The @racket[4] is the
starting (inclusive) index, and @racket[10] the ending (exclusive)
index of the matching substring:
@interaction[
(substring "hay needle stack" 4 10)
]
In this first example, @scheme[regexp-match-positions]'s return list
In this first example, @racket[regexp-match-positions]'s return list
contains only one index pair, and that pair represents the entire
substring matched by the regexp. When we discuss @tech{subpatterns}
later, we will see how a single match operation can yield a list of
@tech{submatch}es.
The @scheme[regexp-match-positions] function takes optional third and
The @racket[regexp-match-positions] function takes optional third and
fourth arguments that specify the indices of the @tech{text string} within
which the matching should take place.
@ -127,8 +127,8 @@ which the matching should take place.
Note that the returned indices are still reckoned relative to the full
@tech{text string}.
The @scheme[regexp-match] function is like
@scheme[regexp-match-positions], but instead of returning index pairs,
The @racket[regexp-match] function is like
@racket[regexp-match-positions], but instead of returning index pairs,
it returns the matching substrings:
@interaction[
@ -136,7 +136,7 @@ it returns the matching substrings:
(regexp-match #rx"needle" "hay needle stack")
]
When @scheme[regexp-match] is used with byte-string regexp, the result
When @racket[regexp-match] is used with byte-string regexp, the result
is a matching byte substring:
@interaction[
@ -153,7 +153,7 @@ is a matching byte substring:
avoids UTF-8 encodings.}
If you have data that is in a port, there's no need to first read it
into a string. Functions like @scheme[regexp-match] can match on the
into a string. Functions like @racket[regexp-match] can match on the
port directly:
@interaction[
@ -163,8 +163,8 @@ port directly:
(regexp-match #rx#"needle" i)
]
The @scheme[regexp-match?] function is like
@scheme[regexp-match-positions], but simply returns a boolean
The @racket[regexp-match?] function is like
@racket[regexp-match-positions], but simply returns a boolean
indicating whether the match succeeded:
@interaction[
@ -172,7 +172,7 @@ indicating whether the match succeeded:
(regexp-match? #rx"needle" "hay needle stack")
]
The @scheme[regexp-split] function takes two arguments, a
The @racket[regexp-split] function takes two arguments, a
@tech{regexp} pattern and a text string, and it returns a list of
substrings of the text string; the pattern identifies the delimiter
separating the substrings.
@ -190,32 +190,32 @@ single-character substrings is returned.
]
Thus, to identify one-or-more spaces as the delimiter, take care to
use the regexp @scheme[#rx"\u20+"], not @scheme[#rx"\u20*"].
use the regexp @racket[#rx"\u20+"], not @racket[#rx"\u20*"].
@interaction[
(regexp-split #rx" +" "split pea soup")
(regexp-split #rx" *" "split pea soup")
]
The @scheme[regexp-replace] function replaces the matched portion of
The @racket[regexp-replace] function replaces the matched portion of
the text string by another string. The first argument is the pattern,
the second the text string, and the third is either the string to be
inserted or a procedure to convert matches to the insert string.
@interaction[
(regexp-replace #rx"te" "liberte" "ty")
(regexp-replace #rx"." "scheme" string-upcase)
(regexp-replace #rx"." "racket" string-upcase)
]
If the pattern doesn't occur in the text string, the returned string
is identical to the text string.
The @scheme[regexp-replace*] function replaces @emph{all} matches in
The @racket[regexp-replace*] function replaces @emph{all} matches in
the text string by the insert string:
@interaction[
(regexp-replace* #rx"te" "liberte egalite fraternite" "ty")
(regexp-replace* #rx"[ds]" "drscheme" string-upcase)
(regexp-replace* #rx"[ds]" "drracket" string-upcase)
]
@; ----------------------------------------
@ -285,20 +285,20 @@ A @deftech{character class} matches any one character from a set of
characters. A typical format for this is the @deftech{bracketed
character class} @litchar{[}...@litchar{]}, which matches any one
character from the non-empty sequence of characters enclosed within
the brackets. Thus, @scheme[#rx"p[aeiou]t"] matches @litchar{pat},
the brackets. Thus, @racket[#rx"p[aeiou]t"] matches @litchar{pat},
@litchar{pet}, @litchar{pit}, @litchar{pot}, @litchar{put}, and
nothing else.
Inside the brackets, a @litchar{-} between two characters specifies
the Unicode range between the characters. For example,
@scheme[#rx"ta[b-dgn-p]"] matches @litchar{tab}, @litchar{tac},
@racket[#rx"ta[b-dgn-p]"] matches @litchar{tab}, @litchar{tac},
@litchar{tad}, @litchar{tag}, @litchar{tan}, @litchar{tao}, and
@litchar{tap}.
An initial @litchar{^} after the left bracket inverts the set
specified by the rest of the contents; i.e., it specifies the set of
characters @emph{other than} those identified in the brackets. For
example, @scheme[#rx"do[^g]"] matches all three-character sequences
example, @racket[#rx"do[^g]"] matches all three-character sequences
starting with @litchar{do} except @litchar{dog}.
Note that the @tech{metacharacter} @litchar{^} inside brackets means
@ -314,12 +314,12 @@ Bracketed character classes cannot contain other bracketed character
classes (although they contain certain other types of character
classes; see below). Thus, a @litchar{[} inside a bracketed character
class doesn't have to be a metacharacter; it can stand for itself.
For example, @scheme[#rx"[a[b]"] matches @litchar{a}, @litchar{[}, and
For example, @racket[#rx"[a[b]"] matches @litchar{a}, @litchar{[}, and
@litchar{b}.
Furthermore, since empty bracketed character classes are disallowed, a
@litchar{]} immediately occurring after the opening left bracket also
doesn't need to be a metacharacter. For example, @scheme[#rx"[]ab]"]
doesn't need to be a metacharacter. For example, @racket[#rx"[]ab]"]
matches @litchar{]}, @litchar{a}, and @litchar{b}.
@subsection{Some Frequently Used Character Classes}
@ -333,7 +333,7 @@ bracketed expressions: @litchar{\d} matches a digit
@margin-note{Following regexp custom, we identify ``word'' characters
as @litchar{[A-Za-z0-9_]}, although these are too restrictive for what
a Schemer might consider a ``word.''}
a Racketr might consider a ``word.''}
The upper-case versions of these metasequences stand for the
inversions of the corresponding character classes: @litchar{\D}
@ -341,7 +341,7 @@ matches a non-digit, @litchar{\S} a non-whitespace character, and
@litchar{\W} a non-``word'' character.
Remember to include a double backslash when putting these
metasequences in a Scheme string:
metasequences in a Racket string:
@interaction[
(regexp-match #px"\\d\\d"
@ -349,7 +349,7 @@ metasequences in a Scheme string:
]
These character classes can be used inside a bracketed expression. For
example, @scheme[#px"[a-z\\d]"] matches a lower-case letter or a
example, @racket[#px"[a-z\\d]"] matches a lower-case letter or a
digit.
@subsection{POSIX character classes}
@ -389,7 +389,7 @@ supported are
]
For example, the @scheme[#px"[[:alpha:]_]"] matches a letter or
For example, the @racket[#px"[[:alpha:]_]"] matches a letter or
underscore.
@interaction[
@ -516,7 +516,7 @@ it is the last submatch that is returned.
It is also possible for a quantified subpattern to fail to match, even
if the overall pattern matches. In such cases, the failing submatch
is represented by @scheme[#f]
is represented by @racket[#f]
@interaction[
(define date-re
@ -531,7 +531,7 @@ is represented by @scheme[#f]
@subsection{Backreferences}
@tech{Submatch}es can be used in the insert string argument of the
procedures @scheme[regexp-replace] and @scheme[regexp-replace*]. The
procedures @racket[regexp-replace] and @racket[regexp-replace*]. The
insert string can use @litchar{\}@math{n} as a @deftech{backreference}
to refer back to the @math{n}th submatch, which is the substring
that matched the @math{n}th subpattern. A @litchar{\0} refers to the
@ -612,11 +612,11 @@ In the following example, a non-capturing cluster eliminates the
cluster identifies the basename.
@margin-note{But don't parse paths with regexps. Use functions like
@scheme[split-path], instead.}
@racket[split-path], instead.}
@interaction[
(regexp-match #rx"^(?:[a-z]*/)*([a-z]+)$"
"/usr/local/bin/mzscheme")
"/usr/local/bin/racket")
]
@subsection[#:tag "regexp-cloister"]{Cloisters}
@ -734,7 +734,7 @@ Consider
The regexp consists of two subregexps: @litchar{a*} followed by
@litchar{a}. The subregexp @litchar{a*} cannot be allowed to match
all four @litchar{a}'s in the text string @scheme[aaaa], even though
all four @litchar{a}'s in the text string @racket[aaaa], even though
@litchar{*} is a greedy quantifier. It may match only the first
three, leaving the last one for the second subregexp. This ensures
that the full regexp matches successfully.
@ -800,7 +800,7 @@ its subpattern @emph{could} match.
"i left my grey socks at the greyhound")
]
The regexp @scheme[#rx"grey(?=hound)"] matches @litchar{grey}, but
The regexp @racket[#rx"grey(?=hound)"] matches @litchar{grey}, but
@emph{only} if it is followed by @litchar{hound}. Thus, the first
@litchar{grey} in the text string is not matched.
@ -812,7 +812,7 @@ subpattern @emph{could not} possibly match.
"the gray greyhound ate the grey socks")
]
The regexp @scheme[#rx"grey(?!hound)"] matches @litchar{grey}, but
The regexp @racket[#rx"grey(?!hound)"] matches @litchar{grey}, but
only if it is @emph{not} followed by @litchar{hound}. Thus the
@litchar{grey} just before @litchar{socks} is matched.
@ -827,7 +827,7 @@ the text string.
"the hound in the picture is not a greyhound")
]
The regexp @scheme[#rx"(?<=grey)hound"] matches @litchar{hound}, but
The regexp @racket[#rx"(?<=grey)hound"] matches @litchar{hound}, but
only if it is preceded by @litchar{grey}.
Negative lookbehind with @litchar{?<!} checks that its subpattern
@ -838,7 +838,7 @@ could not possibly match immediately to the left.
"the greyhound in the picture is not a hound")
]
The regexp @scheme[#rx"(?<!grey)hound"] matches @litchar{hound}, but
The regexp @racket[#rx"(?<!grey)hound"] matches @litchar{hound}, but
only if it is @emph{not} preceded by @litchar{grey}.
Lookaheads and lookbehinds can be convenient when they
@ -856,7 +856,7 @@ this chapter. The problem is to fashion a regexp that will match any
and only IP addresses or @emph{dotted quads}: four numbers separated
by three dots, with each number between 0 and 255.
First, we define a subregexp @scheme[n0-255] that matches 0 through
First, we define a subregexp @racket[n0-255] that matches 0 through
255:
@interaction[
@ -872,7 +872,7 @@ First, we define a subregexp @scheme[n0-255] that matches 0 through
")"))
]
@margin-note{Note that @scheme[n0-255] lists prefixes as preferred
@margin-note{Note that @racket[n0-255] lists prefixes as preferred
alternates, which is something we cautioned against in
@secref["regexp-alternation"]. However, since we intend to anchor
this subregexp explicitly to force an overall match, the order of the
@ -886,7 +886,7 @@ must be excluded. So we fashion alternates to get 000
through 199, then 200 through 249, and finally 250
through 255.
An IP-address is a string that consists of four @scheme[n0-255]s with
An IP-address is a string that consists of four @racket[n0-255]s with
three dots separating them.
@interaction[
@ -894,10 +894,10 @@ three dots separating them.
(define ip-re1
(string-append
"^" (code:comment @#,t{nothing before})
n0-255 (code:comment @#,t{the first @scheme[n0-255],})
n0-255 (code:comment @#,t{the first @racket[n0-255],})
"(?:" (code:comment @#,t{then the subpattern of})
"\\." (code:comment @#,t{a dot followed by})
n0-255 (code:comment @#,t{an @scheme[n0-255],})
n0-255 (code:comment @#,t{an @racket[n0-255],})
")" (code:comment @#,t{which is})
"{3}" (code:comment @#,t{repeated exactly 3 times})
"$" (code:comment @#,t{with nothing following})
@ -920,7 +920,7 @@ which is fine, except that we also have
]
All-zero sequences are not valid IP addresses! Lookahead to the
rescue. Before starting to match @scheme[ip-re1], we look ahead to
rescue. Before starting to match @racket[ip-re1], we look ahead to
ensure we don't have all zeros. We could use positive lookahead to
ensure there @emph{is} a digit other than zero.
@ -946,7 +946,7 @@ composed of @emph{only} zeros and dots.
ip-re1)))
]
The regexp @scheme[ip-re] will match all and only valid IP addresses.
The regexp @racket[ip-re] will match all and only valid IP addresses.
@interaction[
#:eval ex-eval

View File

@ -1,142 +1,141 @@
#lang scribble/doc
@(require scribble/manual
"guide-utils.ss"
(for-syntax scheme/pretty))
(for-syntax racket/pretty))
@title[#:tag "running" #:style 'toc]{Running and Creating Executables}
While developing programs, many PLT Scheme programmers use the
While developing programs, many Racket programmers use the
@seclink[#:doc '(lib "scribblings/drscheme/drscheme.scrbl")
"top"]{DrScheme} programming environment. To run a program without the
development environment, use @exec{mzscheme} (for console-based
programs) or @exec{mred} (for GUI program). This chapter mainly
explains how to run @exec{mzscheme} and @exec{mred}.
"top"]{DrRacket} programming environment. To run a program without the
development environment, use @exec{racket} (for console-based
programs) or @exec{gracket} (for GUI programs). This chapter mainly
explains how to run @exec{racket} and @exec{gracket}.
@local-table-of-contents[]
@; ----------------------------------------------------------------------
@section[#:tag "mzscheme"]{Running @exec{mzscheme} and @exec{mred}}
@section[#:tag "racket"]{Running @exec{racket} and @exec{gracket}}
Depending on command-line arguments, @exec{mzscheme} or @exec{mred}
Depending on command-line arguments, @exec{racket} or @exec{gracket}
runs in @seclink["start-interactive-mode"]{interactive mode},
@seclink["start-module-mode"]{module mode}, or
@seclink["start-load-mode"]{load mode}.
@subsection[#:tag "start-interactive-mode"]{Interactive Mode}
When @exec{mzscheme} is run with no command-line arguments (other than
When @exec{racket} is run with no command-line arguments (other than
confguration options, like @Flag{j}), then it starts a @tech{REPL}
with a @litchar{> } prompt:
@verbatim[#:indent 2]{
Welcome to MzScheme
Welcome to Racket
>
}
@margin-note{For information on GNU Readline support, see
@schememodname[readline].}
@racketmodname[readline].}
To initialize the @tech{REPL}'s environment, @exec{mzscheme} first
requires the @schememodname[scheme/init] module, which provides all of
@scheme[scheme], and also installs @scheme[pretty-print] for display
results. Finally, @exec{mzscheme} loads the file reported by
@scheme[(find-system-path 'init-file)], if it exists, before starting
To initialize the @tech{REPL}'s environment, @exec{racket} first
requires the @racketmodname[racket/init] module, which provides all of
@racket[racket], and also installs @racket[pretty-print] for display
results. Finally, @exec{racket} loads the file reported by
@racket[(find-system-path 'init-file)], if it exists, before starting
the @tech{REPL}.
If any command-line arguments are provided (other than configuration
options), add @Flag{i} or @DFlag{repl} to re-enable the
@tech{REPL}. For example,
@commandline{mzscheme -e '(display "hi\n")' -i}
@commandline{racket -e '(display "hi\n")' -i}
displays ``hi'' on start-up, but still presents a @tech{REPL}.
If module-requiring flags appear before @Flag{i}/@DFlag{repl}, they
cancel the automatic requiring of @schememodname[scheme/init]. This
cancel the automatic requiring of @racketmodname[racket/init]. This
behavior can be used to initialize the @tech{REPL}'s environment with
a different language. For example,
@commandline{mzscheme -l scheme/base -i}
@commandline{racket -l racket/base -i}
starts a @tech{REPL} using a much smaller initial language (that loads
much faster). Beware that most modules do not provide the basic syntax
of Scheme, including function-call syntax and @scheme[require]. For
of Racket, including function-call syntax and @racket[require]. For
example,
@commandline{mzscheme -l scheme/date -i}
@commandline{racket -l racket/date -i}
produces a @tech{REPL} that fails for every expression, because
@schememodname[scheme/date] provides only a few functions, and not the
@scheme[#%top-interaction] and @scheme[#%app] bindings that are needed
@racketmodname[racket/date] provides only a few functions, and not the
@racket[#%top-interaction] and @racket[#%app] bindings that are needed
to evaluate top-level function calls in the @tech{REPL}.
If a module-requiring flag appears after @Flag{i}/@DFlag{repl} instead
of before it, then the module is required after
@schememodname[scheme/init] to augment the initial environment. For
@racketmodname[racket/init] to augment the initial environment. For
example,
@commandline{mzscheme -i -l scheme/date}
@commandline{racket -i -l racket/date}
starts a useful @tech{REPL} with @schememodname[scheme/date] available
in addition to the exports of @schememodname[scheme].
starts a useful @tech{REPL} with @racketmodname[racket/date] available
in addition to the exports of @racketmodname[racket].
@; ----------------------------------------
@subsection[#:tag "start-module-mode"]{Module Mode}
If a file argument is supplied to @exec{mzscheme} before any
If a file argument is supplied to @exec{racket} before any
command-line switch (other than configuration options), then the file
is required as a module, and (unless @Flag{i}/@DFlag{repl} is
specified), no @tech{REPL} is started. For example,
@commandline{mzscheme hello.ss}
@commandline{racket hello.rkt}
requires the @filepath{hello.ss} module and then exits. Any argument
requires the @filepath{hello.rkt} module and then exits. Any argument
after the file name, flag or otherwise, is preserved as a command-line
argument for use by the required module via
@scheme[current-command-line-arguments].
@racket[current-command-line-arguments].
If command-line flags are used, then the @Flag{u} or
@DFlag{require-script} flag can be used to explicitly require a file
as a module. The @Flag{t} or @DFlag{require} flag is similar, except
that additional command-line flags are processed by @exec{mzscheme},
that additional command-line flags are processed by @exec{racket},
instead of preserved for the required module. For example,
@commandline{mzscheme -t hello.ss -t goodbye.ss}
@commandline{racket -t hello.rkt -t goodbye.rkt}
requires the @filepath{hello.ss} module, then requires the
@filepath{goodbye.ss} module, and then exits.
requires the @filepath{hello.rkt} module, then requires the
@filepath{goodbye.rkt} module, and then exits.
The @Flag{l} or @DFlag{lib} flag is similar to
@Flag{t}/@DFlag{require}, but it requires a module using a
@scheme[lib] module path instead of a file path. For example,
@racket[lib] module path instead of a file path. For example,
@commandline{mzscheme -l compiler}
@commandline{racket -l raco}
is the same as running the @exec{mzc} executable with no arguments,
since the @scheme[compiler] module is the main @exec{mzc}
module.
is the same as running the @exec{raco} executable with no arguments,
since the @racket[raco] module is the executable's main module.
Note that if you wanted to pass command-line flags to
@scheme[compiler] above, you would need to protect the flags with a
@Flag{-}, so that @exec{mzscheme} doesn't try to parse them itself:
@racket[raco] above, you would need to protect the flags with a
@Flag{-}, so that @exec{racket} doesn't try to parse them itself:
@commandline{mzscheme -l compiler -- --make prog.ss}
@commandline{racket -l raco -- --help}
@; ----------------------------------------
@subsection[#:tag "start-load-mode"]{Load Mode}
The @Flag{f} or @DFlag{load} flag supports @scheme[load]ing top-level
The @Flag{f} or @DFlag{load} flag supports @racket[load]ing top-level
expressions in a file directly, as opposed to expressions within a
module file. This evaluation is like starting a @tech{REPL} and typing
the expressions directly, except that the results are not printed.
For example,
@commandline{mzscheme -f hi.ss}
@commandline{racket -f hi.rkts}
@scheme[load]s @filepath{hi.ss} and exits. Note that load mode is
@racket[load]s @filepath{hi.rkts} and exits. Note that load mode is
generally a bad idea, for the reasons explained in
@secref["use-module"]; using module mode is typically better.
@ -144,21 +143,21 @@ The @Flag{e} or @DFlag{eval} flag accepts an expression to evaluate
directly. Unlike file loading, the result of the expression is
printed, as in a @tech{REPL}. For example,
@commandline{mzscheme -e '(current-seconds)'}
@commandline{racket -e '(current-seconds)'}
prints the number of seconds since January 1, 1970.
For file loading and expression evaluation, the top-level environment
is created in the same way for
@seclink["start-interactive-mode"]{interactive mode}:
@schememodname[scheme/init] is required unless another module is
@racketmodname[racket/init] is required unless another module is
specified first. For example,
@commandline{mzscheme -l scheme/base -e '(current-seconds)'}
@commandline{racket -l racket/base -e '(current-seconds)'}
likely runs faster, because it initializes the environment for
evaluation using the smaller @schememodname[scheme/base] language,
instead of @schememodname[scheme/init].
evaluation using the smaller @racketmodname[racket/base] language,
instead of @racketmodname[racket/init].
@; ----------------------------------------------------------------------

View File

@ -5,13 +5,13 @@
@title[#:tag "scripts"]{Scripts}
Scheme files can be turned into executable scripts under Unix and Mac
Racket files can be turned into executable scripts under Unix and Mac
OS X. Under Windows, a compatibility layer like Cygwin support the
same kind of scripts, or scripts can be implemented as batch files.
@section{Unix Scripts}
In a Unix environment (including Linux and Mac OS X), a Scheme file can
In a Unix environment (including Linux and Mac OS X), a Racket file can
be turned into an executable script using the shell's @as-index{@tt{#!}}
convention. The first two characters of the file must be @litchar{#!};
the next character must be either a space or @litchar{/}, and the
@ -19,14 +19,14 @@ remainder of the first line must be a command to execute the script. For
some platforms, the total length of the first line is restricted to 32
characters, and sometimes the space is required.
The simplest script format uses an absolute path to a @exec{mzscheme}
The simplest script format uses an absolute path to a @exec{racket}
executable followed by a module declaration. For example, if
@exec{mzscheme} is installed in @filepath{/usr/local/bin}, then a file
@exec{racket} is installed in @filepath{/usr/local/bin}, then a file
containing the following text acts as a ``hello world'' script:
@verbatim[#:indent 2]{
#! /usr/local/bin/mzscheme
#lang scheme/base
#! /usr/local/bin/racket
#lang racket/base
"Hello, world!"
}
@ -37,43 +37,43 @@ typing @exec{./hello} at the shell prompt produces the output
The above script works because the operating system automatically puts
the path to the script as the argument to the program started by the
@tt{#!} line, and because @exec{mzscheme} treats a single non-flag
@tt{#!} line, and because @exec{racket} treats a single non-flag
argument as a file containing a module to run.
Instead of specifying a complete path to the @exec{mzscheme}
executable, a popular alternative is to require that @exec{mzscheme}
Instead of specifying a complete path to the @exec{racket}
executable, a popular alternative is to require that @exec{racket}
is in the user's command path, and then ``trampoline'' using
@exec{/usr/bin/env}:
@verbatim[#:indent 2]{
#! /usr/bin/env mzscheme
#lang scheme/base
#! /usr/bin/env racket
#lang racket/base
"Hello, world!"
}
In either case, command-line arguments to a script are available via
@scheme[current-command-line-arguments]:
@racket[current-command-line-arguments]:
@verbatim[#:indent 2]{
#! /usr/bin/env mzscheme
#lang scheme/base
#! /usr/bin/env racket
#lang racket/base
(printf "Given arguments: ~s\n"
(current-command-line-arguments))
}
If the name of the script is needed, it is available via
@scheme[(find-system-path 'run-file)], instead of via
@scheme[(current-command-line-arguments)].
@racket[(find-system-path 'run-file)], instead of via
@racket[(current-command-line-arguments)].
Usually, then best way to handle command-line arguments is to parse
them using the @scheme[command-line] form provided by
@schememodname[scheme]. The @scheme[command-line] form extracts
command-line arguments from @scheme[(current-command-line-arguments)]
them using the @racket[command-line] form provided by
@racketmodname[racket]. The @racket[command-line] form extracts
command-line arguments from @racket[(current-command-line-arguments)]
by default:
@verbatim[#:indent 2]{
#! /usr/bin/env mzscheme
#lang scheme
#! /usr/bin/env racket
#lang racket
(define verbose? (make-parameter #f))
@ -95,47 +95,47 @@ command-line arguments are allowed by the script.
An even more general trampoline uses @exec{/bin/sh} plus some lines
that are comments in one language and expressions in the other. This
trampoline is more complicated, but it provides more control over
command-line arguments to @exec{mzscheme}:
command-line arguments to @exec{racket}:
@verbatim[#:indent 2]|{
#! /bin/sh
#|
exec mzscheme -cu "$0" ${1+"$@"}
exec racket -cu "$0" ${1+"$@"}
|#
#lang scheme/base
#lang racket/base
(printf "This script started slowly, because the use of\n")
(printf "bytecode files has been disabled via -c.\n")
(printf "Given arguments: ~s\n"
(current-command-line-arguments))
}|
Note that @litchar{#!} starts a line comment in Scheme, and
Note that @litchar{#!} starts a line comment in Racket, and
@litchar{#|}...@litchar{|#} forms a block comment. Meanwhile,
@litchar{#} also starts a shell-script comment, while @exec{exec
mzscheme} aborts the shell script to start @exec{mzscheme}. That way,
racket} aborts the shell script to start @exec{racket}. That way,
the script file turns out to be valid input to both @exec{/bin/sh} and
@exec{mzscheme}.
@exec{racket}.
@section{Windows Batch Files}
A similar trick can be used to write Scheme code in Windows
A similar trick can be used to write Racket code in Windows
@as-index{@tt{.bat}} batch files:
@verbatim[#:indent 2]|{
; @echo off
; MzScheme.exe "%~f0" %*
; Racket.exe "%~f0" %*
; exit /b
#lang scheme/base
#lang racket/base
"Hello, world!"
}|
@;{
Original trick from Ben Goetter, who used:
; @echo off && REM -*- scheme -*-
; "%MZSCHEME%" "%~f0" %*
; @echo off && REM -*- racket -*-
; "%RACKET%" "%~f0" %*
; exit /b
#lang scheme
#lang racket
...
it might be worth documenting the Emacs "-*-" convention and a way to

View File

@ -33,8 +33,8 @@ The following kinds of values are serializable:
@itemize[
@item{structures created through @scheme[define-serializable-struct] or
@scheme[define-serializable-struct/version], or more generally
@item{structures created through @scheme[serializable-struct] or
@scheme[serializable-struct/versions], or more generally
structures with the @scheme[prop:serializable] property (see
@scheme[prop:serializable] for more information);}
@ -338,10 +338,10 @@ exception to disallow the @scheme[dynamic-require].}
@; ----------------------------------------------------------------------
@defform[(define-serializable-struct id-maybe-super (field ...)
@defform[(serializable-struct id maybe-super (field ...)
struct-option ...)]{
Like @scheme[define-struct], but instances of the structure type are
Like @scheme[struct], but instances of the structure type are
serializable with @scheme[serialize]. This form is allowed only at
the top level or in a module's top level (so that deserialization
information can be found later).
@ -350,17 +350,16 @@ Serialization only supports cycles involving the created structure
type when all fields are mutable (or when the cycle can be broken
through some other mutable value).
In addition to the bindings generated by @scheme[define-struct],
@scheme[define-serializable-struct] binds
In addition to the bindings generated by @scheme[struct],
@scheme[serializable-struct] binds
@schemeidfont{deserialize-info:}@scheme[_id]@schemeidfont{-v0} to
deserialization information. Furthermore, in a module context, it
automatically @scheme[provide]s this binding.
The @scheme[define-serializable-struct] form enables the construction
of structure instances from places where
@schemeidfont{make}@scheme[id] is not accessible, since
deserialization must construct instances. Furthermore,
@scheme[define-serializable-struct] provides limited access to field
The @scheme[serializable-struct] form enables the construction of
structure instances from places where @scheme[id] is not accessible,
since deserialization must construct instances. Furthermore,
@scheme[serializable-struct] provides limited access to field
mutation, but only for instances generated through the deserialization
information bound to
@schemeidfont{deserialize-info:}@scheme[_id]@schemeidfont{-v0}. See
@ -368,9 +367,9 @@ information bound to
The @scheme[-v0] suffix on the deserialization enables future
versioning on the structure type through
@scheme[define-serializable-struct/version].
@scheme[serializable-struct/version].
When a supertype is supplied in @scheme[id-maybe-super] is supplied,
When a supertype is supplied in @scheme[maybe-super] is supplied,
compile-time information bound to the supertype identifier must
include all of the supertype's field accessors. If any field mutator
is missing, the structure type will be treated as immutable for the
@ -379,20 +378,28 @@ structure type cannot be handled by the deserializer).
@examples[
#:eval ser-eval
(define-serializable-struct point (x y))
(point-x (deserialize (serialize (make-point 1 2))))
(serializable-struct point (x y))
(point-x (deserialize (serialize (point 1 2))))
]}
@; ----------------------------------------------------------------------
@defform/subs[(define-serializable-struct/versions id-maybe-super vers (field ...)
@defform[(define-serializable-struct id-maybe-super (field ...)
struct-option ...)]{
Like @racket[serializable-struct], but with the supertype syntax and
default constructor name of @racket[define-struct].}
@; ----------------------------------------------------------------------
@defform/subs[(serializable-struct/versions id-maybe-super vers (field ...)
(other-version-clause ...)
struct-option ...)
([other-version-clause (other-vers make-proc-expr
cycle-make-proc-expr)])]{
Like @scheme[define-serializable-struct], but the generated
deserializer binding is
Like @scheme[serializable-struct], but the generated deserializer
binding is
@schemeidfont{deserialize-info:}@scheme[_id]@schemeidfont{-v}@scheme[vers]. In
addition,
@schemeidfont{deserialize-info:}@scheme[_id]@schemeidfont{-v}@scheme[other-vers]
@ -410,35 +417,44 @@ instance of @scheme[id] and copies its field values into @scheme[x].
@examples[
#:eval ser-eval
(define-serializable-struct point (x y) #:mutable #:transparent)
(define ps (serialize (make-point 1 2)))
(serializable-struct point (x y) #:mutable #:transparent)
(define ps (serialize (point 1 2)))
(deserialize ps)
(define x (make-point 1 10))
(define x (point 1 10))
(set-point-x! x x)
(define xs (serialize x))
(deserialize xs)
(define-serializable-struct/versions point 1 (x y z)
(serializable-struct/versions point 1 (x y z)
([0
(code:comment @#,t{Constructor for simple v0 instances:})
(lambda (x y) (make-point x y 0))
(lambda (x y) (point x y 0))
(code:comment @#,t{Constructor for v0 instance in a cycle:})
(lambda ()
(let ([p0 (make-point #f #f 0)])
(let ([p0 (point #f #f 0)])
(values
p0
(lambda (p)
(set-point-x! p0 (point-x p))
(set-point-y! p0 (point-y p))))))])
#:mutable #:transparent)
(deserialize (serialize (make-point 4 5 6)))
(deserialize (serialize (point 4 5 6)))
(deserialize ps)
(deserialize xs)
]}
@; ----------------------------------------------------------------------
@defform[(define-serializable-struct/versions id-maybe-super vers (field ...)
(other-version-clause ...)
struct-option ...)]{
Like @racket[serializable-struct/versions], but with the supertype syntax and
default constructor name of @racket[define-struct].}
}
@; ----------------------------------------------------------------------
@defproc[(make-deserialize-info [make procedure?]
[cycle-make (-> (values any/c procedure?))])
any]{

View File

@ -2,7 +2,7 @@
(provide all-contract-tests)
(require rktunit
(require racunit
deinprogramm/define-record-procedures
deinprogramm/contract/contract
deinprogramm/contract/contract-syntax)

View File

@ -2,7 +2,7 @@
(provide all-image-tests)
(require rktunit
(require racunit
deinprogramm/image
(only-in lang/private/imageeq image=?)
mred

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require rktunit/text-ui)
(require racunit/text-ui)
(require tests/deinprogramm/contract)
(run-tests all-contract-tests)

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require rktunit/text-ui)
(require racunit/text-ui)
(require tests/deinprogramm/image)
(run-tests all-image-tests)

View File

@ -216,7 +216,7 @@
=> '(#"1 test passed\n" #"2 tests passed\n")
)
;; RktUnit stuff
;; RacUnit stuff
;; (examples that should fail modified to ones that shouldn't)
#|

View File

@ -1,7 +1,7 @@
#lang scheme/base
(require scheme/future
rktunit)
racunit)
#|Need to add expressions which raise exceptions inside a
future thunk which can be caught at the touch site

View File

@ -1,6 +1,6 @@
#lang racket
(require rktunit
rktunit/text-ui
(require racunit
racunit/text-ui
net/url
(prefix-in h: html)
(prefix-in x: xml))

View File

@ -21,7 +21,7 @@
"plot"
"profj"
"r6rs"
"rktunit"
"racunit"
"srfi"
"srpersist"
"stepper"

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require rktunit
rktunit/gui)
(require racunit
racunit/gui)
(require macro-debugger/model/debug
"gentest-framework.ss"
"gentests.ss"

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require rktunit)
(require racunit)
(require macro-debugger/model/debug
macro-debugger/model/stx-util
"gentest-framework.ss"

View File

@ -1,6 +1,6 @@
#lang scheme/base
(require rktunit
rktunit/gui)
(require racunit
racunit/gui)
(require macro-debugger/model/debug
scheme/path
scheme/gui)

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require rktunit)
(require racunit)
(require macro-debugger/model/debug
"../test-setup.ss")
(provide specialized-hiding-tests)

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require rktunit)
(require racunit)
(require macro-debugger/model/debug
"../test-setup.ss")
(provide policy-tests)

View File

@ -1,5 +1,5 @@
#lang scheme/base
(require rktunit)
(require racunit)
(require macro-debugger/model/debug
macro-debugger/model/steps
"../test-setup.ss")

View File

@ -6,7 +6,7 @@
(for-syntax scheme/base)
(prefix-in m: mzlib/match)
(only-in srfi/13 string-contains)
rktunit)
racunit)
(define-syntax (comp stx)
(syntax-case stx ()

View File

@ -1,5 +1,5 @@
(module match-tests mzscheme
(require mzlib/match rktunit)
(require mzlib/match racunit)
(provide match-tests)

View File

@ -1,6 +1,6 @@
(module other-plt-tests mzscheme
(require rktunit net/uri-codec mzlib/pregexp mzlib/plt-match
(require racunit net/uri-codec mzlib/pregexp mzlib/plt-match
mzlib/list mzlib/etc)
(define-struct shape (color))

View File

@ -1,5 +1,5 @@
(module other-tests mzscheme
(require mzlib/match rktunit)
(require mzlib/match racunit)
(provide other-tests)

Some files were not shown because too many files have changed in this diff Show More