I was just about to give up on doing the below, when I thought it might be fun for a more experienced person to offer advice. I have this repetitive cond
for a comparator, with my thanks to @notjack for writing such important data structures for us all in rebellion.
(cond
[(and (null? left-scope) (null? right-scope)) equivalent]
[(and (null? left-scope) (not (null? right-scope))) lesser]
[(and (not (null? left-scope)) (null? right-scope)) greater]
[(< left-scope right-scope) lesser]
[(> left-scope right-scope) greater]
[(and (null? left-tag) (null? right-tag)) equivalent]
[(and (null? left-tag) (not (null? right-tag))) lesser]
[(and (not (null? left-tag)) (null? right-tag)) greater]
[(string<? left-tag right-tag) lesser]
[(string>? left-tag right-tag) greater]
[else equivalent])))
To reduce eye strain and improve readability, I thought I could express it this way instead:
(bulk-cond
(null-pick left-scope right-scope)
(strict-pick left-scope right-scope < >)
(null-pick left-tag right-tag)
(strict-pick left-tag right-tag string<? string>?)
(else equivalent))
I understand this would be an academic exercise, but Racket came from academia; I should be among friends on wanting to do this. So, I went to work with a one-shot approach:
(define-syntax bulk-cond
(syntax-rules (null-pick strict-pick)
[(_ (null-pick left right) more ...)
(bulk-cond
[(and (null? left) (null? right)) equivalent]
[(and (null? left) (not (null? right))) lesser]
[(and (not (null? left)) (null? right)) greater]
more ...)]
[(_ (strict-pick left right on< on>) more ...)
(bulk-cond
[(on< left right) lesser]
[(on> left right) greater]
more ...)]
[(_ more ...)
(cond more ...)]))
But I had a flaw in my recursion that I could not bridge, so I through let me build the constituent parts:
(define-syntax-rule (null-pick left right)
(list ;will need to splice this later
[(and (null? left) (null? right)) equivalent]
[(and (null? left) (not (null? right))) lesser]
[(and (not (null? left)) (null? right)) greater]))
(define-syntax-rule (strict-pick left right on< on>)
(list ;will need to splice this later
[(on< left right) lesser]
[(on> left right) greater]))
But I could not stitch the two patterns together correctly. I know the below "cure" is worse than the ailment and is also wrong, but maybe you can offer ideas on how to proceed differently?
;wrap the above 2 macros in begin-for-syntax, with:
;(require (for-syntax rebellion/base/comparator)), then:
(define-syntax (bulk-cond stx)
(syntax-case stx ()
[(_ pre-chunks ...)
(with-syntax ([(post-chunks ...)
(for/list ([head (in-list (syntax->list #'(pre-chunks ...)))])
(if (memq (syntax-e head) '(null-pick strict-pick))
??? ;some kind of spliced call into sub-cases
???))]) ;leave the else case alone
#'(cond post-chunks ...))]))
Or maybe something simpler, where I just express what I need correctly instead of doing it:
(define-syntax (bulk-cond stx)
(syntax-case stx (null-pick strict-pick else)
[(_ (null-pick n-rest ...) ... (strict-pick s-rest ...) ... o-rest ...)
#`(cond #,@(null-pick n-rest ...) ...
#,@(strict-pick s-rest ...) ...
o-rest ...)]))
;I know this is even more wrong, but I'm flailing at this point
Would you kindly attempt a suggestion in pure Racket? I barley have a handle on what I know that I don't think I can expand to syntax-parse or other libraries, unless you really think it would be more straightforward. Anyway, thanks for reading so far.