3 Type Transformers
(require relation/transform) | package: Relation |
Generic utilities for transforming data into different types.
The type transformers provided by Racket out of the box are type-specific; for instance in order 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. Likewise, 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 convenient interfaces to perform many such 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.
> (->integer "42") 42
> (->integer 3/2) 1
> (->integer 3/2 #:round 'up) 2
> (->integer 3.6 #:round 'nearest) 4
> (->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)) '((a . 1) (c . 3) (b . 2))
> (->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)) '#((a . 1) (c . 3) (b . 2))
procedure
(->generator v return) → generator?
v : any/c return : any/c
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.
> (->generator "apple") (generator #<procedure:generator>)
> (->generator '(97 112 112 108 101)) (generator #<procedure:generator>)
> (->list (->generator (conj (->stream (->generator '(1 2 3))) 4))) '(4 1 2 3)
> (->set "apple") (immutable-custom-set #f '#hash((#\l . #t) (#\p . #t) (#\a . #t) (#\e . #t)))
> (->set '(1 2 2 3 3 3)) (immutable-custom-set #f '#hash((1 . #t) (3 . #t) (2 . #t)))
> (->syntax "apple") #<syntax "apple">
> (->syntax 42) #<syntax 42>
> (->syntax '(+ 1 2)) #<syntax (+ 1 2)>
> (->code "apple") "apple"
> (->code #'42) 42
> (->code #'(+ 1 2)) '(+ 1 2)
> (->code #'(define (square x) (* x x))) '(define (square x) (* x x))
> (eval (->code #'((λ (x) (* x x)) 4))) 16