Sat afternoon
parent
196d9f00f3
commit
6ce38652b7
@ -1,200 +1,28 @@
|
|||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require (only-in racket/list empty? range))
|
(require racket/contract)
|
||||||
(require (only-in racket/format ~a ~v))
|
(require (only-in racket/list empty?))
|
||||||
(require (only-in racket/string string-join))
|
(require (only-in racket/format ~a))
|
||||||
(require (prefix-in williams: (planet williams/describe/describe)))
|
|
||||||
(require racket/date)
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;; Utility functions for readability
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
(provide (all-defined-out))
|
(provide (all-defined-out))
|
||||||
|
|
||||||
; lambda alias
|
;; general way of coercing to string
|
||||||
; won't work as simple define because λ is specially handled in reader
|
(define/contract (as-string x)
|
||||||
(define-syntax-rule (ƒ x ...) (λ x ...))
|
(any/c . -> . string?)
|
||||||
|
|
||||||
(define (describe x)
|
|
||||||
(williams:describe x)
|
|
||||||
x)
|
|
||||||
|
|
||||||
; report the current value of the variable, then return it
|
|
||||||
(define-syntax-rule (report var)
|
|
||||||
(begin
|
|
||||||
(message 'var "=" var)
|
|
||||||
var))
|
|
||||||
|
|
||||||
; debug utilities
|
|
||||||
(define (message . x)
|
|
||||||
(define (zfill s n)
|
|
||||||
(set! s (as-string s))
|
|
||||||
(if (> (string-length s) n)
|
|
||||||
s
|
|
||||||
(string-append (make-string (- n (string-length s)) #\0) s)))
|
|
||||||
|
|
||||||
(define (make-date-string)
|
|
||||||
(define d (current-date))
|
|
||||||
(define df (map (ƒ(x) (zfill x 2)) (list (date-month d)(date-day d)(date-year d)(modulo (date-hour d) 12)(date-minute d)(date-second d)(if (< (date-hour d) 12) "am" "pm"))))
|
|
||||||
|
|
||||||
(apply format "[~a.~a.~a ~a:~a:~a~a]" df))
|
|
||||||
(displayln (string-join `(,(make-date-string) ,@(map (ƒ(x)(if (string? x) x (~v x))) x))) (current-error-port)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define (exists? x)
|
|
||||||
; neither empty nor false
|
|
||||||
(and (not (empty? x)) x))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#|(define (=str . xs)
|
|
||||||
(let ([tester (car xs)])
|
|
||||||
(all (ƒ(x) (equal? tester x)) (map as-string (cdr xs)))))|#
|
|
||||||
|
|
||||||
(define (=str . xs)
|
|
||||||
(let* ([xs (map as-string xs)]
|
|
||||||
[tester (car xs)])
|
|
||||||
(all (ƒ(x) (equal? tester x)) (cdr xs))))
|
|
||||||
|
|
||||||
(define (int x)
|
|
||||||
(cond
|
|
||||||
[(integer? x) x]
|
|
||||||
[(boolean? x) (if x 1 0)]
|
|
||||||
[(real? x) (floor x)]
|
|
||||||
[(string? x) (if (= (len x) 1)
|
|
||||||
(int (car (string->list x))) ; treat as char
|
|
||||||
(int (string->number x)))]
|
|
||||||
[(symbol? x) (int (as-string x))]
|
|
||||||
[(char? x) (char->integer x)]
|
|
||||||
[(empty? x) 0]
|
|
||||||
[(or (list? x) (hash? x) (vector? x)) (len x)]
|
|
||||||
[else (error "Can't convert to integer:" x)]))
|
|
||||||
|
|
||||||
(define (str . x)
|
|
||||||
(string-join (map as-string x) ""))
|
|
||||||
|
|
||||||
(define (len x)
|
|
||||||
(cond
|
(cond
|
||||||
[(list? x) (length x)]
|
|
||||||
[(string? x) (string-length x)]
|
|
||||||
[(symbol? x) (len (as-string x))]
|
|
||||||
[(vector? x) (vector-length x)]
|
|
||||||
[(hash? x) (len (hash-keys x))]
|
|
||||||
[else #f]))
|
|
||||||
|
|
||||||
(define (change x i value)
|
|
||||||
; general-purpose mutable data object setter
|
|
||||||
(cond
|
|
||||||
[(vector? x) (vector-set! x i value)]
|
|
||||||
[(hash? x) (hash-set! x i value)]
|
|
||||||
[else (error "Can't set this datatype using !")]))
|
|
||||||
|
|
||||||
(define (get x i [j #f])
|
|
||||||
(when (and (or (list? x) (string? x) (vector? x)) j)
|
|
||||||
(cond
|
|
||||||
[(and (real? j) (< j 0)) (set! j (+ (len x) j))]
|
|
||||||
[(equal? j 'end) (set! j (len x))]))
|
|
||||||
|
|
||||||
(cond
|
|
||||||
[(list? x) (if j
|
|
||||||
(for/list ([index (range i j)])
|
|
||||||
(get x index))
|
|
||||||
(list-ref x i))]
|
|
||||||
[(vector? x) (if j
|
|
||||||
(for/vector ([index (range i j)])
|
|
||||||
(get x index))
|
|
||||||
(vector-ref x i))]
|
|
||||||
[(string? x) (if j
|
|
||||||
(substring x i j)
|
|
||||||
(get x i (add1 i)))]
|
|
||||||
[(symbol? x) (as-symbol (get (as-string x) i j))]
|
|
||||||
[(hash? x) (if j
|
|
||||||
(error "get: third arg not supported for hash")
|
|
||||||
(hash-ref x i))]
|
|
||||||
[else #f]))
|
|
||||||
|
|
||||||
(define (in? container element)
|
|
||||||
(cond
|
|
||||||
[(list? container) (member element container)]
|
|
||||||
[(hash? container) (hash-has-key? container element)]
|
|
||||||
; todo: should this handle arbitrary-length substrings?
|
|
||||||
; leaning toward no, because it breaks the string-as-array-of-characters abstraction
|
|
||||||
[(string? container) (let ([result (in? (map as-string (string->list container)) (as-string element))])
|
|
||||||
(if result
|
|
||||||
(string-join result "")
|
|
||||||
#f))]
|
|
||||||
[(symbol? container) (let ([result (in? (as-string container) element)])
|
|
||||||
(if result
|
|
||||||
(as-symbol result)
|
|
||||||
result))]
|
|
||||||
[else #f]))
|
|
||||||
|
|
||||||
(define (to-lc x)
|
|
||||||
(string-downcase x))
|
|
||||||
|
|
||||||
(define (to-uc x)
|
|
||||||
(string-upcase x))
|
|
||||||
|
|
||||||
; python-style string testers
|
|
||||||
(define (starts-with? string starter)
|
|
||||||
(if (<= (len starter) (len string))
|
|
||||||
(equal? (get string 0 (len starter)) starter)
|
|
||||||
#f))
|
|
||||||
|
|
||||||
(define (ends-with? string ender)
|
|
||||||
(if (<= (len ender) (len string) )
|
|
||||||
(equal? (get string (- (len string) (len ender)) 'end) ender)
|
|
||||||
#f))
|
|
||||||
|
|
||||||
; coercions
|
|
||||||
(define (as-path thing)
|
|
||||||
(set! thing
|
|
||||||
(if (string? thing)
|
|
||||||
(string->path thing)
|
|
||||||
thing))
|
|
||||||
(when (not (path? thing)) (error (format "Can't make ~a into path" thing)))
|
|
||||||
thing)
|
|
||||||
|
|
||||||
(define (as-list thing)
|
|
||||||
(set! thing
|
|
||||||
(if (not (list? thing))
|
|
||||||
(list thing)
|
|
||||||
thing))
|
|
||||||
(when (not (list? thing)) (error (format "Can't make ~a into list" thing)))
|
|
||||||
thing)
|
|
||||||
|
|
||||||
; nice way of converting to string
|
|
||||||
(define (as-string x)
|
|
||||||
(set! x (cond
|
|
||||||
[(empty? x) ""]
|
[(empty? x) ""]
|
||||||
[(symbol? x) (symbol->string x)]
|
[(symbol? x) (symbol->string x)]
|
||||||
[(number? x) (number->string x)]
|
[(number? x) (number->string x)]
|
||||||
[(path? x) (path->string x)]
|
[(path? x) (path->string x)]
|
||||||
[(char? x) (~a x)]
|
[(char? x) (~a x)]
|
||||||
[else x]))
|
[else (error (format "Can't make ~a into string" x))]))
|
||||||
(when (not (string? x)) (error (format "Can't make ~a into string" x)))
|
|
||||||
x)
|
|
||||||
|
(module+ test
|
||||||
; nice way of converting to symbol
|
(require rackunit)
|
||||||
; todo: on bad input, it will pop a string error rather than symbol error
|
(check-equal? (as-string '()) "")
|
||||||
(define (as-symbol thing)
|
(check-equal? (as-string 'foo) "foo")
|
||||||
(string->symbol (as-string thing)))
|
(check-equal? (as-string 123) "123")
|
||||||
|
(define file-name-as-text "foo.txt")
|
||||||
; nice way of converting to path
|
(check-equal? (as-string (string->path file-name-as-text)) file-name-as-text)
|
||||||
(define (as-complete-path thing)
|
(check-equal? (as-string #\¶) "¶")
|
||||||
(path->complete-path (as-path thing)))
|
)
|
||||||
|
|
||||||
; any & all & none
|
|
||||||
(define (any tests things)
|
|
||||||
(ormap (ƒ(test) (ormap test (as-list things))) (as-list tests)))
|
|
||||||
|
|
||||||
(define (all tests things)
|
|
||||||
(andmap (ƒ(test) (andmap test (as-list things))) (as-list tests)))
|
|
||||||
|
|
||||||
(define (none test things) (not (any test things)))
|
|
||||||
|
|
||||||
|
|
||||||
; Other possibilities
|
|
||||||
; trim
|
|
||||||
; split
|
|
Loading…
Reference in New Issue