38 Generics

▼ |  | Unstable

1 | Guidelines for developing unstable libraries
2 | Bytes
3 | Classes and Objects
4 | Contracts
5 | Definitions
6 | Dictionaries
7 | Directories
8 | Exceptions
9 | Filesystem
10 | Functions
11 | Lists
12 | Net
13 | Path
14 | PLane T Packages
15 | Ports
16 | Pretty-Printing
17 | Regular Expressions
18 | Requiring Modules
19 | Sandboxed Evaluation
20 | Scribble Documentation
21 | Sets
22 | S-Expression Diff
23 | Source Locations
24 | Strings
25 | Structs
26 | Syntax
27 | Planet Package Macros
28 | Text Representations
29 | Multiple Values
30 | XML and CSS
31 | Polymorphic Contracts
32 | Finding Mutated Variables
33 | Find
34 | Interface-Oriented Programming for Classes
35 | Sequences
36 | Hash Tables
37 | Match
38 | Generics
39 | Mark Parameters
40 | Debugging
41 | Contracts for macro subexpressions
42 | GUI libraries

On this page:

define-generics
generics
define-methods
define/ generic

Version: 5.0.1.5
top← prev up next →

### 38`` Generics

Eli Barzilay
and Jay McCarthy <jay@racket-lang.org>

( require unstable/generics)

This library is unstable; compatibility will not be maintained. See Unstable for more information.

( define-generics (name prop:name name?)
[method . kw-formals*]
...)

kw-formals* |  | = |  | (arg* ...)
|  | | |  | (arg* ...+ . rest-id)
|  | | |  | rest-id
arg* |  | = |  | id
|  | | |  | [id]
|  | | |  | keyword id
|  | | |  | keyword [id]

> | name |  | : |  | identifier?

> | prop:name |  | : |  | identifier?

> | name? |  | : |  | identifier?

> | method |  | : |  | identifier?

Defines name as a transformer binding for the static information about a new generic group.

Defines prop:name as a structure type property. Structure types implementing this generic group should have this property where the value is a vector with one element per method where each value is either #f or a procedure with the same arity as specified by kw-formals*. (kw-formals* is similar to the kw-formals used by lambda, except no expression is given for optional arguments.) The arity of each method is checked by the guard on the structure type property.

Defines name? as a predicate identifying instances of structure types that implement this generic group.

Defines each method as a generic procedure that calls the corresponding method on values where name? is true. Each method must have a required by-position argument that is free-identifier=? to name. This argument is used in the generic definition to locate the specialization.

( generics name
[method . kw-formals*]
...)

> | name |  | : |  | identifier?

> | method |  | : |  | identifier?

Expands to

( define-generics (name prop:name name?)
[method . kw-formals*]
...)

where prop:name and name? are created with the lexical context of name.

( define-methods name definition ...)

| name |  | : |  | identifier?

name must be a transformer binding for the static information about a new generic group.

Expands to a value usable as the property value for the structure type property of the name generic group.

If the definitions define the methods of name, then they are used in the property value.

If any method of name is not defined, then #f is used to signify that the structure type does not implement the particular method.

Allows define/generic to appear in definition ....

( define/generic local-name method-name)

> | local-name |  | : |  | identifier?

> | method-name |  | : |  | identifier?

When used inside define-methods, binds local-name to the generic for method-name. This is useful for method specializations to use the generic methods on other values.

Syntactically an error when used outside define-methods.

Examples:

> ( define-generics (printable prop:printable printable?)
(gen-print printable [port])
(gen-port-print port printable)
(gen-print* printable [port] #:width width #:height [height]))

> ( define-struct num (v)
#:property prop:printable
( define-methods printable
( define/generic super-print gen-print)
( define (gen-print n [port ( current-output-port)])
( fprintf port "Num: ~a" (num-v n)))
( define (gen-port-print port n)
(super-print n port))
( define (gen-print* n [port ( current-output-port)]
#:width w #:height [h 0])
( fprintf port "Num (~ax~a): ~a" w h (num-v n)))))

> ( define-struct bool (v)
#:property prop:printable
( define-methods printable
( define/generic super-print gen-print)
( define (gen-print b [port ( current-output-port)])
( fprintf port "Bool: ~a"
( if (bool-v b) "Yes" "No")))
( define (gen-port-print port b)
(super-print b port))
( define (gen-print* b [port ( current-output-port)]
#:width w #:height [h 0])
( fprintf port "Bool (~ax~a): ~a" w h
( if (bool-v b) "Yes" "No")))))

> ( define x (make-num 10))
> (gen-print x)
Num: 10
> (gen-port-print ( current-output-port) x)
Num: 10
> (gen-print* x #:width 100 #:height 90)
Num (100x90): 10
> ( define y (make-bool #t))
> (gen-print y)
Bool: Yes
> (gen-port-print ( current-output-port) y)
Bool: Yes
> (gen-print* y #:width 100 #:height 90)
Bool (100x90): Yes

top← prev up next →