On this page:
2.1 Constructors
make
:
make!
:  !
2.2 Transformers
->boolean
->string
->number
->inexact
->exact
->integer
->list
->vector
->symbol
->keyword
->bytes
->char
->stream
->generator
->set
->syntax
->symex
string->symex
->values
->hash
->procedure

2 Types🔗ℹ

 (require relation/type) package: relation-lib

Generic utilities for constructing data and transforming it from one type to another.

The type constructors and transformers provided by Racket out of the box are type-specific; for instance in order to construct a list, we use cons or list, and for a stream we’d use stream-cons or stream. Likewise, to convert data into a string, we would use symbol->string if the data is a symbol, and number->string if the data is a number. Similarly, converting a number to an integer from a more precise form, or vice versa, typically involves multiple steps and the method varies depending on the number’s type.

This module provides a generic type constructor that constructs a type by referring to a provided instance, and also provides convenient interfaces to perform many common type conversions, while keeping them agnostic to the source type. If mutable and immutable versions of a data type exist, these interfaces will return the immutable version.

See also: Sugar.

2.1 Constructors🔗ℹ

procedure

(make form element ...)  collection?

  form : collection?
  element : any/c

procedure

(: element ... form)  any/c

  element : any/c
  form : any/c

procedure

(make! form element ...)  collection?

  form : collection?
  element : any/c

procedure

(:! element ... form)  any/c

  element : any/c
  form : any/c
make is a generic constructor that creates a value of the same type as form out of the provided elements and form itself. This utility relies upon the gen:collection interface for the means to create an instance of the desired type. Custom types must therefore implement gen:collection in order to support construction via make.

: is a convenience wrapper around make with a more familiar interface, mirroring the cons list constructor in terms of argument order and the constructed result, and handling additional common cases outside the purview of make. In particular, if form is not a generic collection, then the elements are simply cons’d together (if there are two of them) or collected into a list (if there are more).

make! and :! are similar except that they mutate the form rather than construct the new object "functionally."

These constructors are a generic alternative to type-specific constructors like cons, stream-cons, set-add, hash-set, and so on (along with their mutative counterparts), with the caveat that for streams, the construction will not happen lazily since these generic versions are functions rather than macros. For streams, unless you are just prototyping or running tests in a shell, you will want to use stream-cons directly.

Examples:
> (: 1 2)

'(1 . 2)

> (: 1 2 3 4 5)

'(1 2 3 4 5)

> (: 1 null)

'(1)

> (: 1 (list 2 3))

'(1 2 3)

> (: 1 2 3 4 (list 5 6))

'(1 2 3 4 5 6)

> (->list (: 1 empty-stream))

'(1)

