It's terrible. Not sure how to do better.
* split-by-tests
(defun split-by-tests (msg-lst test-lst &key ((:test default-test) #'eql))
(flet ((do-test (test msg)
(if (functionp test)
(funcall test msg)
(funcall default-test test msg))))
(loop with tests = test-lst
with done-tests = nil
with section = nil ; What I really want is use collect
instead, but see next comment
for msgs on msg-lst
for msg = (car msgs)
for is-separator? = (loop for test in tests
collect test into done-tests2
thereis (and (do-test test msg)
(setq done-tests (append done-tests2 done-tests)) done-tests2))
if is-separator?
collect (nreverse section) into sections
and do (setq section (list msg) ; I need to set section nil here.
Loop facility resets it back when collecting.
tests (cdr tests))
else
if (loop for test in done-tests thereis (do-test test msg))
do (error "repeated separator ~S found. With tests ~S on list ~S"
msg test-lst msg-lst)
else do (push msg section)
end
end
finally (return (nconc sections (list (nreverse section)))))))
This is a utility function I need for parsing the message passing
syntax of javascript forms.
* A few tests for split-by-tests:
(split-by-tests '(~ @) '(~ @))
=> (NIL (~) (@))
(split-by-tests '(1 ~ @) '(~ @))
=> ((1) (~) (@))
(split-by-tests '(~ 2 @) '(~ @))
=> (NIL (~ 2) (@))
(split-by-tests '(~ @ 3) '(~ @))
=> (NIL (~) (@ 3))
(split-by-tests '(~ 2 @ 3) '(~ @))
=> (NIL (~ 2) (@ 3))
(split-by-tests '(1 ~ 2 @ 3) '(~ @))
=> ((1) (~ 2) (@ 3))
(split-by-tests '(1 1 ~ 2 2 @ 3 3) '(~ @))
=> ((1 1) (~ 2 2) (@ 3 3))
(split-by-tests '(1 1 ~ 2 2 @ 3 3 ~ 4 4) '(~ @))
[error]
(defparameter foo (loop for i to 100 collect i))
(defparameter foo-tests (mapcar #'(lambda (x) #'(lambda (y) (eql x y)))
(loop for i to 100 by 10 collect i)))
(split-by-tests '(1 1 1 1 1 2 1 1 1 1 ) (list #'evenp))
=>
((1 1 1 1 1) (2 1 1 1 1))
(split-by-tests foo foo-tests)
=>
(NIL (0 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))
(split-by-tests foo '(6 25 30 90))
=>
((0 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))
* The planned javascript syntax is:
(foo ~)
foo();
1 Special Case for 0 arguments application:
(foo)
foo();
foo
foo
(foo @)
foo[];
(foo @ a)
foo[a];
(foo bar ~)
foo.bar();
(foo ~ a b)
foo(a,b);
(foo bar ~ a b @ c d)
foo.bar(a,b)[c][d];
((foo bar ~ a b @ c d) ~ e f)
foo.bar(a,b)[c][d](e,f);