$
~vs
$:
$c
~d
~l
8.18
top
← prev up next →

Racket Generic Binding FormsπŸ”— i

Stephen Chang <stchang at racket-lang dot org>
and Alexander Knauth <alexander at knauth dot org>

This library implements new Racket binding forms (ie, ~define , ~lambda , ~let , etc.) that support generic binding instances. A generic binding instance is a syntax object that implements an "interface" (currently just some syntax properties) that the binding forms then use to determine how to proceed with the binding.

This moves the binding "logic" to the binding site itself and enables one binding form to support many different binding modes (ie, match or values ), rather than have to manually implement a version of each binding form for all the different combinations (ie, define-values , match-define , match-define-values , etc.).

The hope is that the forms in this library can be used in place of their analogous Racket counterparts.

1Generic Binding InstancesπŸ”— i

The forms described in this section may be used only in binding positions of binding forms that support generic bindings. Any other use is invalid. For examples, see the next section, Core Generic Binding Forms.

Generic binding instances are further separated into two categories:
  • bindings that may be used anywhere, and

  • bindings that may only be used in "define" contexts.

The second category is a subset of the first and is needed in order to handle Racket’s multiple return values . Since Racket functions cannot receive values , we must know what we are binding at the time of the binding. For example, this means that ~let may support values binding, but ~define or ~lambda may not. Thus, the second category essentially the first, but without values -bindings.

A few generic binding instances are currently supported. Defining new generic bindings is currently limited to new match -specific binding instances. See Implementing New Generic Binding Instances for more information.

syntax

( $ match-pattern)

The match binding instance. The required pattern is a match pattern. May be used in any context.

Other generic binding instances can be nested within the match pattern.

syntax

( ~vs b...)

b = define-allowable-generic-binding
Binding instance for values . May only be used in "let" contexts (which means not in ~define or ~lambda for example).

Currently supports one-level of nested generic binding instances. In other words, each binding site in the ~vs form may be either an identifier, or another generic binding instance. However, any nested binding positions are considered "define" contexts. This means that one cannot nest ~vs bindings.

syntax

( b...)

Same as ~vs .

syntax

( $: xxs)

A match binding instance where the outer match pattern is cons . Equivalent to ($ (cons xxs)).

syntax

( $list x...)

($list x...:rst)
A match binding instance where the outer match pattern is either list or list-rest, depending whether a rest argument is supplied. Equivalent to either ($ (list x... )) or ($ (list-restx... rst)).

value

$null :_

A match binding instance for null .

syntax

( $stx patternpattern-directive...)

A binding instance for parsing syntax-objects with syntax-parse .

syntax

( $and b...)

b = generic-binding
A binding instance that binds each b binding.

syntax

( $c dbcontract-expr)

($c b(valuescontract-expr...))
db = define-allowable-generic-binding
b = generic-binding
A binding instance that binds b or db with a contract.

2Core Generic Binding FormsπŸ”— i

syntax

( ~define bbody)

(~define (fdb...)body...)
b = generic-binding
| identifier?
db = define-allowable-generic-binding
| identifier?
Same as define but each binding site (except for the function name) may be either an identifier or a generic binding instance.

When using ~define to define a function, any generic binding must be define-allowable. (So the ~vs values-binding form is not allowed.)

define -like, non-function examples:
> (~define x1(+ 12))
> x1

3

> (~define x2(list 12))
> x2

'(1 2)

Non-function examples with generic bind forms:
> (~define ($ (list y1y2))(list 1020))
> y1

10

> y2

20

> (~define ($ (list (cons y3y4)y5))(list (cons 2030)40))
> y3

20

> y4

30

> y5

40

> (~define ( v1v2)(values 101202))
> v1

101

> v2

202

> (~define ( ($ (list x4x5))x6)(values (list 99999)9999))
> x4

99

> x5

999

> x6

9999

> (struct A(xy))
> (~define ($ (Ax7y7))(A101202))
> x7

101

> y7

202

