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 var
s 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
funct
things 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-conditions
into theprocessed-bindings
andprocessed-conditions
, stopping when theinput-binding-conditions
is empty.Using it:
To explain this, I will step through how this example processes each clause. It initially turns into this
if-let-helper
call: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
funct
in 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 thefunct
there in the second clause.It this point it has processed all three clauses, so it hits the base case and transforms into the final
let
andif
: