Это возможно с помощью вспомогательного макроса, чтобы выполнить рекурсию, необходимую для поиска funct
вещей в середине.
(if-let-helper processed-bindings processed-conditions input-binding-conditions then else)
Как только он повторяется, он передает информацию из input-binding-conditions
в
processed-bindings
и processed-conditions
, останавливаясь, когда
input-binding-conditions
пусто.
(define-syntax if-let-helper
(syntax-rules ()
[(_ ([bnd val] ...) (cnd ...) () then else)
(let ([bnd val] ...)
(if (and cnd ...) then else))]
[(_ ([bnd val] ...) (cnd ...) ([binding value] . rest) then else)
(if-let-helper ([bnd val] ... [binding value]) (cnd ...) rest then else)]
[(_ ([bnd val] ...) (cnd ...) ([binding funct value] . rest) then else)
(if-let-helper ([bnd val] ... [binding value]) (cnd ... (funct binding))
rest then else)]))
(define-syntax if-let
(syntax-rules ()
[(_ (binding-funct-value ...) then else)
(if-let-helper () () (binding-funct-value ...) then else)]))
Используя его:
> (if-let ([var1 1]
[diff null? '(1 2 3 4 5)]
[var2 2])
var1
var2)
2
Чтобы объяснить это, я расскажу, как этот пример обрабатывает каждое предложение. Первоначально он превращается в этот if-let-helper
вызов:
(if-let-helper
()
()
([var1 1]
[diff null? '(1 2 3 4 5)]
[var2 2])
var1
var2)
Первые два списка начинаются пустыми, потому что он еще ничего не обработал.
(if-let-helper
([var1 1])
()
([diff null? '(1 2 3 4 5)]
[var2 2])
var1
var2)
На этом этапе он обработал первое предложение и добавил пару значений привязки в первый список «обработанных привязок». Однако в первом предложении не было funct
, поэтому оно не добавило условие во второй список «обработанных условий».
(if-let-helper
([var1 1]
[diff '(1 2 3 4 5)])
((null? diff))
([var2 2])
var1
var2)
В этот момент он обработал первые два предложения и добавил условие (null? diff)
во второй список, поскольку во втором предложении он увидел funct
.
(if-let-helper
([var1 1]
[diff '(1 2 3 4 5)]
[var2 2])
((null? diff))
()
var1
var2)
В этот момент он обработал все три предложения, поэтому он попадает в базовый вариант и преобразуется в финальные let
и if
:
(let ([var1 1]
[diff '(1 2 3 4 5)]
[var2 2])
(if (and (null? diff))
var1
var2))