diff --git a/scribblings/utils.scrbl b/scribblings/utils.scrbl index cc63de3..2634e0b 100644 --- a/scribblings/utils.scrbl +++ b/scribblings/utils.scrbl @@ -6,6 +6,15 @@ (only-in racket/set set) (only-in racket/stream stream->list stream-take))) +@(define utils-evaluator + (parameterize ([sandbox-output 'string] + [sandbox-error-output 'string] + [sandbox-memory-limit 50]) + (make-evaluator 'typed/racket #:requires '("utils.rkt")))) + +@(define-syntax-rule (ex . args) + (examples #:eval utils-evaluator . args)) + @title[#:tag "utils"]{dds/utils: Various Utilities} @defmodule[dds/utils] @@ -14,12 +23,6 @@ This module defines miscellaneous utilities, supporting the other modules of the package: evaluating sexps, manipulating lists, @hyperlink["https://orgmode.org/"]{Org-mode} interoperability, etc. -@(define utils-evaluator - (parameterize ([sandbox-output 'string] - [sandbox-error-output 'string] - [sandbox-memory-limit 50]) - (make-evaluator 'typed/racket #:requires '("utils.rkt")))) - @section{Base types} @defidform[Variable]{ @@ -50,7 +53,7 @@ typing} either via a direct @racket[if] check using a predicate, or using @racket[assert] that the type of @racket[expr] is @racket[type]. -@examples[#:eval utils-evaluator +@ex[ (define some-number : Any 1) (assert-type some-number Integer) (assert-type some-number Positive-Integer) @@ -68,7 +71,7 @@ explicit @racket[hash-ref] calls. Temporarily injects the mappings from the given hash table as bindings in a namespace including @racket[racket/base] and then evaluates the expression. -@examples[#:eval utils-evaluator +@ex[ (let ([ht (hash 'a 1 'b 1)]) (eval-with ht '(+ b a 1))) ] @@ -77,7 +80,7 @@ The local bindings from the current lexical scope are not conserved. Therefore, the following outputs an error about a missing identifier: -@examples[#:eval utils-evaluator +@ex[ (eval:error (let ([ht (hash 'a 1 'b 1)] [z 1]) @@ -89,7 +92,7 @@ missing identifier: Like @racket[eval-with], but returns only the first value computed by @racket[expr]. -@examples[#:eval utils-evaluator +@ex[ (let ([ht (hash 'a 1 'b 1)]) (eval1-with ht '(+ b a 1))) ]} @@ -101,7 +104,7 @@ Given a @racket[VariableMapping] and a sequence of symbols, binds these symbols to the values they are associated with in the hash table, then puts the body in the context of these bindings. -@examples[#:eval utils-evaluator +@ex[ (define env #hash((a . 1) (b . 2))) (auto-hash-ref/explicit (env a b) (+ a (* 2 b))) ] @@ -117,7 +120,7 @@ Given an expression and a @racket[VariableMapping], looks up the symbols with a leading semicolon and binds them to the value they are associated with in the hash table. -@examples[#:eval utils-evaluator +@ex[ (define env #hash((a . 1) (b . 2))) (auto-hash-ref/: env (+ :a (* 2 :b))) ] @@ -136,7 +139,7 @@ Note that only one expression can be supplied in the body. Produces a list of symbols appearing in the quoted expression passed in the first argument. -@examples[#:eval utils-evaluator +@ex[ (extract-symbols '(1 (2 3) x (y z 3))) ] @@ -159,7 +162,7 @@ for examples of usage. Converts any value to string by calling @racket[display] on it and capturing the result in a string. -@examples[#:eval utils-evaluator +@ex[ (any->string '(a 1 (x y))) ]} @@ -167,7 +170,7 @@ the result in a string. Converts all the values of a @racket[VariableMapping] to string. -@examples[#:eval utils-evaluator +@ex[ (stringify-variable-mapping (hash 'a '(and a b) 'b '(not b))) ]} @@ -175,7 +178,7 @@ Converts all the values of a @racket[VariableMapping] to string. Reads any value from string. -@examples[#:eval utils-evaluator +@ex[ (string->any "(or b (not a))") ]} @@ -188,7 +191,7 @@ a list. every non-list element of @racket[sexp]. If this is not the case, a contract violation for func will be generated. -@examples[#:eval utils-evaluator +@ex[ (map-sexp (λ (x) (add1 (cast x Number))) '(1 2 (4 10) 3)) ]} @@ -199,7 +202,7 @@ Reads a @racket[sexp] from a string produced by Org-mode for a named table. @racket[unorg] is a shortcut for @racket[read-org-sexp]. -@examples[#:eval utils-evaluator +@ex[ (unorg "(#t \"#t\" \"#t \" '(1 2 \"#f\"))") ]} @@ -216,7 +219,7 @@ Given a list of pairs of strings and some other values (possibly strings), converts the first element of each pair to a string, and reads the second element with @racket[string->any] or keeps it as is if it is not a string. -@examples[#:eval utils-evaluator +@ex[ (unstringify-pairs '(("a" . 1) ("b" . "(and a (not b))"))) ]} @@ -228,7 +231,7 @@ produces from tables. @racket[unorgv] is a synonym of @racket[read-org-variable-mapping]. -@examples[#:eval utils-evaluator +@ex[ (read-org-variable-mapping "((\"a\" . \"(and a b)\") (\"b\" . \"(or b (not a))\"))") ]} @@ -237,7 +240,7 @@ produces from tables. Reads a list of symbols from a string. -@examples[#:eval utils-evaluator +@ex[ (read-symbol-list "a b c") ]} @@ -247,7 +250,7 @@ Removes the first and the last symbol of a given string. Useful for removing the parentheses in string representations of lists. -@examples[#:eval utils-evaluator +@ex[ (drop-first-last "(a b)") ]} @@ -256,7 +259,7 @@ Useful for removing the parentheses in string representations of lists. Converts a list of sets of symbols to a list of strings containing those symbols. -@examples[#:eval utils-evaluator +@ex[ (list-sets->list-strings (list (set 'x 'y) (set 'z) (set) (set 't))) ]} @@ -266,7 +269,7 @@ those symbols. Pretty prints a set by listing its elements in alphabetic order. -@examples[#:eval utils-evaluator +@ex[ (pretty-print-set (set 'a 'b 1)) ]} @@ -277,7 +280,7 @@ Pretty-prints a set of sets of symbols. Typically used for pretty-printing the annotations on the edges of a state graph. -@examples[#:eval utils-evaluator +@ex[ (pretty-print-set-sets (set (set 'a 'b) (set 'c))) ]} @@ -285,7 +288,7 @@ a state graph. All examples in this section depend on @racket[typed/graph]: -@examples[#:eval utils-evaluator +@ex[ (require typed/graph) ] @@ -293,7 +296,7 @@ All examples in this section depend on @racket[typed/graph]: Typesets the graph via @racket[graphviz] and @racket[display]s it. -@examples[#:eval utils-evaluator +@ex[ (dotit (weighted-graph/directed '((1 a b) (2 b c)))) ]} @@ -309,7 +312,7 @@ may be called multiple times for the same vertex. This function does not rely on @racket[rename-vertex!], so it can be used to permute vertex labels. -@examples[#:eval utils-evaluator +@ex[ (define g (directed-graph '((a b) (b c)))) (define (double-labels [x : Any]) (define x-str (symbol->string (cast x Symbol))) @@ -329,7 +332,7 @@ functions. If @racket[graph] is an weighted graph, the result is a weighted graph. If @racket[graph] is an unweighted graph, the result is an unweighted graph. -@examples[#:eval utils-evaluator +@ex[ (define g (weighted-graph/directed '((10 a b) (11 b c)))) (define (double-labels [x : Any]) (define x-str (symbol->string (cast x Symbol))) @@ -351,7 +354,7 @@ a list containing the corresponding list of values. If @racket[keys] can be treated as edges (i.e. pairs of vertices), the results produced by this function are suitable for graph constructors. -@examples[#:eval utils-evaluator +@ex[ (collect-by-key '(a b a) '(1 2 3)) ]} @@ -361,7 +364,7 @@ produced by this function are suitable for graph constructors. Like @racket[collect-by-key], but produce a list of sets instead of a list of lists. -@examples[#:eval utils-evaluator +@ex[ (collect-by-key/sets '(a b a) '(1 2 3)) ]} @@ -370,7 +373,7 @@ of lists. Converts the values of a hash table from lists to sets. -@examples[#:eval utils-evaluator +@ex[ (ht-values/list->set #hash((a . (1 1)))) ]} @@ -384,7 +387,7 @@ hash table orders them for @racket[hash-map]. @bold{TODO:} Remove after Typed Racket has caught up with Racket 8.4, in which @racket[hash->list] gets a new optional argument @racket[try-order?]. -@examples[#:eval utils-evaluator +@ex[ (hash->list/ordered #hash((b . 1) (a . 1))) ]} @@ -396,7 +399,7 @@ Given a list of lists, splits every single list at the given position, and then returns two lists of lists: one consisting of the first halves, and the one consisting of the second halves. -@examples[#:eval utils-evaluator +@ex[ (multi-split-at '((1 2 3) (a b c)) 2) ]} @@ -409,7 +412,7 @@ the shortest list in @racket[lists]. This function is essentially @racket[in-parallel], wrapped in a couple conversions. -@examples[#:eval utils-evaluator +@ex[ (lists-transpose '((a b) (1 2))) (lists-transpose '((a b) (1 2 3) (#t))) ] @@ -427,7 +430,7 @@ untyped code. @racket[lsts] is a list of rows, in which each row is split in two halves. The function returns the list of the same rows, with the two halves appended. -@examples[#:eval utils-evaluator +@ex[ (append-lists '(((1 2) (a b)) ((3 4) (c d)))) ]} @@ -454,7 +457,7 @@ range @racket[min] to @racket[max]-1.} ] -@examples[#:eval utils-evaluator +@ex[ (require typed/racket/stream) (stream->list (stream-take (in-random) 5)) (stream->list (stream-take (in-random 10) 5)) @@ -471,7 +474,7 @@ Generates a stream containing all the pairs of the elements from @racket[s1] and @racket[s2]. The elements of @racket[s2] are enumerated in order for every element of the @racket[s1], taken in order as well. -@examples[#:eval utils-evaluator +@ex[ (require typed/racket/stream) (stream->list (cartesian-product-2/stream (in-range 1 5) '(a b))) ] @@ -479,7 +482,7 @@ element of the @racket[s1], taken in order as well. The streams can be infinite. If the second stream is infinite, only the first element of @racket[s1] will be enumerated. -@examples[#:eval utils-evaluator +@ex[ (stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10)) ]} @@ -496,7 +499,7 @@ which the streams are enumerated. Union types can be used to build the Cartesian product of streams containing values of different types. -@examples[#:eval utils-evaluator +@ex[ (stream->list (cartesian-product/stream (list (in-range 3) (in-range 4 6) '(a b)))) ]} @@ -507,7 +510,7 @@ values of different types. Returns the @racket[n]-th Cartesian power of the Boolean domain. -@examples[#:eval utils-evaluator +@ex[ (boolean-power 2) ]} @@ -516,7 +519,7 @@ Returns the @racket[n]-th Cartesian power of the Boolean domain. Like @racket[boolean-power], but returns a stream. -@examples[#:eval utils-evaluator +@ex[ (stream->list (boolean-power/stream 2)) ]} @@ -524,7 +527,7 @@ Like @racket[boolean-power], but returns a stream. Converts any non-@racket[#f] value to 1 and @racket[#f] to 0. -@examples[#:eval utils-evaluator +@ex[ (any->01 #t) (any->01 #f) (any->01 'hello) @@ -534,7 +537,7 @@ Converts any non-@racket[#f] value to 1 and @racket[#f] to 0. Converts 0 to @racket[#f] and 1 to @racket[#t]. -@examples[#:eval utils-evaluator +@ex[ (01->boolean 0) (01->boolean 1) ]} @@ -554,6 +557,9 @@ contracts by Typed Racket. [sandbox-memory-limit 50]) (make-evaluator 'racket #:requires '((submod "utils.rkt" untyped))))) +@(define-syntax-rule (ex/untyped . args) + (examples #:eval utils-evaluator/untyped . args)) + @defproc[(lists-transpose [lists (listof (listof any/c))]) (listof (listof any/c))]{ @@ -563,7 +569,7 @@ the shortest list in @racket[lists]. This function is essentially @racket[in-parallel], wrapped in a couple conversions. -@examples[#:eval utils-evaluator/untyped +@ex/untyped[ (lists-transpose '((a b) (1 2))) (lists-transpose '((a b) (1 2 3) (#t))) ]}