diff options
Diffstat (limited to 'chicanery.extras.scm')
-rw-r--r-- | chicanery.extras.scm | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/chicanery.extras.scm b/chicanery.extras.scm new file mode 100644 index 0000000..f9bb4a1 --- /dev/null +++ b/chicanery.extras.scm | |||
@@ -0,0 +1,145 @@ | |||
1 | (module (chicanery extras) ( append for-each map | ||
2 | list-append list-for-each list-map | ||
3 | ref copy | ||
4 | atom? defined? | ||
5 | read-port-chunk-size read-port | ||
6 | with-output-to-string with-input-from-string | ||
7 | displayed written print ->string) | ||
8 | (import scheme (chicanery base)) | ||
9 | |||
10 | (define list-append append) | ||
11 | (define list-for-each for-each) | ||
12 | (define list-map map) | ||
13 | |||
14 | (define (map proc . collections) | ||
15 | (let ((first (car collections))) ; we only need to check the first one | ||
16 | (cond | ||
17 | ((list? first) | ||
18 | (apply list-map proc collections)) | ||
19 | ((vector? first) | ||
20 | (apply vector-map proc collections)) | ||
21 | ((string? first) | ||
22 | (apply string-map proc collections)) | ||
23 | (else (error "Bad datatype" first))))) | ||
24 | |||
25 | (define (for-each proc . collections) | ||
26 | (let ((first (car collections))) ; we only need to check the first one | ||
27 | (cond | ||
28 | ((list? first) | ||
29 | (apply list-for-each proc collections)) | ||
30 | ((vector? first) | ||
31 | (apply vector-for-each proc collections)) | ||
32 | ((string? first) | ||
33 | (apply string-for-each proc collections)) | ||
34 | (else (error "Bad datatype" first))))) | ||
35 | |||
36 | (define (append . collections) | ||
37 | (let ((first (car collections))) ; we only need to check the first one | ||
38 | (cond | ||
39 | ((list? first) | ||
40 | (apply list-append collections)) | ||
41 | ((vector? first) | ||
42 | (apply vector-append collections)) | ||
43 | ((string? first) | ||
44 | (apply string-append collections)) | ||
45 | ((bytevector? first) | ||
46 | (apply bytevector-append collections)) | ||
47 | (else (error "Bad datatype" first))))) | ||
48 | |||
49 | ;;; Extended generic functions. | ||
50 | ;; These functions already have a list- version defined, but no non-prefixed | ||
51 | ;; one. So I'm fixing that. | ||
52 | (define (ref collection k) | ||
53 | (cond | ||
54 | ((list? collection) | ||
55 | (list-ref collection k)) | ||
56 | ((vector? collection) | ||
57 | (vector-ref collection k)) | ||
58 | ((string? collection) | ||
59 | (string-ref collection k)) | ||
60 | ((bytevector? collection) | ||
61 | (bytevector-u8-ref collection k)) | ||
62 | (else (error "Bad datatype" collection)))) | ||
63 | |||
64 | ;; I'm not going to generalize -copy! because I don't think it's a great idea, | ||
65 | ;; really. | ||
66 | (define (copy collection) | ||
67 | (cond | ||
68 | ((list? collection) | ||
69 | (list-copy collection)) | ||
70 | ((vector? collection) | ||
71 | (vector-copy collection)) | ||
72 | ((string? collection) | ||
73 | (string-copy collection)) | ||
74 | ((bytevector? collection) | ||
75 | (bytevector-copy collection)) | ||
76 | (else (error "Bad datatype" collection)))) | ||
77 | |||
78 | ;;; Definitions that should be in scheme | ||
79 | ;; This sections should be as small as possible | ||
80 | |||
81 | (define (atom? x) | ||
82 | (and (not (pair? x)) | ||
83 | (not (null? x)))) | ||
84 | |||
85 | (define read-port-chunk-size | ||
86 | (make-parameter 512)) | ||
87 | |||
88 | (define (%read-port port) | ||
89 | (let ((chunk-size (read-port-chunk-size))) | ||
90 | (let loop ((next (read-string chunk-size port)) | ||
91 | (blank? #f) | ||
92 | (acc '())) | ||
93 | (cond | ||
94 | ((or (eof-object? next) | ||
95 | (and blank? (equal? next ""))) | ||
96 | (apply string-append (reverse acc))) | ||
97 | ((equal? next "") | ||
98 | (loop (read-string chunk-size port) | ||
99 | #t | ||
100 | (cons next acc))) | ||
101 | (else | ||
102 | (loop (read-string chunk-size port) | ||
103 | blank? | ||
104 | (cons next acc))))))) | ||
105 | |||
106 | (define read-port | ||
107 | (case-lambda | ||
108 | (() (%read-port (current-input-port))) | ||
109 | ((p) (%read-port p)))) | ||
110 | |||
111 | (define (defined? sym) | ||
112 | (call-with-current-continuation | ||
113 | (lambda (k) | ||
114 | (with-exception-handler | ||
115 | (lambda (e) (k #f)) | ||
116 | (lambda () | ||
117 | (eval sym (interaction-environment)) | ||
118 | #t))))) | ||
119 | |||
120 | (define (with-output-to-string thunk) | ||
121 | (call-with-port (open-output-string) | ||
122 | (lambda (port) | ||
123 | (parameterize ((current-output-port port)) | ||
124 | (thunk)) | ||
125 | (get-output-string port)))) | ||
126 | |||
127 | (define (with-input-from-string s thunk) | ||
128 | (call-with-port (open-input-string s) | ||
129 | (lambda (port) | ||
130 | (parameterize ((current-input-port port)) | ||
131 | (thunk))))) | ||
132 | |||
133 | (define (displayed x) | ||
134 | (with-output-to-string | ||
135 | (lambda () (display x)))) | ||
136 | |||
137 | (define (written x) | ||
138 | (with-output-to-string | ||
139 | (lambda () (write x)))) | ||
140 | |||
141 | (define (print . xs) | ||
142 | (for-each display xs) | ||
143 | (newline)) | ||
144 | |||
145 | (define ->string displayed)) | ||