-
Notifications
You must be signed in to change notification settings - Fork 11
/
anaphoric-if.kl
38 lines (35 loc) · 1.16 KB
/
anaphoric-if.kl
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
#lang "prelude.kl"
(import (shift "prelude.kl" 1))
(import "define-syntax-rule.kl")
(import "list.kl")
(define-macro (if-non-empty cond then else)
-- Consider the following simpler implementation.
--
-- (pure `(let [it ,cond]
-- (case it
-- [(:: _ _)
-- ,then]
-- [(nil)
-- ,else])))
--
-- Since the "it" variable is bound by code generated by the macro, hygiene
-- dictates that it is only visible to the rest of the code generated by the
-- macro. Thus, it would be visible in (case it ...), but not in the caller's
-- (:: 0 it).
--
-- This is not what we want, so we override hygiene by constructing an
-- identifier which inherits the lexical scope (and the source location) of
-- one of the input syntax objects. This allows the identifier to be visible
-- to the code in that input as well.
(let [it
(ident-syntax 'it cond)]
(pure `(let [,it ,cond]
(case ,it
[(:: _ _)
,then]
[(nil)
,else])))))
(example
(if-non-empty (snoc (list 1 2 3) 4)
(:: 0 it)
(list 0)))