nydp 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/nydp +1 -1
- data/lib/lisp/core-000.nydp +1 -0
- data/lib/lisp/core-010-precompile.nydp +15 -15
- data/lib/lisp/core-012-utils.nydp +6 -5
- data/lib/lisp/core-020-utils.nydp +20 -6
- data/lib/lisp/core-030-syntax.nydp +14 -16
- data/lib/lisp/core-035-flow-control.nydp +26 -8
- data/lib/lisp/core-040-utils.nydp +4 -15
- data/lib/lisp/core-041-string-utils.nydp +3 -3
- data/lib/lisp/core-043-list-utils.nydp +81 -16
- data/lib/lisp/core-045-dox-utils.nydp +2 -2
- data/lib/lisp/core-060-benchmarking.nydp +92 -27
- data/lib/lisp/tests/all-examples.nydp +20 -0
- data/lib/lisp/tests/any-examples.nydp +28 -0
- data/lib/lisp/tests/builtin-tests.nydp +3 -1
- data/lib/lisp/tests/collect-tests.nydp +10 -0
- data/lib/lisp/tests/curry-tests.nydp +7 -2
- data/lib/lisp/tests/error-tests.nydp +11 -0
- data/lib/lisp/tests/foundation-test.nydp +66 -0
- data/lib/lisp/tests/len-examples.nydp +1 -0
- data/lib/lisp/tests/list-gsub-examples.nydp +25 -0
- data/lib/lisp/tests/list-match-examples.nydp +40 -0
- data/lib/lisp/tests/list-tests.nydp +13 -0
- data/lib/lisp/tests/none-examples.nydp +16 -0
- data/lib/lisp/tests/parser-tests.nydp +4 -5
- data/lib/lisp/tests/quasiquote-examples.nydp +2 -0
- data/lib/lisp/tests/syntax-tests.nydp +3 -2
- data/lib/lisp/tests/tuples-examples.nydp +2 -2
- data/lib/nydp.rb +50 -18
- data/lib/nydp/assignment.rb +3 -1
- data/lib/nydp/builtin.rb +15 -13
- data/lib/nydp/builtin/error.rb +1 -1
- data/lib/nydp/builtin/handle_error.rb +8 -2
- data/lib/nydp/builtin/parse_in_string.rb +1 -1
- data/lib/nydp/builtin/plus.rb +4 -4
- data/lib/nydp/closure.rb +5 -1
- data/lib/nydp/compiler.rb +2 -3
- data/lib/nydp/cond.rb +134 -13
- data/lib/nydp/context_symbol.rb +4 -1
- data/lib/nydp/error.rb +8 -0
- data/lib/nydp/function_invocation.rb +46 -48
- data/lib/nydp/helper.rb +15 -0
- data/lib/nydp/interpreted_function.rb +10 -14
- data/lib/nydp/lexical_context.rb +13 -2
- data/lib/nydp/lexical_context_builder.rb +28 -13
- data/lib/nydp/pair.rb +35 -36
- data/lib/nydp/parser.rb +3 -0
- data/lib/nydp/runner.rb +4 -32
- data/lib/nydp/string_atom.rb +3 -2
- data/lib/nydp/symbol.rb +1 -1
- data/lib/nydp/symbol_lookup.rb +9 -1
- data/lib/nydp/truth.rb +1 -1
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +2 -2
- data/nydp.gemspec +1 -1
- data/spec/error_spec.rb +14 -4
- data/spec/hash_non_hash_behaviour_spec.rb +19 -12
- data/spec/hash_spec.rb +0 -13
- data/spec/pair_spec.rb +17 -3
- data/spec/spec_helper.rb +13 -1
- data/spec/symbol_spec.rb +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc628274c2cf2f44cd05559766575d3cc9920d69
|
4
|
+
data.tar.gz: 619d6083cf6dab728793950bbc005fe3b281be56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 391b384008f3e7e23505cb0871ab667435aea31a0841f71f3572316bdf1fc731a142f6dff7f0e2be26cf2eb60750bd60cf8ae89f298f9670f387b24fa2fd6141
|
7
|
+
data.tar.gz: 4390de26c600a52fbcf82bd91045acd3ed8791aeddcbec340cd227982632a28cdf2cbb1db42f2608f48b04010d3526870d5bfbfcc8161bf6601edd290394b5e5
|
data/bin/nydp
CHANGED
data/lib/lisp/core-000.nydp
CHANGED
@@ -70,11 +70,11 @@
|
|
70
70
|
(qq-skip-unquote-splicing arg rest level)))
|
71
71
|
|
72
72
|
(def qq-do-unquote-splicing (arg rest level)
|
73
|
-
(cond
|
74
|
-
arg
|
73
|
+
(cond rest
|
75
74
|
(list '+
|
76
75
|
(pre-compile arg)
|
77
|
-
(qq-quasiquote rest level))
|
76
|
+
(qq-quasiquote rest level))
|
77
|
+
arg))
|
78
78
|
|
79
79
|
(def qq-skip-unquote-splicing (arg rest level)
|
80
80
|
(list 'cons
|
@@ -117,18 +117,18 @@
|
|
117
117
|
(pre-compile xs)
|
118
118
|
(list 'list ''unquote (qq-quasiquote xs (- level 1)))))
|
119
119
|
|
120
|
-
(def qq-quasiquote (
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
120
|
+
(def qq-quasiquote (things level)
|
121
|
+
(cond things
|
122
|
+
(cond (pair? things)
|
123
|
+
(cond (eq? (car things) 'unquote)
|
124
|
+
(qq-maybe-unquote (cadr things) level)
|
125
|
+
(cond (eq? (car things) 'unquote-splicing)
|
126
|
+
(qq-handle-unquote-splicing (cadr things) nil level)
|
127
|
+
(cond (eq? (car things) 'quasiquote)
|
128
|
+
(list 'list ''quasiquote (qq-quasiquote (cdr things) (+ level 1)))
|
129
|
+
(qq-unquote? (car things) (cdr things) level))))
|
130
|
+
(list 'quote things))
|
131
|
+
nil))
|
132
132
|
|
133
133
|
(hash-set macs 'quasiquote
|
134
134
|
(fn (arg) (qq-quasiquote arg 0)))
|
@@ -1,11 +1,12 @@
|
|
1
1
|
|
2
2
|
(hash-set macs 'if (fn args
|
3
|
-
(cond
|
3
|
+
(cond args
|
4
4
|
(cond (cdr args)
|
5
5
|
(cond (cddr args)
|
6
6
|
`(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
|
7
7
|
`(cond ,(car args) ,(cadr args)))
|
8
|
-
(car args))
|
8
|
+
(car args))
|
9
|
+
nil)))
|
9
10
|
|
10
11
|
(def map (f things)
|
11
12
|
; transforms the list 'things by applying 'f to each item
|
@@ -20,10 +21,10 @@
|
|
20
21
|
(hash-set h k (cons v (hash-get h k))))
|
21
22
|
|
22
23
|
(def rev-accum (things acc)
|
23
|
-
(cond
|
24
|
-
acc
|
24
|
+
(cond things
|
25
25
|
(rev-accum (cdr things)
|
26
26
|
(cons (car things)
|
27
|
-
acc))
|
27
|
+
acc))
|
28
|
+
acc))
|
28
29
|
|
29
30
|
(def rev (things) (rev-accum things nil))
|
@@ -9,12 +9,13 @@
|
|
9
9
|
"with arguments a b c d e, return b if a is true, otherwise return d if c is true, otherwise e"
|
10
10
|
"and so on for subsequent arguments")
|
11
11
|
'args
|
12
|
-
'(cond
|
12
|
+
'(cond args
|
13
13
|
(cond (cdr args)
|
14
14
|
(cond (cddr args)
|
15
15
|
`(cond ,(car args) ,(cadr args) (if ,@(cddr args)))
|
16
16
|
`(cond ,(car args) ,(cadr args)))
|
17
|
-
(car args))
|
17
|
+
(car args))
|
18
|
+
nil)
|
18
19
|
'(flow-control))
|
19
20
|
|
20
21
|
(dox-add-doc 'map
|
@@ -22,11 +23,10 @@
|
|
22
23
|
'("transforms the list 'things by applying 'f to each item"
|
23
24
|
"returns the resulting list")
|
24
25
|
'(f things)
|
25
|
-
'(if (
|
26
|
-
nil
|
27
|
-
(pair? things)
|
26
|
+
'(if (pair? things)
|
28
27
|
(cons (f (car things)) (map f (cdr things)))
|
29
|
-
|
28
|
+
things
|
29
|
+
(f things))
|
30
30
|
'(list-manipulation))
|
31
31
|
|
32
32
|
(dox-add-doc 'rev
|
@@ -42,3 +42,17 @@
|
|
42
42
|
'(h k v)
|
43
43
|
'(hash-set h k (cons v (hash-get h k)))
|
44
44
|
'(hash-manipulation))
|
45
|
+
|
46
|
+
(def join-str (prefix joint things)
|
47
|
+
(chapter string-manipulation)
|
48
|
+
; equivalent to (join-str "~prefix~joint~(car things)" joint (cdr things)) - except
|
49
|
+
; 'string-pieces hasn't been defined yet, and if it were, it would be defined in terms of
|
50
|
+
; 'join-str, so it would be circular.
|
51
|
+
; see 'joinstr for a more powerful and easier-to-use implementation of the same idea
|
52
|
+
(if things
|
53
|
+
(join-str (+ (to-string prefix)
|
54
|
+
joint
|
55
|
+
(to-string (car things)))
|
56
|
+
joint
|
57
|
+
(cdr things))
|
58
|
+
prefix))
|
@@ -47,7 +47,7 @@ scoping, assignment, anonymous functions and more...")
|
|
47
47
|
(fn (,var) ,@body)))
|
48
48
|
|
49
49
|
(def-colon-syntax || names
|
50
|
-
(error "Irregular ': syntax: got ~(inspect names) : not prefix-syntax : in ~(
|
50
|
+
(error "Irregular ': syntax: got ~(inspect names) : not prefix-syntax : in ~(join-str (car names) ":" (cdr names))"))
|
51
51
|
|
52
52
|
(mac colon-syntax names
|
53
53
|
; handle syntax of the form a:b, which the parser expands to
|
@@ -68,9 +68,9 @@ scoping, assignment, anonymous functions and more...")
|
|
68
68
|
; For example,
|
69
69
|
; (!eq? a 10) is the same as (no:eq? a 10), which is the same as (no (eq? a 10))
|
70
70
|
(if (no (eq? pfx '||))
|
71
|
-
(error "Irregular '! syntax: got prefix ~(inspect pfx) in ~(
|
71
|
+
(error "Irregular '! syntax: got prefix ~(inspect pfx) in ~(join-str pfx "!" rest)"))
|
72
72
|
(if (cdr rest)
|
73
|
-
(error "Irregular '! syntax: got suffix ~(inspect (cdr rest)) in ~(
|
73
|
+
(error "Irregular '! syntax: got suffix ~(inspect (cdr rest)) in ~(join-str pfx "!" rest)")
|
74
74
|
(if (caris 'colon-syntax (car rest))
|
75
75
|
`(colon-syntax no ,@(cdar rest))
|
76
76
|
`(colon-syntax no ,(car rest)))))
|
@@ -79,10 +79,10 @@ scoping, assignment, anonymous functions and more...")
|
|
79
79
|
`(cond ,condition (do ,@body)))
|
80
80
|
|
81
81
|
(def pairs (things)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
(if (no things) nil
|
83
|
+
(no (cdr things)) (list (list (car things)))
|
84
|
+
(cons (list (car things) (cadr things))
|
85
|
+
(pairs (cddr things)))))
|
86
86
|
|
87
87
|
(mac with (parms . body)
|
88
88
|
`((fn ,(map car (pairs parms))
|
@@ -117,13 +117,11 @@ scoping, assignment, anonymous functions and more...")
|
|
117
117
|
(,name ,@(map cadr ppairs)))))
|
118
118
|
|
119
119
|
(let uniq-counter 0
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
(def reset-uniq-counter ()
|
126
|
-
(assign uniq-counter 0)))
|
120
|
+
(def uniq (prefix)
|
121
|
+
(assign uniq-counter (+ uniq-counter 1))
|
122
|
+
(sym (join-str prefix "-" (list uniq-counter))))
|
123
|
+
(def reset-uniq-counter ()
|
124
|
+
(assign uniq-counter 0)))
|
127
125
|
|
128
126
|
(mac w/uniq (vars . body)
|
129
127
|
; creates a lexical scope with a unique symbol assigned to
|
@@ -226,9 +224,9 @@ scoping, assignment, anonymous functions and more...")
|
|
226
224
|
(mac ampersand-syntax (pfx . rest)
|
227
225
|
; parser expands a&b to (ampersand-syntax a b)
|
228
226
|
(if (no (eq? pfx '||))
|
229
|
-
(error "Irregular '& syntax: got prefix ~(inspect pfx) in ~(
|
227
|
+
(error "Irregular '& syntax: got prefix ~(inspect pfx) in ~(join-str pfx "&" rest)"))
|
230
228
|
(if (cdr rest)
|
231
|
-
(error "Irregular '& syntax: got suffix ~(inspect (cdr rest)) in ~(
|
229
|
+
(error "Irregular '& syntax: got suffix ~(inspect (cdr rest)) in ~(join-str pfx "&" rest)")
|
232
230
|
(build-ampersand-syntax (car rest))))
|
233
231
|
|
234
232
|
(mac brace-list-mono (arg)
|
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
(mac on-err (handler . body)
|
4
4
|
; executes 'body. If an error is raised, executes 'handler. Inside
|
5
|
-
; 'handler, the parameter '
|
6
|
-
|
7
|
-
|
5
|
+
; 'handler, the parameter 'errors is a list of error messages extracted from
|
6
|
+
; the sequence of errors that led here (Exception#cause in ruby or Throwable.getCause() in java)
|
7
|
+
`(handle-error (fn (errors) ,handler)
|
8
|
+
(fn () ,@body)))
|
8
9
|
|
9
10
|
(mac ensure (protection . body)
|
10
11
|
; executes 'body. Afterwards, executes 'protection.
|
@@ -39,12 +40,29 @@
|
|
39
40
|
(loop (assign ,v ,gi) (< ,v ,gm) (assign ,v (+ ,v 1))
|
40
41
|
,@body))))
|
41
42
|
|
42
|
-
(
|
43
|
+
(mac curry (func . args1)
|
43
44
|
; return a new function which is the original function with
|
44
45
|
; the given args1 already applied
|
45
46
|
; arguments to the new function are whatever arguments remain
|
46
47
|
; for the old function
|
47
|
-
(fn args
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
`(fn args (apply ,func ,@args1 args)))
|
49
|
+
|
50
|
+
(mac cache-get (hsh key val)
|
51
|
+
; if ,key is already in ,hsh - return the associated value.
|
52
|
+
; if ,key is not already in ,hsh - evaluate ,val, store the result
|
53
|
+
; under ,key in ,hsh, and return it
|
54
|
+
(w/uniq (h k v)
|
55
|
+
`(with (,h ,hsh ,k ,key)
|
56
|
+
(let ,v (hash-get ,h ,k)
|
57
|
+
(or ,v (returnlet ,v ,val (hash-set ,h ,k ,v)))))))
|
58
|
+
|
59
|
+
(mac defmemo (name args . body)
|
60
|
+
; same as 'def, but caches the result, keyed on args, so for a given set of args the result
|
61
|
+
; is only ever calculated once
|
62
|
+
(let forms (filter-forms (build-def-hash (hash)) body)
|
63
|
+
(w/uniq h
|
64
|
+
`(let ,h (hash)
|
65
|
+
(def ,name ,args
|
66
|
+
,@(if forms.comment (map (fn (c) list 'comment c)) forms.comment)
|
67
|
+
,(if forms.chapter `(chapter ,forms.chapter))
|
68
|
+
(cache-get ,h (list ,@args) (do ,@(hash-get forms nil))))))))
|
@@ -1,17 +1,5 @@
|
|
1
1
|
(chapter-start 'nydp-core "essential functions for getting anything done")
|
2
2
|
|
3
|
-
(def joinstr (txt . things)
|
4
|
-
; flatten 'things into a single list (ie unnest lists)
|
5
|
-
; convert each item to a string
|
6
|
-
; return a single string which is the concatenation of each
|
7
|
-
; stringified item, with given 'txt inserted in between
|
8
|
-
; each item
|
9
|
-
(let joinables (flatten things)
|
10
|
-
(apply +
|
11
|
-
(to-string (car joinables))
|
12
|
-
(flatten (zip (map (fn (_) txt) (cdr joinables))
|
13
|
-
(map to-string (cdr joinables)))))))
|
14
|
-
|
15
3
|
(def iso (x y)
|
16
4
|
(or (eq? x y)
|
17
5
|
(and (pair? x)
|
@@ -21,6 +9,7 @@
|
|
21
9
|
|
22
10
|
(def x1 (thing) thing)
|
23
11
|
(def sym? (arg) (isa 'symbol arg))
|
12
|
+
(def num? (arg) (isa 'number arg))
|
24
13
|
(def string? (arg) (isa 'string arg))
|
25
14
|
(mac just (arg) arg)
|
26
15
|
(def quotify (arg) `(quote ,arg))
|
@@ -32,11 +21,11 @@
|
|
32
21
|
(chapter list-manipulation)
|
33
22
|
(chapter string-manipulation)
|
34
23
|
(chapter hash-manipulation)
|
35
|
-
(if (
|
36
|
-
(pair? things) (list-length things)
|
24
|
+
(if (pair? things) (list-length things)
|
37
25
|
(string? things) (string-length things)
|
38
26
|
(hash? things) (list-length:hash-keys things)
|
39
|
-
nil
|
27
|
+
things nil
|
28
|
+
0))
|
40
29
|
|
41
30
|
(assign dynamics (hash))
|
42
31
|
|
@@ -11,9 +11,9 @@
|
|
11
11
|
; each item
|
12
12
|
(let joinables (flatten things)
|
13
13
|
(apply +
|
14
|
-
(to-string
|
15
|
-
(flatten (
|
16
|
-
(
|
14
|
+
(to-string:car joinables)
|
15
|
+
(flatten (map (fn (x) (list txt x))
|
16
|
+
(cdr joinables))))))
|
17
17
|
|
18
18
|
(def j items
|
19
19
|
; delegate to 'joinstr with an empty join string
|
@@ -1,18 +1,20 @@
|
|
1
1
|
(chapter-start 'list-manipulation)
|
2
2
|
|
3
3
|
(def list-length (things)
|
4
|
-
(if (
|
5
|
-
(
|
6
|
-
|
4
|
+
(if (atom? things) 1
|
5
|
+
things (+ 1 (list-length (cdr things)))
|
6
|
+
0))
|
7
7
|
|
8
8
|
(def list-slices (things slice-size)
|
9
9
|
; slice 'things into a list of lists each with maximum 'slice-size items
|
10
10
|
(chapter pagination)
|
11
|
-
(if
|
12
|
-
(
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
(if things
|
12
|
+
(if (> slice-size (len things))
|
13
|
+
(list things)
|
14
|
+
(cons (firstn slice-size things)
|
15
|
+
(list-slices (nthcdr slice-size things)
|
16
|
+
slice-size)))
|
17
|
+
nil))
|
16
18
|
|
17
19
|
(def intersperse (inbetween things)
|
18
20
|
; return a new list with 'inbetween in between every element of 'things
|
@@ -43,6 +45,16 @@
|
|
43
45
|
(f items)
|
44
46
|
items)))
|
45
47
|
|
48
|
+
(assign select collect)
|
49
|
+
|
50
|
+
(def compact (things)
|
51
|
+
; return a new list containing only non-nil items from the given list
|
52
|
+
(collect present? things))
|
53
|
+
|
54
|
+
(def +nz args
|
55
|
+
; return the sum of all non-nil values (consider nil as zero)
|
56
|
+
(apply + (compact args)))
|
57
|
+
|
46
58
|
(def reject (f things)
|
47
59
|
; return all the items in 'things for which 'f returns nil
|
48
60
|
(collect !f things))
|
@@ -53,14 +65,13 @@
|
|
53
65
|
(car things)
|
54
66
|
(nth (- n 1) (cdr things))))
|
55
67
|
|
56
|
-
(mac each (var things
|
68
|
+
(mac each (var things . body)
|
57
69
|
; repeatedly assigns an element of 'things to 'var,
|
58
|
-
; and executes '
|
70
|
+
; and executes 'body each time
|
59
71
|
(w/uniq (xs c)
|
60
72
|
`((rfn ,c (,xs)
|
61
73
|
(if (pair? ,xs)
|
62
|
-
(do
|
63
|
-
(let ,var (car ,xs) ,code)
|
74
|
+
(do (let ,var (car ,xs) ,@body)
|
64
75
|
(,c (cdr ,xs)))))
|
65
76
|
,things)))
|
66
77
|
|
@@ -81,10 +92,10 @@
|
|
81
92
|
|
82
93
|
(def firstn (n things)
|
83
94
|
; returns the first 'n items in the list 'things
|
84
|
-
(if (eq? n 0)
|
85
|
-
(cons (car things)
|
86
|
-
|
87
|
-
|
95
|
+
(if (eq? n 0) nil
|
96
|
+
things (cons (car things)
|
97
|
+
(firstn (- n 1)
|
98
|
+
(cdr things)))))
|
88
99
|
|
89
100
|
(def nthcdr (n things)
|
90
101
|
; returns the nth cdr of the list 'things
|
@@ -155,3 +166,57 @@
|
|
155
166
|
|
156
167
|
(def min things (best < things))
|
157
168
|
(def max things (best > things))
|
169
|
+
|
170
|
+
(def map-recurse (on-atom on-list things)
|
171
|
+
((afn (xs)
|
172
|
+
(if (pair? xs)
|
173
|
+
(on-list self xs)
|
174
|
+
xs
|
175
|
+
(on-atom xs)))
|
176
|
+
things))
|
177
|
+
|
178
|
+
(def list-gsub (list old new)
|
179
|
+
; recursively replaces 'old with 'new inside 'list
|
180
|
+
(map-recurse (fn (s) (if (eq? s old) new s))
|
181
|
+
(fn (m things)
|
182
|
+
(if (eq? things old)
|
183
|
+
new
|
184
|
+
(map m things)))
|
185
|
+
list))
|
186
|
+
|
187
|
+
(def all? (f things)
|
188
|
+
; if 'things is a list, true when all items are non-nil
|
189
|
+
; if 'things is an atom, true when non-nil
|
190
|
+
(if (pair? things)
|
191
|
+
(and (f:car things)
|
192
|
+
(or (no:cdr things)
|
193
|
+
(all? f (cdr things))))
|
194
|
+
(f things)))
|
195
|
+
|
196
|
+
(def any? (f things)
|
197
|
+
; if 'things is a list, true when at least one item is non-nil
|
198
|
+
; if 'things is an atom, true when non-nil
|
199
|
+
(if (pair? things)
|
200
|
+
(or (f:car things)
|
201
|
+
(and (cdr things)
|
202
|
+
(any? f (cdr things))))
|
203
|
+
(f things)))
|
204
|
+
|
205
|
+
(def none? (f things)
|
206
|
+
; if 'things is a list, true when all items are nil
|
207
|
+
; if 'things is an atom, true when nil
|
208
|
+
(if (pair? things)
|
209
|
+
(and (no:f:car things)
|
210
|
+
(none? f (cdr things)))
|
211
|
+
(no:f things)))
|
212
|
+
|
213
|
+
(def list-match? (matchers things)
|
214
|
+
; 'matchers is a list of functions
|
215
|
+
; 'things is a list of items to match
|
216
|
+
; true when each function in 'matchers returns non-nil for the corresponding value in 'things
|
217
|
+
(if (pair? matchers)
|
218
|
+
(and ((car matchers) (car things))
|
219
|
+
(list-match? (cdr matchers) (cdr things)))
|
220
|
+
matchers
|
221
|
+
(matchers things)
|
222
|
+
t))
|