Macros are subject to function shadowing, which means
(flet ((if () 999)) (if))
is well defined and returns 999. That's because if is a macro, not a special form.
Special forms, on the other hand, take precedent over all variables, even those in a narrow scope. So
(flet ((cond () 999)) (cond))
will actually return (), not 999, since the cond special form takes precedent over the local function and returns () (since it's been given no arguments.
Since drawing an arbitrary line between built-in macros and special forms like this is fairly unintuitive, I propose that we allow special forms to be shadowed. This does mean that you can basically monkeypatch your way into an unworkable function scope, by redefining all of the primitives. But I think it's worth it.
Macros are subject to function shadowing, which means
is well defined and returns
999
. That's becauseif
is a macro, not a special form.Special forms, on the other hand, take precedent over all variables, even those in a narrow scope. So
will actually return
()
, not999
, since thecond
special form takes precedent over the local function and returns()
(since it's been given no arguments.Since drawing an arbitrary line between built-in macros and special forms like this is fairly unintuitive, I propose that we allow special forms to be shadowed. This does mean that you can basically monkeypatch your way into an unworkable function scope, by redefining all of the primitives. But I think it's worth it.