> (: 1 #(2 3))

'#(2 3 1)

> (: '(a . 1) (hash 'b 2 'c 3))

'#hash((a . 1) (b . 2) (c . 3))

> (define h (hash 'a 1 'b 2 'c 3))
> (:! '(a . 5) h)
> h

'#hash((a . 5) (b . 2) (c . 3))

> (define s (set 1 2 3))
> (:! 2 3 4 s)
> (->list s)

'(4 3 2 1)

2.2 Transformers🔗ℹ

procedure

(->boolean v)  boolean?

  v : any/c
Maps the input data to a boolean. Note that in Racket, out of the box, anything that isn’t #f is treated as #t, including, for instance, the empty string and the number 0.

Examples:
> (->boolean 42)

#t

> (->boolean #f)

#f

> (->boolean "apple")

#t

procedure

(->string v)  string?

  v : any/c
Maps the input data to a string.

Examples:
> (->string 42)

"42"

> (->string 'apple)

"apple"

> (->string '(1 2 3))

"(1 2 3)"

> (->string ID)

""

procedure

(->number v)  number?

  v : any/c
Maps the input data to a number.

Examples:
> (->number "42")

42

> (->number #\a)

97

procedure

(->inexact v)  inexact?

  v : any/c
Maps the input data to an inexact number.

Examples:
> (->inexact 3/2)

1.5

> (->inexact "42")

42.0

procedure

(->exact v)  exact?

  v : any/c
Maps the input data to an exact number.

Examples:
> (->exact 1.5)

3/2

> (->exact "42")

42

procedure

(->integer v [#:round round])  integer?

  v : any/c
  round : (one-of/c 'up 'down 'nearest) = 'down
Maps the input data to an integer.

Examples:
> (->integer "42")

42

> (->integer 3/2)

1

> (->integer 3/2 #:round 'up)

2

> (->integer 3.6 #:round 'nearest)

4

procedure

(->list v)  list?

  v : any/c
Maps the input data to a list.

Examples:
> (->list "apple")

'(#\a #\p #\p #\l #\e)

> (->list #(1 2 3))

'(1 2 3)

> (->list (stream 1 2 3))

'(1 2 3)

> (->list (hash 'a 1 'b 2 'c 3))

'((c . 3) (b . 2) (a . 1))

procedure

(->vector v)  vector?

  v : any/c
Maps the input data to a vector.

Examples:
> (->vector "apple")

'#(#\a #\p #\p #\l #\e)

> (->vector '(1 2 3))

'#(1 2 3)

> (->vector (stream 1 2 3))

'#(1 2 3)

> (->vector (hash 'a 1 'b 2 'c 3))

'#((c . 3) (b . 2) (a . 1))

procedure

(->symbol v)  symbol?

  v : any/c
Maps the input data to a symbol.

Examples:
> (->symbol "apple")

'apple

> (->symbol '#:apple)

'apple

procedure

(->keyword v)  keyword?

  v : any/c
Maps the input data to a keyword.

Examples:
> (->keyword "apple")

'#:apple

> (->keyword 'apple)

'#:apple

procedure

(->bytes v)  bytes?

  v : any/c
Maps the input data to a byte string.

Examples:
> (->bytes "apple")

#"apple"

> (->bytes '(97 112 112 108 101))

#"apple"

procedure

(->char v)  char?

  v : any/c
Maps the input data to a character.

Examples:
> (->char "a")

#\a

> (->char 97)

#\a

> (->char 'a)

#\a

procedure

(->stream v)  stream?

  v : any/c
Maps the input data to a stream.

Examples:
> (->stream "apple")

#<stream>

> (->stream '(97 112 112 108 101))

'(97 112 112 108 101)

procedure

(->generator v [return])  generator?

  v : any/c
  return : any/c = (void)
Maps the input data to a generator. If a return value is provided, it will be used as the return value of the generator once the sequence v has been exhausted. Any sequence can be transformed into a generator, and vice versa. This allows us to leverage sequence patterns for generators in a natural way, for instance cons-ing and extending generators to produce additional values by transforming them into streams and then back again.

Note that, owing to the stateful nature of the underlying generator, it’s possible that a stream constructed from a generator would continue to provide lazy evaluation but not take up constant memory. On the other hand, a stream to generator conversion should not incur any additional memory overhead.

Another thing to be wary of with a generator to stream conversion is that since the underlying generator is mutable, independent invocations of the generator after the stream has been constructed would affect the sequence represented by the stream, which is likely to result in unexpected behavior. In general it is advisable to manipulate stateful entities such as generators via a single common interface, whether that is, in the present case, the generator itself directly, or the stream representation of it – but not both.

Examples:
> (->generator "apple")

#<procedure:sequence->generator>

> (->generator '(97 112 112 108 101))

#<procedure:sequence->generator>

> (->list (->generator (conj (->stream (->generator '(1 2 3))) 4)))

'(4 1 2 3)

procedure

(->set v)  set?

  v : any/c
Maps the input data to a set.

Examples:
> (->set "apple")

(set #\p #\a #\e #\l)

> (->set '(1 2 2 3 3 3))

(set 1 2 3)

procedure

(->syntax v [ctx])  syntax?

  v : any/c
  ctx : syntax? = #f
Constructs a syntax object wrapping the provided symbolic expression v. If the input is already a syntax object, then it is left unchanged. If a syntax object ctx is provided, it will be used as the context in constructing the new syntax object.

Examples:
> (->syntax "apple")

#<syntax "apple">

> (->syntax 42)

#<syntax 42>

> (->syntax '(+ 1 2))

#<syntax (+ 1 2)>

procedure

(->symex v)  any/c

  v : any/c

procedure

(string->symex v)  any/c

  v : any/c
->symex maps a syntax object to its underlying symbolic expression, the literal "code" that will be evaluated by the interpreter. If the input is already a symex (also known in Racket as a datum), then it is left unchanged.

string->symex maps a string to a symex by treating the string as a representation of a symex rather than as a symex itself (which it is, since a string by itself is a valid expression).

Examples:
> (->symex "apple")

"apple"

> (->symex #'42)

42

> (->symex #'(+ 1 2))

'(+ 1 2)

> (->symex #'(define (square x) (* x x)))

'(define (square x) (* x x))

> (eval (->symex #'((λ (x) (* x x)) 4)))

16

> (->symex "(+ 1 2)")

"(+ 1 2)"

> (string->symex "(+ 1 2)")

'(+ 1 2)

procedure

(->values v)  values?

  v : any/c
Maps the input data to a set of values.

Examples:
> (->values #(1 2 3))

1

2

3

> (->values '(1 2 3))

1

2

3

> (->values "apple")

#\a

#\p

#\p

#\l

#\e

procedure

(->hash v)  hash?

  v : any/c
Maps the input data to a hash.

Examples:
> (->hash (hash 'a 1 'b 2))

'#hash((a . 1) (b . 2))

> (->hash (list '(a . 1) '(b . 2)))

'#hash((a . 1) (b . 2))

procedure

(->procedure v)  procedure?

  v : any/c
Maps the input data to a procedure. For inputs that aren’t already procedures, this is equivalent to thunk*.

Examples:
> (->procedure add1)

#<procedure:add1>

> (->procedure 5)

#<procedure:...elation-lib/type.rkt:283:13>

> ((->procedure 5) 'a 'b)

5