I'm trying to, more or less, recreate a let construct via syntax-rules but it seems to be tripping on the use of two ellipses.
I tried writting it out as so:
(define-syntax if-let
(syntax-rules ()
[(_ (([binding value] ...)
([binding2 funct value2])
([binding3 value3] ...)) then else) (let ([binding value] ...
[binding2 value2]
[binding3 value3] ...)
(if (funct binding2) then else))]))
I figured the distinct pattern in the middle of [binding2 funct value2] would be able to provide a clear division, in terms of pattern, of when the first pattern ended and when the second one would begin but I keep getting back the error in the title.
The intended result is to be able to do something like
(if-let ([var1 1]
[diff null? '(1 2 3 4 5)]
[var2 2])
var1
var2)
and get back 2 but being able to have as many vars before and after diff as remotely desired so the order of the variables used, ultimately, doesn't matter.
Am I missing something obvious? And is this pattern feasibly able to be done with hygenic macros? Thanks for any help!
This is possible with a helper macro, to do the recursion necessary for finding the
functthings in the middle.(if-let-helper processed-bindings processed-conditions input-binding-conditions then else)As it recurs, it transfers the information in
input-binding-conditionsinto theprocessed-bindingsandprocessed-conditions, stopping when theinput-binding-conditionsis empty.Using it:
To explain this, I will step through how this example processes each clause. It initially turns into this
if-let-helpercall:The first two lists start empty because it hasn't processed anything yet.
At this point it has processed the first clause and added a binding-value pair to the first "processed-bindings" list. However, there was no
functin the first clause, so it didn't add a condition to the second "processed-conditions" list.At this point it has processed the first two clauses, and added a
(null? diff)condition to the second list because it saw thefunctthere in the second clause.It this point it has processed all three clauses, so it hits the base case and transforms into the final
letandif: