Switch utils to Typed Racket.
This commit is contained in:
parent
f62d53ed8f
commit
97d4c18305
2 changed files with 497 additions and 532 deletions
|
@ -1,7 +1,7 @@
|
|||
#lang scribble/manual
|
||||
@(require scribble/example racket/sandbox
|
||||
(for-label typed/racket/base graph
|
||||
(submod "../utils.rkt" typed)
|
||||
"../utils.rkt"
|
||||
(only-in typed/graph Graph)
|
||||
(only-in racket/set set)
|
||||
(only-in racket/stream stream->list stream-take)))
|
||||
|
@ -14,20 +14,11 @@ This module defines miscellaneous utilities, supporting the other modules of
|
|||
the package: evaluating sexps, manipulating lists,
|
||||
@hyperlink["https://orgmode.org/"]{Org-mode} interoperability, etc.
|
||||
|
||||
@bold{Note:} I am currently migrating this module to Typed Racket.
|
||||
This documentation only lists the functions and the types which have already
|
||||
been converted. However, the typed part is currently hidden in an untyped
|
||||
module, so you cannot yet use the types directly.
|
||||
|
||||
@bold{TODO:} Hyperlinks are currently broken in this document because it
|
||||
actually documents a submodule. Fix them once the migration to Typed Racket
|
||||
has reached a fixed point.
|
||||
|
||||
@(define utils-evaluator
|
||||
(parameterize ([sandbox-output 'string]
|
||||
[sandbox-error-output 'string]
|
||||
[sandbox-memory-limit 50])
|
||||
(make-evaluator 'typed/racket #:requires '((submod "utils.rkt" typed)))))
|
||||
(make-evaluator 'typed/racket #:requires '("utils.rkt"))))
|
||||
|
||||
@section{Base types}
|
||||
|
||||
|
|
276
utils.rkt
276
utils.rkt
|
@ -1,20 +1,9 @@
|
|||
#lang racket
|
||||
#lang typed/racket
|
||||
|
||||
;;; dds/utils
|
||||
|
||||
;;; Various utilities.
|
||||
|
||||
(require
|
||||
graph
|
||||
(require typed/graph typed/rackunit typed-compose typed/racket/stream
|
||||
(for-syntax syntax/parse racket/list))
|
||||
|
||||
;;; Typed section.
|
||||
|
||||
(module typed typed/racket
|
||||
(require typed/graph typed/rackunit typed-compose typed/racket/stream
|
||||
(for-syntax syntax/parse racket/list))
|
||||
|
||||
(provide
|
||||
(provide
|
||||
Variable VariableMapping GeneralPair
|
||||
|
||||
eval-with eval1-with auto-hash-ref/explicit auto-hash-ref/:
|
||||
|
@ -30,21 +19,21 @@
|
|||
|
||||
variable-mapping?)
|
||||
|
||||
(define-type Variable Symbol)
|
||||
(define-type (VariableMapping A) (Immutable-HashTable Variable A))
|
||||
(define-type Variable Symbol)
|
||||
(define-type (VariableMapping A) (Immutable-HashTable Variable A))
|
||||
|
||||
(: eval-with (-> (VariableMapping Any) Any AnyValues))
|
||||
(define (eval-with ht expr)
|
||||
(: eval-with (-> (VariableMapping Any) Any AnyValues))
|
||||
(define (eval-with ht expr)
|
||||
(parameterize ([current-namespace (make-base-namespace)])
|
||||
(for ([(x val) (in-hash ht)]) (namespace-set-variable-value! x val))
|
||||
(eval expr)))
|
||||
|
||||
(: eval1-with (-> (VariableMapping Any) Any Any))
|
||||
(define (eval1-with ht expr)
|
||||
(: eval1-with (-> (VariableMapping Any) Any Any))
|
||||
(define (eval1-with ht expr)
|
||||
(call-with-values (λ () (eval-with ht expr))
|
||||
(λ args (car args))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "eval-with"
|
||||
(check-equal? (eval1-with (hash 'a 1 'b 2) '(+ a b 1))
|
||||
4)
|
||||
|
@ -53,14 +42,14 @@
|
|||
(check-equal? (eval1-with ht expr)
|
||||
4)))
|
||||
|
||||
(define-syntax (auto-hash-ref/explicit stx)
|
||||
(define-syntax (auto-hash-ref/explicit stx)
|
||||
(syntax-parse stx
|
||||
[(_ (ht:id keys:id ...) body:expr)
|
||||
#`(let #,(for/list ([key (syntax->list #'(keys ...))])
|
||||
`[,key (hash-ref ,#'ht ',key)])
|
||||
body)]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "auto-hash-ref/explicit"
|
||||
(define mytable #hash((a . 3) (b . 4)))
|
||||
(check-equal? (auto-hash-ref/explicit (mytable b a)
|
||||
|
@ -71,8 +60,8 @@
|
|||
(and (not a) b))
|
||||
#f)))
|
||||
|
||||
;;; Helper functions for auto-hash-ref/:.
|
||||
(begin-for-syntax
|
||||
;;; Helper functions for auto-hash-ref/:.
|
||||
(begin-for-syntax
|
||||
(define (colon? s)
|
||||
(and (symbol? s)
|
||||
(eq? (string-ref (symbol->string s) 0) #\:)))
|
||||
|
@ -85,7 +74,7 @@
|
|||
(define (strip-colon s)
|
||||
(string->symbol (substring (symbol->string s) 1))))
|
||||
|
||||
(define-syntax (auto-hash-ref/: stx)
|
||||
(define-syntax (auto-hash-ref/: stx)
|
||||
(syntax-parse stx
|
||||
[(_ ht:id body:expr)
|
||||
(define colons (collect-colons (syntax->datum stx)))
|
||||
|
@ -94,7 +83,7 @@
|
|||
(with-syntax ([bindings-stx (datum->syntax stx bindings)])
|
||||
#'(let bindings-stx body))]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "auto-hash-ref/:"
|
||||
(define ht1 #hash((x . #t) (y . #t) (t . #f)))
|
||||
(define z #t)
|
||||
|
@ -105,8 +94,8 @@
|
|||
(check-equal? (auto-hash-ref/: ht2 (+ :a (* 2 :b)))
|
||||
5)))
|
||||
|
||||
(: extract-symbols (-> Any (Listof Symbol)))
|
||||
(define (extract-symbols form)
|
||||
(: extract-symbols (-> Any (Listof Symbol)))
|
||||
(define (extract-symbols form)
|
||||
(: extract-rec (-> Any (Listof Any)))
|
||||
(define (extract-rec form)
|
||||
(match form
|
||||
|
@ -118,93 +107,93 @@
|
|||
[else '()]))
|
||||
(cast (extract-rec form) (Listof Symbol)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "extract-symbols"
|
||||
(check-equal? (extract-symbols '(1 (2 3) x (y z 3)))
|
||||
'(x y z))))
|
||||
|
||||
(: any->string (-> Any String))
|
||||
(define (any->string x)
|
||||
(: any->string (-> Any String))
|
||||
(define (any->string x)
|
||||
(with-output-to-string (λ () (display x))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "any->string"
|
||||
(check-equal? (any->string 'a) "a")
|
||||
(check-equal? (any->string '(a 1 (x y))) "(a 1 (x y))")
|
||||
(check-equal? (any->string "hello") "hello")))
|
||||
|
||||
(: stringify-variable-mapping (-> (VariableMapping Any) (VariableMapping String)))
|
||||
(define (stringify-variable-mapping ht)
|
||||
(: stringify-variable-mapping (-> (VariableMapping Any) (VariableMapping String)))
|
||||
(define (stringify-variable-mapping ht)
|
||||
(for/hash : (VariableMapping String)
|
||||
([(key val) (in-hash ht)]) (values key (any->string val))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "stringify-variable-mapping"
|
||||
(define mp (stringify-variable-mapping #hash((a . (and a b)) (b . (not b)))))
|
||||
(check-equal? (hash-ref mp 'a) "(and a b)")
|
||||
(check-equal? (hash-ref mp 'b) "(not b)")))
|
||||
|
||||
(: string->any (-> String Any))
|
||||
(define (string->any str)
|
||||
(: string->any (-> String Any))
|
||||
(define (string->any str)
|
||||
(with-input-from-string str (λ () (read))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "string->any"
|
||||
(check-equal? (string->any "(or b (not a))") '(or b (not a)))
|
||||
(check-equal? (string->any "14") 14)))
|
||||
|
||||
;;; Given a sexp, converts all "#f" to #f and "#t" to #t.
|
||||
;;;
|
||||
;;; When I read Org-mode tables, I pump them through a call to the
|
||||
;;; prin1 because the Elisp sexps seems incompatible with Racket.
|
||||
;;; On the other hand, Racket Booleans seem to upset Elisp a little,
|
||||
;;; so prin1 wraps them in additional double quotes. This function
|
||||
;;; removes those quotes.
|
||||
(: handle-org-booleans (-> Any Any))
|
||||
(define/match (handle-org-booleans datum)
|
||||
;;; Given a sexp, converts all "#f" to #f and "#t" to #t.
|
||||
;;;
|
||||
;;; When I read Org-mode tables, I pump them through a call to the
|
||||
;;; prin1 because the Elisp sexps seems incompatible with Racket.
|
||||
;;; On the other hand, Racket Booleans seem to upset Elisp a little,
|
||||
;;; so prin1 wraps them in additional double quotes. This function
|
||||
;;; removes those quotes.
|
||||
(: handle-org-booleans (-> Any Any))
|
||||
(define/match (handle-org-booleans datum)
|
||||
[("#t") #t]
|
||||
[("#f") #f]
|
||||
[((? list?)) (map handle-org-booleans datum)]
|
||||
[ (_) datum])
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "handle-org-booleans"
|
||||
(check-equal? (handle-org-booleans "#t") #t)
|
||||
(check-equal? (handle-org-booleans "#f") #f)
|
||||
(check-equal? (handle-org-booleans '("#t" "#f")) '(#t #f))
|
||||
(check-equal? (handle-org-booleans "t") "t")))
|
||||
|
||||
(: map-sexp (-> (-> Any Any) Any Any))
|
||||
(define (map-sexp func sexp)
|
||||
(: map-sexp (-> (-> Any Any) Any Any))
|
||||
(define (map-sexp func sexp)
|
||||
(match sexp
|
||||
[(? list?) (map ((curry map-sexp) func) sexp)]
|
||||
[datum (func datum)]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "map-sexp"
|
||||
(check-equal? (map-sexp (λ (x) (add1 (cast x Number))) '(1 2 (4 10) 3))
|
||||
'(2 3 (5 11) 4))))
|
||||
|
||||
(: read-org-sexp (-> String Any))
|
||||
(define read-org-sexp
|
||||
(: read-org-sexp (-> String Any))
|
||||
(define read-org-sexp
|
||||
(compose ((curry map-sexp) (match-lambda
|
||||
[(and (? string?) str) (string->any str)]
|
||||
[x x]))
|
||||
string->any))
|
||||
(define unorg read-org-sexp)
|
||||
(define unorg read-org-sexp)
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "read-org-sexp"
|
||||
(check-equal? (read-org-sexp "((\"a\" \"(and a b)\") (\"b\" \"(or b (not a))\"))")
|
||||
'((a (and a b)) (b (or b (not a)))))
|
||||
(check-equal? (unorg "(#t \"#t\" \"#t \" '(1 2 \"#f\"))")
|
||||
'(#t #t #t '(1 2 #f)))))
|
||||
|
||||
(define-type (GeneralPair A B) (U (Pair A B) (List A B)))
|
||||
(define-type (GeneralPair A B) (U (Pair A B) (List A B)))
|
||||
|
||||
(: unstringify-pairs (-> (Listof (GeneralPair String Any))
|
||||
(: unstringify-pairs (-> (Listof (GeneralPair String Any))
|
||||
(Listof (GeneralPair Symbol Any))))
|
||||
(define (unstringify-pairs pairs)
|
||||
(define (unstringify-pairs pairs)
|
||||
(for/list ([p pairs])
|
||||
(match p
|
||||
[(list key val)
|
||||
|
@ -216,15 +205,15 @@
|
|||
(string->any val)
|
||||
val))])))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "unstringify-pairs"
|
||||
(check-equal? (unstringify-pairs '(("a" . "1") ("b" . "(and a (not b))")))
|
||||
'((a . 1) (b . (and a (not b)))))
|
||||
(check-equal? (unstringify-pairs '(("a" . 1) ("b" . "(and a (not b))")))
|
||||
'((a . 1) (b . (and a (not b)))))))
|
||||
|
||||
(: read-org-variable-mapping (-> String (VariableMapping Any)))
|
||||
(define read-org-variable-mapping
|
||||
(: read-org-variable-mapping (-> String (VariableMapping Any)))
|
||||
(define read-org-variable-mapping
|
||||
(multi-compose
|
||||
(λ ([pairs : (Listof (Pair Symbol Any))])
|
||||
(make-immutable-hash pairs))
|
||||
|
@ -232,10 +221,10 @@
|
|||
(unstringify-pairs (cast sexp (Listof (GeneralPair String Any)))))
|
||||
string->any))
|
||||
|
||||
;;; A synonym for read-org-variable-mapping.
|
||||
(define unorgv read-org-variable-mapping)
|
||||
;;; A synonym for read-org-variable-mapping.
|
||||
(define unorgv read-org-variable-mapping)
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "read-org-variable-mapping"
|
||||
(define m1 (read-org-variable-mapping "((\"a\" \"(and a b)\") (\"b\" \"(or b (not a))\"))"))
|
||||
(define m2 (read-org-variable-mapping "((\"a\" . \"(and a b)\") (\"b\" . \"(or b (not a))\"))"))
|
||||
|
@ -247,61 +236,61 @@
|
|||
(check-equal? (hash-ref m2 'b) '(or b (not a)))
|
||||
(check-equal? (hash-ref m3 'b) '(or b (not a)))))
|
||||
|
||||
(: read-symbol-list (-> String (Listof Symbol)))
|
||||
(define (read-symbol-list str)
|
||||
(: read-symbol-list (-> String (Listof Symbol)))
|
||||
(define (read-symbol-list str)
|
||||
(cast (string->any (string-append "(" str ")")) (Listof Symbol)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "read-symbol-list"
|
||||
(check-equal? (read-symbol-list "a b c") '(a b c))))
|
||||
|
||||
(: drop-first-last (-> String String))
|
||||
(define (drop-first-last str)
|
||||
(: drop-first-last (-> String String))
|
||||
(define (drop-first-last str)
|
||||
(substring str 1 (- (string-length str) 1)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "drop-first-last"
|
||||
(check-equal? (drop-first-last "(a b)") "a b")))
|
||||
|
||||
(: list-sets->list-strings (-> (Listof (Setof Any)) (Listof String)))
|
||||
(define (list-sets->list-strings lst)
|
||||
(: list-sets->list-strings (-> (Listof (Setof Any)) (Listof String)))
|
||||
(define (list-sets->list-strings lst)
|
||||
(map (multi-compose drop-first-last
|
||||
any->string
|
||||
(λ ([x : (Setof Any)])
|
||||
(set->list x))) lst))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "list-sets->list-strings"
|
||||
(check-equal? (list-sets->list-strings (list (set 'x 'y) (set 'z) (set) (set 't)))
|
||||
'("x y" "z" "" "t"))))
|
||||
|
||||
(: pretty-print-set (-> (Setof Any) String))
|
||||
(define (pretty-print-set s)
|
||||
(: pretty-print-set (-> (Setof Any) String))
|
||||
(define (pretty-print-set s)
|
||||
(string-join (sort (set-map s any->string) string<?)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "pretty-print-set"
|
||||
(check-equal? (pretty-print-set (set 'a 'b 1)) "1 a b")))
|
||||
|
||||
(: pretty-print-set-sets (-> (Setof (Setof Any)) String))
|
||||
(define (pretty-print-set-sets ms)
|
||||
(: pretty-print-set-sets (-> (Setof (Setof Any)) String))
|
||||
(define (pretty-print-set-sets ms)
|
||||
(string-join (for/list ([m ms]) : (Listof String)
|
||||
(format "{~a}" (pretty-print-set m))) ""))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "pretty-print-set-sets"
|
||||
(check-equal? (pretty-print-set-sets (set (set 'a 'b) (set 'c))) "{a b}{c}")))
|
||||
|
||||
(define dotit (compose display graphviz))
|
||||
(define dotit (compose display graphviz))
|
||||
|
||||
(: update-vertices/unweighted (-> Graph (-> Any Any) Graph))
|
||||
(define (update-vertices/unweighted gr func)
|
||||
(: update-vertices/unweighted (-> Graph (-> Any Any) Graph))
|
||||
(define (update-vertices/unweighted gr func)
|
||||
(unweighted-graph/directed
|
||||
(for/list ([e (in-edges gr)])
|
||||
(match-let ([(list u v) e])
|
||||
(list (func u) (func v))))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "update-vertices/unweighted"
|
||||
(define gr1 (directed-graph '((a b) (b c))))
|
||||
(define gr2 (undirected-graph '((a b) (b c))))
|
||||
|
@ -325,8 +314,8 @@
|
|||
(check-true (has-edge? new-gr2 'bb 'cc))
|
||||
(check-true (has-edge? new-gr2 'cc 'bb))))
|
||||
|
||||
(: update-graph (->* (Graph) (#:v-func (-> Any Any) #:e-func (-> Any Any)) Graph))
|
||||
(define (update-graph gr #:v-func [v-func identity] #:e-func [e-func identity])
|
||||
(: update-graph (->* (Graph) (#:v-func (-> Any Any) #:e-func (-> Any Any)) Graph))
|
||||
(define (update-graph gr #:v-func [v-func identity] #:e-func [e-func identity])
|
||||
(cond
|
||||
[(unweighted-graph? gr)
|
||||
(unweighted-graph/directed
|
||||
|
@ -340,7 +329,7 @@
|
|||
(list (e-func (edge-weight gr u v))
|
||||
(v-func u) (v-func v)))))]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "update-graph"
|
||||
(define gr1 (directed-graph '((a b) (b c))))
|
||||
(define gr2 (undirected-graph '((a b) (b c))))
|
||||
|
@ -375,9 +364,9 @@
|
|||
(check-equal? (edge-weight new-gr3 'aa 'bb) 20)
|
||||
(check-equal? (edge-weight new-gr3 'bb 'cc) 22)))
|
||||
|
||||
(: collect-by-key (All (a b) (-> (Listof a) (Listof b)
|
||||
(: collect-by-key (All (a b) (-> (Listof a) (Listof b)
|
||||
(Values (Listof a) (Listof (Listof b))))))
|
||||
(define (collect-by-key keys vals)
|
||||
(define (collect-by-key keys vals)
|
||||
(for/fold ([ht : (HashTable a (Listof b))
|
||||
(make-immutable-hash)]
|
||||
#:result (values (hash-keys ht) (hash-values ht)))
|
||||
|
@ -385,48 +374,48 @@
|
|||
[l vals])
|
||||
((inst hash-update a (Listof b)) ht e (λ (ls) (cons l ls)) (λ () empty))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "collect-by-key"
|
||||
(define-values (e1 l1) (collect-by-key '((1 2) (1 3)) '(a b)))
|
||||
(define-values (e2 l2) (collect-by-key '((1 2) (1 2)) '(a b)))
|
||||
(check-equal? e1 '((1 2) (1 3))) (check-equal? l1 '((a) (b)))
|
||||
(check-equal? e2 '((1 2))) (check-equal? l2 '((b a)))))
|
||||
|
||||
(: collect-by-key/sets (All (a b) (-> (Listof a) (Listof b)
|
||||
(: collect-by-key/sets (All (a b) (-> (Listof a) (Listof b)
|
||||
(Values (Listof a) (Listof (Setof b))))))
|
||||
(define (collect-by-key/sets edges labels)
|
||||
(define (collect-by-key/sets edges labels)
|
||||
(define-values (es ls) (collect-by-key edges labels))
|
||||
(values es ((inst map (Setof b) (Listof b)) list->set ls)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "collect-by-key/sets"
|
||||
(define-values (e3 l3) (collect-by-key/sets '(a b a) '(1 2 1)))
|
||||
(check-equal? e3 '(b a)) (check-equal? l3 (list (set 2) (set 1)))))
|
||||
|
||||
;;; Converts the values of a hash table from lists to sets.
|
||||
(: ht-values/list->set (All (a b) (-> (HashTable a (Listof b)) (HashTable a (Setof b)))))
|
||||
(define (ht-values/list->set ht)
|
||||
;;; Converts the values of a hash table from lists to sets.
|
||||
(: ht-values/list->set (All (a b) (-> (HashTable a (Listof b)) (HashTable a (Setof b)))))
|
||||
(define (ht-values/list->set ht)
|
||||
(for/hash ([(k v) (in-hash ht)]) : (HashTable a (Setof b))
|
||||
(values k (list->set v))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "ht-values/list->set"
|
||||
(check-equal? (ht-values/list->set #hash((a . (1 1))))
|
||||
(hash 'a (set 1)))))
|
||||
|
||||
;; TODO: Remove after Racket 8.4.
|
||||
(: hash->list/ordered (All (a b) (-> (HashTable a b) (Listof (Pairof a b)))))
|
||||
(define (hash->list/ordered ht)
|
||||
;; TODO: Remove after Racket 8.4.
|
||||
(: hash->list/ordered (All (a b) (-> (HashTable a b) (Listof (Pairof a b)))))
|
||||
(define (hash->list/ordered ht)
|
||||
((inst hash-map a b (Pairof a b)) ht cons #t))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "hash->list/ordered"
|
||||
(check-equal? (hash->list/ordered #hash((b . 1) (a . 1)))
|
||||
'((a . 1) (b . 1)))))
|
||||
|
||||
(: multi-split-at (All (a) (-> (Listof (Listof a)) Integer
|
||||
(: multi-split-at (All (a) (-> (Listof (Listof a)) Integer
|
||||
(Values (Listof (Listof a)) (Listof (Listof a))))))
|
||||
(define (multi-split-at lists pos)
|
||||
(define (multi-split-at lists pos)
|
||||
(for/fold ([lefts : (Listof (Listof a)) '()]
|
||||
[rights : (Listof (Listof a)) '()]
|
||||
#:result (values (reverse lefts) (reverse rights)))
|
||||
|
@ -434,34 +423,34 @@
|
|||
(define-values (left right) ((inst split-at a) lst pos))
|
||||
(values (cons left lefts) (cons right rights))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "multi-split-at"
|
||||
(define-values (l1 l2) (multi-split-at '((1 2 3) (a b c)) 2))
|
||||
(check-equal? l1 '((1 2) (a b))) (check-equal? l2 '((3) (c)))))
|
||||
|
||||
;; https://racket.discourse.group/t/get-to-type-apply-in-parallel-lst/683
|
||||
;;
|
||||
;; Same thread: (apply ((curry map) list) lsts), however I don't
|
||||
;; feel like typing this right now (2022-02-18).
|
||||
(: lists-transpose (All (a ...) (-> (List (Listof a) ... a) (Listof (List a ... a)))))
|
||||
(define (lists-transpose lists)
|
||||
;; https://racket.discourse.group/t/get-to-type-apply-in-parallel-lst/683
|
||||
;;
|
||||
;; Same thread: (apply ((curry map) list) lsts), however I don't
|
||||
;; feel like typing this right now (2022-02-18).
|
||||
(: lists-transpose (All (a ...) (-> (List (Listof a) ... a) (Listof (List a ... a)))))
|
||||
(define (lists-transpose lists)
|
||||
(sequence->list (in-values-sequence (apply in-parallel lists))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "lists-transpose"
|
||||
(check-equal? (lists-transpose '((1 2) (a b))) '((1 a) (2 b)))))
|
||||
|
||||
(: in-random (case->
|
||||
(: in-random (case->
|
||||
(-> (Sequenceof Flonum))
|
||||
(-> Integer (Sequenceof Nonnegative-Fixnum))
|
||||
(-> Integer Integer (Sequenceof Nonnegative-Fixnum))))
|
||||
(define in-random
|
||||
(define in-random
|
||||
(case-lambda
|
||||
[() (stream-cons (random) (in-random))]
|
||||
[(k) (stream-cons (random k) (in-random k))]
|
||||
[(min max) (stream-cons (random min max) (in-random min max))]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "in-random"
|
||||
(random-seed 1)
|
||||
(check-equal? (stream->list (stream-take (in-random 100) 10))
|
||||
|
@ -480,8 +469,8 @@
|
|||
0.21646500425988832
|
||||
0.15188352823997242))))
|
||||
|
||||
(: cartesian-product-2/stream (All (a b) (-> (Sequenceof a) (Sequenceof b) (Sequenceof (Pair a b)))))
|
||||
(define (cartesian-product-2/stream s1 s2)
|
||||
(: cartesian-product-2/stream (All (a b) (-> (Sequenceof a) (Sequenceof b) (Sequenceof (Pair a b)))))
|
||||
(define (cartesian-product-2/stream s1 s2)
|
||||
(: cp2-store (All (a b) (-> (Sequenceof a) (Sequenceof b) (Sequenceof b)
|
||||
(Sequenceof (Pair a b)))))
|
||||
;; The recursive implementation using s2-store as an accumulator.
|
||||
|
@ -497,7 +486,7 @@
|
|||
(cp2-store s1 (stream-rest s2) s2-store))]))
|
||||
(cp2-store s1 s2 s2))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "cartesian-product-2/stream"
|
||||
(check-equal? (stream->list (cartesian-product-2/stream (in-range 1 5) '(a b)))
|
||||
'((1 . a) (1 . b) (2 . a) (2 . b) (3 . a) (3 . b) (4 . a) (4 . b)))
|
||||
|
@ -505,13 +494,13 @@
|
|||
(stream->list (stream-take (cartesian-product-2/stream '(a b) (in-naturals)) 10))
|
||||
'((a . 0) (a . 1) (a . 2) (a . 3) (a . 4) (a . 5) (a . 6) (a . 7) (a . 8) (a . 9)))))
|
||||
|
||||
(: cartesian-product/stream (All (a) (-> (Listof (Sequenceof a)) (Sequenceof (Listof a)))))
|
||||
(define (cartesian-product/stream ss)
|
||||
(: cartesian-product/stream (All (a) (-> (Listof (Sequenceof a)) (Sequenceof (Listof a)))))
|
||||
(define (cartesian-product/stream ss)
|
||||
(for/foldr ([prod (stream (list))])
|
||||
([s (in-list ss)])
|
||||
(cartesian-product-2/stream s prod)))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "cartesian-product/stream"
|
||||
(check-equal? (stream->list (cartesian-product/stream '())) '(()))
|
||||
(check-equal? (stream->list (cartesian-product/stream '((a b c))))
|
||||
|
@ -530,57 +519,42 @@
|
|||
(2 5 a)
|
||||
(2 5 b)))))
|
||||
|
||||
(: boolean-power (-> Integer (Listof (Listof Boolean))))
|
||||
(define (boolean-power n)
|
||||
(: boolean-power (-> Integer (Listof (Listof Boolean))))
|
||||
(define (boolean-power n)
|
||||
(apply cartesian-product (make-list n '(#f #t))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "boolean-power"
|
||||
(check-equal? (boolean-power 2) '((#f #f) (#f #t) (#t #f) (#t #t)))))
|
||||
|
||||
(: boolean-power/stream (-> Integer (Sequenceof (Listof Boolean))))
|
||||
(define (boolean-power/stream n) (cartesian-product/stream (make-list n '(#f #t))))
|
||||
(: boolean-power/stream (-> Integer (Sequenceof (Listof Boolean))))
|
||||
(define (boolean-power/stream n) (cartesian-product/stream (make-list n '(#f #t))))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "boolean-power/stream"
|
||||
(check-equal? (stream->list (boolean-power/stream 2)) '((#f #f) (#f #t) (#t #f) (#t #t)))))
|
||||
|
||||
(: any->01 (-> Any (U Zero One)))
|
||||
(define (any->01 x)
|
||||
(: any->01 (-> Any (U Zero One)))
|
||||
(define (any->01 x)
|
||||
(if x 1 0))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "any->01"
|
||||
(check-equal? (any->01 #t) 1)
|
||||
(check-equal? (any->01 #f) 0)))
|
||||
|
||||
(: 01->boolean (-> (U Zero One) Boolean))
|
||||
(define (01->boolean x)
|
||||
(: 01->boolean (-> (U Zero One) Boolean))
|
||||
(define (01->boolean x)
|
||||
(case x [(0) #f] [else #t]))
|
||||
|
||||
(module+ test
|
||||
(module+ test
|
||||
(test-case "01->boolean"
|
||||
(check-equal? (01->boolean 0) #f)
|
||||
(check-equal? (01->boolean 1) #t)))
|
||||
|
||||
;; TODO: Remove when the other modules are converted to Typed Racket
|
||||
;; and these contracts are not needed any more.
|
||||
;; TODO: Remove when the other modules are converted to Typed Racket
|
||||
;; and these contracts are not needed any more.
|
||||
|
||||
(: variable-mapping? (-> Any Boolean : HashTableTop))
|
||||
(define (variable-mapping? dict)
|
||||
(: variable-mapping? (-> Any Boolean : HashTableTop))
|
||||
(define (variable-mapping? dict)
|
||||
(hash? dict))
|
||||
)
|
||||
|
||||
(require 'typed)
|
||||
(provide eval-with eval1-with auto-hash-ref/explicit auto-hash-ref/:
|
||||
extract-symbols any->string stringify-variable-mapping string->any
|
||||
map-sexp read-org-sexp unorg unstringify-pairs
|
||||
read-org-variable-mapping unorgv read-symbol-list drop-first-last
|
||||
list-sets->list-strings pretty-print-set pretty-print-set-sets
|
||||
update-vertices/unweighted update-graph dotit collect-by-key
|
||||
collect-by-key/sets ht-values/list->set hash->list/ordered
|
||||
multi-split-at lists-transpose in-random cartesian-product-2/stream
|
||||
cartesian-product/stream boolean-power boolean-power/stream any->01
|
||||
01->boolean
|
||||
|
||||
variable-mapping?)
|
||||
|
|
Loading…
Reference in a new issue