> (~define ($stx ((~seq kw:keywordarg:expr)... ))#'(#:a1#:b2#:c3))
> #'(kw... )

#<syntax:eval:25:0 (#:a #:b #:c)>

> #'(arg... )

#<syntax:eval:26:0 (1 2 3)>

> #'([kw. arg]... )

#<syntax:eval:27:0 ((#:a . 1) (#:b . 2) (#:c . 3))>

define -like function examples:
> (~define (f1x[y10]#:z[z0])(+ xyz))
> (f1100)

110

> (f1100200)

300

> (f1100200#:z300)

600

> (~define (f3. rst)rst)
> (f3123)

'(1 2 3)

> (f3)

'()

> (~define (f4xy. rst)(cons x(cons yrst)))
> (f4123456)

'(1 2 3 4 5 6)

> (f412)

'(1 2)

Function examples using generic bind forms:
> (~define (f2($ (list xy)))(- xy))
> (f2(list 14545))

100

> (~define (g1($ (list (list ab)y... )))(apply + aby))
> (g1(list (list 101202)303))

606

> (~define (f5($ (list (list xy)z)). rst)(cons x(cons y(cons zrst))))
> (f5(list (list 12)3))

'(1 2 3)

> (f5(list (list 12)3)45)

'(1 2 3 4 5)

> (~define (gg($ xxx))(add1 xxx))
> (gg10001)

10002

> (~define (ggg($ _ ))12345)
> (ggg5432)

12345

> (~define (gggg($ 11111))22222)
> (gggg111)

match-define: no matching clause for 111

> (gggg11111)

22222

> (~define (f20($list xyz:xs))(+ xyz(length xs)))
> (f20(list 102030405060708090))

66

> (~define (f21($: xxs))(+ x(length xs)))
> (f21(list 102030405060708090))

18

Argument-with-default and keyword binding positions support generic bindings too:
> (~define (fkw1[($list xy)(list 12)])(+ xy10))
> (fkw1)

13

> (fkw1(list 1020))

40

> (fkw110)

match-define: no matching clause for 10

> (~define (fkw2#:A($list xy))(+ xy10))
> (fkw2#:A(list 12))

13

> (~define (fkw3#:B[($list xy)(list 12)])(+ xy10))
> (fkw3#:B(list 1020))

40

> (fkw3#:B10)

match-define: no matching clause for 10

syntax

( ~def ...)

Same as ~define .

syntax

( ~d ...)

Same as ~define .

syntax

( ~define/contract bcontract-exprbody)

(~define/contract (fdb...)contract-exprbody...)
b = generic-binding
| identifier?
db = define-allowable-generic-binding
| identifier?
like define/contract , except allowing generic binding instances like ~define .

syntax

( ~lambda dbbody...)

(~lambda (db...)body...)
db = define-allowable-generic-binding
| identifier?
Same as lambda but each binding site may be either an identifier or a (define-allowable) generic binding instance. (So the ~vs values-binding form is not allowed.)

If a single identifier is given with no parentheses, then the arguments are put in a list, just like lambda . A single generic bind instance may also be used without parens. If a list of bindings if given, then each may be either an identifier or a generic bind instance.

syntax

( ~lam ...)

Same as ~lambda .

syntax

( ~l ...)

Same as ~lambda .

syntax

( ...)

Same as ~lambda .

Examples of standard, lambda -like behavior:
> (( (x)x)111)

111

> (( rstrst)123)

'(1 2 3)

> (( (x[y0]#:zz#:a[a10])(+ xyza))1#:z10)

21

> (( (x[y0]#:zz#:a[a10])(+ xyza))122#:z10)

43

> (( (x[y0]#:zz#:a[a10])(+ xyza))1#:z10#:a111)

122

> ((~lambda (x[y0]#:zz#:a[a10])(+ xyza))1#:z10#:a111)

122

Examples with generic bind forms:
> ((~lambda ($: xxs)(append xs(list x)))(list 12345))

'(2 3 4 5 1)

> ((~lambda (f($: xxs))(cons (fx)xs))add1 (list 1234))

'(2 2 3 4)

> ((~lambda (f($list ))(f1))add1 null )

2

> ((~lambda (f($list ))(f1))add1 (list 123))

match-define: no matching clause for '(1 2 3)

> (( (($ (list xy))($ (cons ab)))(+ abxy))
(list 12)(cons 34))

10

> (( (xy($ (Aab)))(+ xyab))1020(A3040))

100

Example of single-arg generic bind support:
> (( ($ (list xy))(+ xy))(list 1456))

70

The next example may look like a single-arg generic bind, but since ~vs is not allowed in this context, it is treated as an identifier and shadows the existing binding for ~vs .
> (( (~vs v1v2)(+ ~vs v1v2))123)

6

Here is a disallowed generic bind used in the standard way, resulting in an error:
> ( ((~vs v1v2))(+ v1v2))

eval:79:0: ~λ: expected a generic bind instance

at: ((~vs v1 v2))

in: (~λ ((~vs v1 v2)) (+ v1 v2))

parsing context:

while parsing a generic bind instance for define contexts

term: ((~vs v1 v2))

location: eval:79:0

Generic bind forms are allowed in keyword and arg-with-default binding positions too:
> (( ([($: xxs)(list 12)])(+ x(length xs)20)))

22

> (( ([($: xxs)(list 12)])(+ x(length xs)20))(list 1234))

24

> (( (#:C($: xxs))(append xs(list x)))#:C(list 123))

'(2 3 1)

> (( (#:D[($: xxs)(list 102030)])(append xs(list x))))

'(20 30 10)

> (( (#:D[($: xxs)(list 102030)])(append xs(list x)))#:D(list 123))

'(2 3 1)

syntax

( ~case-lambda clause...)

clause = (headerbody...)
A "simulation" of a case-lambda that also acccepts generic binds.

Since case-lambda only distinguishes between cases based on the number of arguments, ~case-lambda cannot be defined in terms of case-lambda . Instead ~case-lambda defines a series of lambda s, and then tries to apply each one, backtracking on exn:misc:match? .

Examples:
> (define casemap1
[(f($: xxs))(cons (fx)(casemap1fxs))]))
> (casemap1add1 null )

'()

> (casemap1add1 (list 1))

'(2)

> (casemap1add1 (list 1234))

'(2 3 4 5)

> (casemap1add1 1)

match-define: no matching clause for 1

syntax

( ~case-lam clause...)

Same as ~case-lambda

syntax

( ~case-define fclause1...)

(~case-define fclause2...)
clause1 = (headerbody...)
clause2 = (b...body...)
Syntax for naming a ~case-lambda

Examples:
> (~case-define new-map1
[(f$null )null ]
[(f($: xxs))(cons (fx)(new-map1fxs))])
> (new-map1add1 null )

'()

> (new-map1add1 (list 1))

'(2)

> (new-map1add1 (list 12))

'(2 3)

> (~case-define new-filter1
[(p?$null )null ]
[(p?($: xxs))(if (p?x)(cons x(new-filter1p?xs))(new-filter1p?xs))])
> (new-filter1even? null )

'()

> (new-filter1even? (list 1))

'()

> (new-filter1even? (list 12345))

'(2 4)

> (~case-define new-foldl1
[(fbase$null )base]
[(fbase($: xxs))(new-foldl1f(fxbase)xs)])
> (new-foldl1- 0null )

0

> (new-foldl1- 0(list 1))

1

> (foldl - 0(list 1))

1

> (new-foldl1- 0(list 12))

1

> (foldl - 0(list 12))

1

> (~case-define new-foldr1
[(fbase$null )base]
[(fbase($: xxs))(fx(new-foldr1fbasexs))])
> (new-foldr1- 0null )

0

> (new-foldr1- 0(list 1))

1

> (foldr - 0(list 1))

1

> (new-foldr1- 0(list 12))

-1

> (foldr - 0(list 12))

-1

syntax

( ~case-def clause...)

Same as ~case-define

Examples:
> (~case-def new-map[f$null null ]
[f($: xxs)(cons (fx)(new-mapfxs))])
> (new-mapadd1 null )

'()

> (new-mapadd1 (list 1))

'(2)

> (new-mapadd1 (list 12))

'(2 3)

> (~case-def new-filter[p?$null null ]
[p?($: (?p?x)xs)(cons x(new-filterp?xs))]
[p?($: xxs)(new-filterp?xs)])
> (new-filtereven? null )

'()

> (new-filtereven? (list 1))

'()

> (new-filtereven? (list 12345))

'(2 4)

> (~case-def new-foldl[fbase$null base]
[fbase($: xxs)(new-foldlf(fxbase)xs)])
> (new-foldl- 0null )

0

> (new-foldl- 0(list 1))

1

> (foldl - 0(list 1))

1

> (new-foldl- 0(list 12))

1

> (foldl - 0(list 12))

1

> (~case-def new-foldr[fbase$null base]
[fbase($: xxs)(fx(new-foldrfbasexs))])
> (new-foldr- 0null )

0

> (new-foldr- 0(list 1))

1

> (foldr - 0(list 1))

1

> (new-foldr- 0(list 12))

-1

> (foldr - 0(list 12))

-1

syntax

( ~let loop([dbe]...)body...)

(~let ([be]...)body...)
db = define-allowable-generic-bind
| identifier?
b = generic-bind
| identifier?
Same as let , but with generic bind support. If a name is given to the let, then the bindings must be define-allowable, since it’s essentially defining a function. If no name is given to the ~let , then any generic bind is allowed.

Note that when using the match $ binding with ~let , the behavior is NOT like match-let , in that there is no coupling between between the binding positions. This means that trying to bind duplicate identifiers in a $ match pattern will produce the same results or errors as in let , let* , or letrec .

Examples:
> (define x55155)
> (~let ([x55(add1 x55)])x55)

156

> (define x56156)
> (~let ([x56157][x57x56])x57)

156

> (~let ([($ (list x58x59))(list 158159)])(list x59x58))

'(159 158)

> (~let ([(~vs v17v27)(values 1727)])(+ v17v27))

44

> (~let ([(~vs ($ (list x18y18))v18)(values (list 1819)20)])
(+ x18y18v18))

57

> (~let ([x1][x2])x)

eval:137:0: define-values: duplicate binding name

at: x

in: (define-values (x) (values g922))

> (~let ([($ (list xy))(list 12)][x3])x)

eval:138:0: define-values: duplicate binding name

at: x

in: (define-values (x) (values g924))

> (~let ([x3][($ (list xy))(list 12)])x)

eval:139:0: define-values: duplicate binding name

at: x

in: (define-values (x y) (let-local-keys ((g40402

stx-param929)) (let-values (((temp930) (values g928)))

(match*/derived (temp930) (match-define (list x y) (values

g928)) (((list x y)) (values x y))))))

> (~let ([($ (list xy))(list 12)][($ (list xy))(list 34)])(list xy))

eval:140:0: define-values: duplicate binding name

at: x

in: (define-values (x y) (let-local-keys ((g40402

stx-param935)) (let-values (((temp936) (values g932)))

(match*/derived (temp936) (match-define (list x y) (values

g932)) (((list x y)) (values x y))))))

> (~let ([($ (list xy))(list 12)][(~vs xy)(list 34)])(list xy))

eval:141:0: define-values: duplicate binding name

at: x

in: (define-values (x) g942)

> (~let ([($ (list xx))(list 22)])x)

2

> (let ([x12345])(~let ([x40][yx])y))

12345

> (let ([x12345])(~let ([x40][y1][zx])z))

12345

> (let ([x12345][y5432])(~let ([x40][y23][zy])z))

5432

> (~let ([x59x59])x59)

x59: undefined;

cannot reference an identifier before its definition

in module: top-level

> (~let ([f(λ (x)(if (zero? x)1(* x(f(sub1 x)))))])(f10))

f: undefined;

cannot reference an identifier before its definition

in module: top-level

> (~let L([($ (list xy... ))(list 12345)][n4])
(if (zero? n)0
(+ nx(Ly(sub1 n)))))

20

> (let loop([x1][x2])x)

eval:149:0: let: duplicate identifier

at: x

in: (let loop ((x 1) (x 2)) x)

> (~let loop([x1][x2])x)

eval:150:0: lambda: duplicate argument name

at: x

in: (lambda (x x) x)

> (define x8109)
> (let loop([x81][yx8])y)

109

> (~let loop([x81][yx8])y)

109

syntax

( ~let* ([be]...)body...)

b = generic-bind
| identifier?
Same as let* , but with generic bind support.

Examples:
> (~let* ([x46436][yx])y)

46436

> (~let* ([($ (list xy))(list 10102020)][z(+ xy)])z)

3030

> (~let* ([( v1v2)(values 40405050)][z(+ v1v2)])z)

9090

> (~let* ([( v3($ (list xyyx)))(values 202(list 303404))]
[z(+ v3(- yxxy))])
z)

303

> (~let* ([x1122]
[( ($ (cons abbc))($ (list-restyys)))
(values (cons x(* x2))(list x(add1 x)(sub1 x)))])
(+ (- bcab)(- y(+ (car ys)(cadr ys)))))

0

> (~let* ([x101][x202])x)

202

syntax

( ~letrec ([be]...)body...)

b = generic-bind
| identifier?
Same as letrec , but with generic bind support.

Examples:
> (require math/number-theory)
> (~letrec ([xx])x)

x: undefined;

cannot use before initialization

> (~letrec ([f(λ (x)(if (zero? x)1(* x(f(sub1 x)))))])(f10))

3628800

> (factorial10)

3628800

> (~letrec ([evn?(λ (x)(if (zero? x)#t(od?(sub1 x))))]
[od?(λ (x)(if (zero? x)#f(evn?(sub1 x))))])
(evn?10))

#t

> (~letrec ([( evn?od?)
(values (λ (x)(if (zero? x)#t(od?(sub1 x))))
(λ (x)(if (zero? x)#f(evn?(sub1 x)))))])
(evn?10))

#t

> (~letrec ([($ (list evn?od?))
(list (λ (x)(if (zero? x)#t(od?(sub1 x))))
(λ (x)(if (zero? x)#f(evn?(sub1 x)))))])
(and (od?101)(evn?10)))

#t

> (~letrec ([( evn?($ (list od?)))
(values (λ (x)(if (zero? x)#t(od?(sub1 x))))
(list (λ (x)(if (zero? x)#f(evn?(sub1 x))))))])
(and (od?101)(evn?10)))

#t

3Generic Comprehension FormsπŸ”— i

All the forms in this section are the same as their Racket counterparts (see for ), but with added generic bind support.

syntax

( ~for ...)

syntax

( ~for/list ...)

syntax

( ~for/lists ...)

syntax

( ~for/vector ...)

syntax

( ~for/fold ...)

Allows generic binds in sequence clauses, not accumulator clauses.

syntax

( ~for/foldr ...)

Allows generic binds in sequence clauses, not accumulator clauses.

syntax

( ~for/first ...)

syntax

( ~for/last ...)

syntax

( ~for/or ...)

syntax

( ~for/and ...)

syntax

( ~for/sum ...)

syntax

( ~for/product ...)

syntax

( ~for/hash ...)

syntax

( ~for/hasheq ...)

syntax

( ~for/hasheqv ...)

syntax

( ~for/hashalw ...)

syntax

( ~for* ...)

syntax

( ~for*/list ...)

syntax

( ~for*/lists ...)

syntax

( ~for*/vector ...)

syntax

( ~for*/fold ...)

Allows generic binds in sequence clauses, not accumulator clauses.

syntax

( ~for*/foldr ...)

Allows generic binds in sequence clauses, not accumulator clauses.

syntax

( ~for*/first ...)

syntax

( ~for*/last ...)

syntax

( ~for*/or ...)

syntax

( ~for*/and ...)

syntax

( ~for*/sum ...)

syntax

( ~for*/product ...)

syntax

( ~for*/hash ...)

syntax

( ~for*/hasheq ...)

syntax

( ~for*/hasheqv ...)

syntax

( ~for*/hashalw ...)

Examples:
> (~for/list ([($ (list xy))'((12)(34)(56))])(list yx))

'((2 1) (4 3) (6 5))

([($ (list xy))'((12)(34))]
[($ (list ab))'((56)(78))])
(list yxba))

'((2 1 6 5) (4 3 8 7))

([($ (list xy))'((12)(34))]
[($ (list ab))'((56)(78))]
#:when(= x1))
(list yxba))

'((2 1 6 5))

([($ (list xy))'((12)(34))]
[($ (list ab))'((56)(78))]
#:unless(= x1))
(list yxba))

'((4 3 8 7))

([($ (list xy))'((22)(14)(14))]
[($ (list ab))'((56)(67)(78))]
#:when(= x1)
#:unless(= a6))
(list yxba))

'((4 1 8 7))

> (~for/list ([x'(123)]#:break(= x2))x)

'(1)

> (~for/list ([x'(123)]#:final(= x2))x)

'(1 2)

> (~for*/list ([x'(123)])#:break(= x2)x)

'(1)

> (~for*/list ([x'(123)])#:final(= x2)x)

'(1 2)

> (~for/list ([x'(123)]#:when#t[y'(456)]#:when#t)(list xy))

'((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

> (~for*/list ([x'(123)][y'(456)])(list xy))

'((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

> (require racket/generator)
> (~for/list ([($ (list xy))(in-generator(let loop([n3])
(yield(list n(add1 n)))
(loop(sub1 n)))))])
(list xy))

'((3 4) (2 3) (1 2))

> (~for/fold ([sum0])([x'(123456)])(+ xsum))

21

> (for/fold ([sum0])([x'(123456)])(+ xsum))

21

> (~for/and ([x(list #t#f#t)])(displayln x)x)

#t

#f

#f

> (~for*/list ([($ (list xy))(list (list (list 123)(list 456))
(list (list 101112)(list 131415)))]
[ax][by])
(list ab))

'((1 4)

(1 5)

(1 6)

(2 4)

(2 5)

(2 6)

(3 4)

(3 5)

(3 6)

(10 13)

(10 14)

(10 15)

(11 13)

(11 14)

(11 15)

(12 13)

(12 14)

(12 15))

> (for*/list ([lst(list (list (list 123)(list 456))
(list (list 101112)(list 131415)))]
[a(car lst)][b(cadr lst)])
(list ab))

'((1 4)

(1 5)

(1 6)

(2 4)

(2 5)

(2 6)

(3 4)

(3 5)

(3 6)

(10 13)

(10 14)

(10 15)

(11 13)

(11 14)

(11 15)

(12 13)

(12 14)

(12 15))

> (~for*/list ([(~vs v1v2)(in-hash (hash 1234))]
[xv1][yv2])
(cons xy))

'((0 . 0)

(0 . 1)

(0 . 0)

(0 . 1)

(0 . 2)

(0 . 3)

(1 . 0)

(1 . 1)

(1 . 2)

(1 . 3)

(2 . 0)

(2 . 1)

(2 . 2)

(2 . 3))

> (for*/list ([(v1v2)(in-hash (hash 1234))]
[xv1][yv2])
(cons xy))

'((0 . 0)

(0 . 1)

(0 . 0)

(0 . 1)

(0 . 2)

(0 . 3)

(1 . 0)

(1 . 1)

(1 . 2)

(1 . 3)

(2 . 0)

(2 . 1)

(2 . 2)

(2 . 3))

> (~for*/list ([(v1v2)(in-hash (hash 1234))]
[xv1][yv2])
(cons xy))

'((0 . 0)

(0 . 1)

(0 . 0)

(0 . 1)

(0 . 2)

(0 . 3)

(1 . 0)

(1 . 1)

(1 . 2)

(1 . 3)

(2 . 0)

(2 . 1)

(2 . 2)

(2 . 3))

> (~for*/list ([(~vs ($ (list xy))($ (list ab)))
(in-hash (hash (list 12)(list 34)(list 56)(list 78)))]
[cx])
(list xyabc))

'((1 2 3 4 0) (5 6 7 8 0) (5 6 7 8 1) (5 6 7 8 2) (5 6 7 8 3) (5 6 7 8 4))

> (for*/list ([(lst1lst2)(in-hash (hash (list 12)(list 34)(list 56)(list 78)))]
[c(car lst1)])
(list (car lst1)(cadr lst1)(car lst2)(cadr lst2)c))

'((1 2 3 4 0) (5 6 7 8 0) (5 6 7 8 1) (5 6 7 8 2) (5 6 7 8 3) (5 6 7 8 4))

4Implementing New Generic Binding InstancesπŸ”— i

Only defining match -specific new binding instances are currently possible.

syntax

( define-match-bind (namex...))

Defines a new binding instance $name that binds using the match pattern (namex... ).

> (struct B(xyz))
> (define-match-bind (Bxyz))
> (~define (bf($Bxyz))(+ xyz))
> (bf(B204060))

120

> (define-match-bind hash-table)
> (~define ($hash-table[keysvals]... )(hash 'a1'b2'c3))
> keys

'(c b a)

> vals

'(3 2 1)

syntax

( ~struct struct-id(field...)struct-option...)

(~struct struct-idsuper-struct-id(field...)struct-option...)
field = field-id
| [field-idfield-option...]
struct-option = #:mutable
| #:supersuper-expr
| #:inspectorinspector-expr
| #:auto-valueauto-expr
| #:guardguard-expr
| #:propertyprop-exprval-expr
| #:transparent
| #:prefab
| #:sealed
| #:authentic
| #:namename-id
| #:extra-namename-id
| #:constructor-nameconstructor-id
| #:extra-constructor-nameconstructor-id
| #:reflection-namesymbol-expr
| #:methodsgen:name-idmethod-defs
| #:omit-define-syntaxes
| #:omit-define-values
field-option = #:mutable
| #:auto
method-defs = (definition...)
Exactly like struct except a new generic binding instance is also defined. Equivalent to using struct and define-match-bind .

> (~struct C(abc[d#:mutable]))
Behaves like a struct -defined struct:
> (define c(C9876))
> (C?c)

#t

> (C-ac)

9

> (C-bc)

8

> (C-cc)

7

> (C-dc)

6

> (set-C-d!c20)
> (C-dc)

20

Generic binding instance:
> (~define (cf($Cefgh))(+ efgh))
> (cfc)

44

syntax

( ~struct/contract struct-id
([fieldcontract-expr]...)
struct-option...)
(~struct/contract struct-idsuper-struct-id
([fieldcontract-expr]...)
struct-option...)
field = field-id
| [field-idfield-option...]
struct-option = #:mutable
| #:auto-valueauto-expr
| #:propertyprop-exprval-expr
| #:transparent
| #:omit-define-syntaxes
field-option = #:mutable
| #:auto
Exactly like struct/contract except a new generic binding instance is also defined. Equivalent to using struct/contract and define-match-bind .

> (~struct/contract D([anumber? ][bstring? ][[c#:mutable]list? ]))
Behaves like a struct/contract -defined struct:
> (define d(D200"abcdefghij"'(klmnop)))
> (D?d)

#t

> (D-ad)

200

> (D-bd)

"abcdefghij"

> (D-cd)

'(k l m n o p)

> (set-D-c!d'(qrs))
> (D-cd)

'(q r s)

Generic binding instance:
> (~define (df($Dnsl))(+ n(string-length s)(length l)))
> (dfd)

213

syntax

([fieldcontract-expr]...)
struct-option...)
(~define-struct/contract (struct-idsuper-struct-id)
([fieldcontract-expr]...)
struct-option...)
field = field-id
| [field-idfield-option...]
struct-option = #:mutable
| #:auto-valueauto-expr
| #:propertyprop-exprval-expr
| #:transparent
| #:omit-define-syntaxes
field-option = #:mutable
| #:auto
Exactly like define-struct/contract except a new generic binding instance is also defined. Equivalent to using define-struct/contract and define-match-bind .

> (~define-struct/contract E([anumber? ][bstring? ][[c#:mutable]list? ]))
Behaves like a define-struct/contract -defined struct:
> (define e(make-E200"abcdefghij"'(klmnop)))
> (E?e)

#t

> (E-ae)

200

> (E-be)

"abcdefghij"

> (E-ce)

'(k l m n o p)

> (set-E-c!e'(qrs))
> (E-ce)

'(q r s)

Generic binding instance:
> (~define (ef($Ensl))(+ n(string-length s)(length l)))
> (efe)

213

top
← prev up next →

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /