Arc Forumnew | comments | leaders | submit | zunz's commentslogin
1 point by zunz 6120 days ago | link | parent | on: Unhygienic macros?

Sure, you could indeed use markup to make the burden of uniq-ing lower - that mitigates the impact of the design decision, but doesn't address the underlying issue.

Fundamentally, hygienic macro systems assume that capture is unintentional by default (although you can ask for it), rather than assuming that capture is the default and you have to ask to avoid it.

When writing macros, which is the more common default? Since arc appears to be using macros extensively in it's implementation, perhaps it was found that capture was actually more common but that implies a language implementation issue has been 'promoted' to a language design issue. Maybe I shouldn't see those as seperate - this is LISP after all :-)

Hygiene is one of those things that doesn't bite you when the code-base (or more importantly, the idea-space) is small. But as the system gets bigger (and I'm assuming we all want arc to be good for big problems), you can't keep it all in your head anymore and spending many hours debugging a complex application to find a simple macro capture oversight bit you is not fun.

-----

2 points by zunz 6120 days ago | link | parent | on: Unhygienic macros?

Thanks - manually generating unique variables where needed solves the arguably biggest part of the hygiene problem.

It's then part of macro writer discipline to remember to guard your introduced names. Fair enough. If you're writing macros, you arguably should know what you're doing.

It does still leave the problem of the macro using bindings from it's expansion point rather than it's definitition point i.e. you redefine if() and the macro uses that rather than the original definition and thus behaves badly.

Admittedly, redefining core parts of the language and using macros can be a 'don't do that then' sort of thing but considering arc's focus on language exploration, I would have thought having automatic guard-rails to be 'a good thing' (TM) (which is what hygiene really is IMO i.e. avoiding suprises from idea X interacting strangely with idea Y).

I've always felt the biggest benefit of hygiene is that it makes macro writing a bit more approachable for mere mortals. But considering the audience and arc's author(s), maybe that's not worth worrying about :-)

-----

1 point by tjr 6120 days ago | link

Yeah, it seems like, "let the programmer do whatever the want, no matter how silly it seems, because they might actually have a valid reason" drove a non-trivial amount of Arc design.

This sort of "programmer power" is similar to what you get in C. You can't redefine the language with C, but you can do some pretty nasty things if you want to. Or even if you make a subtle, honest mistake. Or even if you use C at all. ;-)

-----

1 point by kennytilton 6119 days ago | link

Mortals need not fear. Avoiding variable capture is easy albeit mildy tedious, and deliberate variable capture can be quite useful. I have seen good Schemers explaining why Scheme's macros were just as good as CL's and they convinced me they were not. :)

-----

1 point by petermichaux 6120 days ago | link

;;;;;;;;;;; the following doesn't work reliably ;;;;;;;;;;

;;; in Arc + is defined

;;; macro writers code depends on Arc's + ;;; but doesn't insure it always uses Arc's +

(mac foo () (list '+ 1 2))

;;; app writers code

(* 2 (foo)) ;;; 6

;;; app writer doesn't know foo depends on Arc's + ;;; and decides to redefine +

(= + (fn ((o x) (o y)) (prn "gotcha")))

(* 2 (foo)) ;;; error

;;;;;;;;;;;;;;;;;; the following works ;;;;;;;;;;;;;;;;;;;;

;;; in Arc + is defined

;;; macro writers code is tricky and ugly ;;; but will always use Arc's +

(= g (uniq))

(eval (list '= g '+))

(eval (list 'mac 'foo `() `(list (quote ,g) 1 2)))

;;; app writers code

(* 2 (foo)) ;;; 6

;;; redefining + doesn't affect the addtion function ;;; used in the foo macro

(= + (fn ((o x) (o y)) (prn "gotcha")))

(* 2 (foo)) ;;; 6

;;;;;;;;;;;; if foo is a function then it is easy ;;;;;;;;;;

;;; in Arc + is defined

;;; library writers code is easy because ;;; the original + can be in a closure

(= foo ((fn () (let plus + (fn () (plus 1 2))))))

;;; app writers code

(* 2 (foo)) ;;; 6

;;; redefining + doesn't affect the addtion function ;;; used in the foo function

(= + (fn ((o x) (o y)) (prn "gotcha")))

(* 2 (foo)) ;;; 6

-----