-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpredicates.sls
152 lines (134 loc) · 4.5 KB
/
predicates.sls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!r6rs
;; Copyright 2009 Derick Eddington. My MIT-style license is in the file named
;; LICENSE from the original collection this file is distributed with.
(library (xitomatl predicates)
(export
not? and? or? xor?
non-negative-integer?
exact-non-negative-integer?
positive-integer?
exact-positive-integer?
exact-integer?
list-of?
#;datum?
pairwise?
symbol<?
name=?
non-empty-string?
char-line-ending?)
(import
(rnrs)
(only (xitomatl conditionals) xor))
(define (not? pred)
(lambda (x)
(not (pred x))))
(define and?
(case-lambda
((pred0 pred1)
(lambda (x) (and (pred0 x) (pred1 x))))
((pred0 pred1 pred2)
(lambda (x) (and (pred0 x) (pred1 x) (pred2 x))))
(preds
(lambda (x)
(or (null? preds)
(let loop ((preds preds))
(if (null? (cdr preds))
((car preds) x) ;; tail call
(and ((car preds) x)
(loop (cdr preds))))))))))
(define or?
(case-lambda
((pred0 pred1)
(lambda (x) (or (pred0 x) (pred1 x))))
((pred0 pred1 pred2)
(lambda (x) (or (pred0 x) (pred1 x) (pred2 x))))
(preds
(lambda (x)
(and (pair? preds)
(let loop ((preds preds))
(if (null? (cdr preds))
((car preds) x) ;; tail call
(or ((car preds) x)
(loop (cdr preds))))))))))
(define xor?
;; NOTE: Does not tail-call the last predicate.
(case-lambda
((pred0 pred1)
(lambda (x) (xor (pred0 x) (pred1 x))))
((pred0 pred1 pred2)
(lambda (x) (xor (pred0 x) (pred1 x) (pred2 x))))
(preds
(lambda (x)
(let loop ((preds preds) (r #F))
(if (null? preds)
r
(let ((v ((car preds) x)))
(if v
(and (not r)
(loop (cdr preds) v))
(loop (cdr preds) r)))))))))
(define (non-negative-integer? x)
(and (integer? x) (not (negative? x))))
(define (exact-non-negative-integer? x)
(and (integer? x) (exact? x) (not (negative? x))))
(define (positive-integer? x)
(and (integer? x) (positive? x)))
(define (exact-positive-integer? x)
(and (integer? x) (exact? x) (positive? x)))
(define (exact-integer? x)
(and (integer? x) (exact? x)))
(define (list-of? pred)
(letrec ((list-of?-pred
(lambda (x)
(if (pair? x)
(and (pred (car x))
(list-of?-pred (cdr x)))
(null? x)))))
list-of?-pred))
#;(define (datum? x)
;; The naive implementation cannot handle cyclic structures.
;; How to do this..?
)
(define pairwise?
;; Make a predicate which tests if all its arguments are pairwise true
;; for a given binary predicate. 0 and 1 arguments are always considered
;; true; e.g.: ((pairwise? <)) => #T and ((pairwise? =) 42) => #T.
;; The optional 2nd argument is an arbitrary procedure that takes 1
;; argument, and it is applied to each element once and must return a value
;; to use with the binary predicate, or raise an exception; this procedure
;; is useful for efficiently type-checking elements and/or transforming them.
(case-lambda
((binary-pred)
(pairwise? binary-pred #F))
((binary-pred proc)
(let ((next (if proc
(lambda (l) (proc (car l)))
car)))
(lambda args
(or (null? args)
(let ((x (next args)))
(let loop ((x x) (r (cdr args)))
(or (null? r)
(let ((y (next r)))
(and (binary-pred x y)
(loop y (cdr r)))))))))))))
(define symbol<?
(pairwise? string<?
(lambda (x)
(if (symbol? x)
(symbol->string x)
(assertion-violation 'symbol<? "not a symbol" x)))))
(define name=?
(pairwise? string=?
(lambda (x)
(cond ((identifier? x) (symbol->string (syntax->datum x)))
((symbol? x) (symbol->string x))
((string? x) x)
(else (assertion-violation 'name=?
"not an identifier, symbol, or string" x))))))
(define (non-empty-string? x)
(and (string? x) (positive? (string-length x))))
(define (char-line-ending? c)
(and (memv c '(#\xa #\xd #\x85 #\x2028)) ;; correct? everything it should be?
#T))
)