| There seems to be a slight limitation in the macro system in Arc. Basically, your ability to shadow things is forcing you to always shadow them, even if you don't want to, like in this code: ; copy-structure: return exactly its argument, but
; in new cons cells
(mac copy-structure (lst) `(list ,@lst))
; (copy-structure (cons 'a 'b)) -> (a . b)
; tag-lists: take some code that makes lists, and
; return one that makes tagged lists - but doesn't
; disturb literals
(mac tag-lists (tag . body)
`(let list (fn args (cons ,tag args)) ,@body))
; (tag-lists 'nums (list 1 2 3)) -> '(nums 1 2 3)
; (tag-lists 'nums '(1 2 3)) -> '(1 2 3)
; here's the problem:
(tag-lists 'nums (copy-structure (1 2 3))) -> '(nums 1 2 3)
The problem is not that this happens (that's correct), but that there's no way to not make this happen. When you're defining copy-structure, you cannot guarantee that your definition of list is the one that will be used, and if you use copy-structure, you must be aware of the fact that the binding of list matters. This makes the implementation of copy-structure part of its definition (since you have to be aware of the implementation in order to use copy-structure correctly).In some cases, this may be what you want; but it also might not. Luckily, there's a simple way to allow both possibilities. What you want to do is to allow someone to write copy-structure like this, ; note the lack of quotation of the symbol list
(mac copy-structure (lst) (cons list lst))
so that the list function used is the one that copy-structure had. This is just like letting someone type in a function literal at the command line, instead of typing a symbol and having arc evaluate it (except it's much more useful for macros).The only change is in the function literal? in ac.scm. (define (literal? x)
(or (boolean? x)
(char? x)
(string? x)
(number? x)
(procedure? x) ; New line here!
(eq? x '())))
This will allow people to write hygienic macros if they want to, while not requiring it in any way.(edited for formatting) |