Ben wrote: > This kind of discussions between two groups of people, > neither of who know the other person's language very well just wind me > up something chronic!
I must say, it is pretty funny how a flamewar turned into a pretty interesting SoC project. > Anything that makes programming more fun is good, and I hope the Lisp > true way explodes into my head at some point. Here is an excerpt of an excerpt from famous Gears demo. I notice it really makes concrete what Lispniks are talking about in re macros and multi-line lambda (pity about the formatting): (defmodel gears-demo (window) ((gear-ct :initform (c-in 1) :accessor gear-ct :initarg :gear-ct)) (:default-initargs :title$ "Rotating Gear Widget Test" :kids (c? (the-kids (mk-stack (:packing (c?pack-self)) (mk-row () (mk-button-ex (" Add " (incf (gear-ct .tkw)))) (mk-button-ex ("Remove" (when (plusp (gear-ct .tkw)) (decf (gear-ct .tkw))))) (mk-entry :id :vtime :md-value (c-in "10"))) (make-instance 'gears :fm-parent *parent* :width 400 :height 400 :timer-interval (max 1 (or (parse-integer (fm^v :vtime)) :junk-allowed t) 0))))))) Don't worry, Lispniks cannot read that either. It is a delarative construction of a hierarchical GUI. That is such a common task, that I have rolled up a bunch of GUI-building macrology so that just the stuff specific to this GUI gets typed in. Since the Gears widget is a custom widget I have no macrology for that, and the wiring shows in the expression ":fm-parent *parent*" (which itself leverages Lisp special variables). And no, I cannot remember all my macrology. I can certainly read it and easily modify my GUI, because all the wiring is hidden, but if I have to build a new GUI I cut and paste from other GUIs. Let's look at just one form, which I believe destroys Alex's whole case for naming every lambda: (mk-button-ex ("Remove" (when (plusp (gear-ct .tkw)) (decf (gear-ct .tkw))))) "mk-button-ex" (a) makes fun of MS$ naming standards and (b) expands to: (make-instance 'button :fm-parent *parent* :text "remove" :on-command (c? (lambda (self) (when (plusp (gear-ct .tkw)) (decf (gear-ct .tkw)))))) The above is what one really needs to write to stick something in my GUI framework, but who wants to look at all of that when most of it is boilerplate? I need ":fm-parent *parent*" on every label and widget because of some internals requirements, I just do not want to look at it or have to remember to code it all the time (the latter not being a huge problem because I really am cutting/pasting when I build a new GUI). Is mk-button-ex some mysterious new language construct that will make multi-programmer projects collapse in a heap of programmer-specific constructs inscrutable to anyone else on the team? (a) mk-button-ex kinda tells you (1) it makes a button and (2) no, this is not part of Common Lisp, so where is the confusion? (b) control-alt-. in my IDE shows me: (defmacro mk-button-ex ((text command) &rest initargs) `(make-instance 'button :fm-parent *parent* :text ,text :on-command (c? (lambda (self) (declare (ignorable self)) ,command)) ,@initargs)) Looks a lot like the expansion, right? That is really important in making macrology easy. Once one has mastered the syntax (` , @), writing a macro gets as natural as writing out the code. (In case you are wondering, in my little example I did not need any other customizations on the button, so it is hard to make out what the initargs are doign up there. here is how they would work (also getting a little fancier by actually disabling the "Remove" button, not just making it do nothing when pressed, if the gear count is zero): (mk-button-ex ("Remove" (decf (gear-ct .tkw))) :fore-color 'red ;; Tcl/Tk will understand :enabled (c? (plusp (gear-ct .tkw)))) becomes: (make-instance 'button :fm-parent *parent* :text "remove" :on-command (c? (lambda (self) (decf (gear-ct .tkw)))) :fore-color 'red :enabled (c? (plusp (gear-ct .tkw)))) [ps. Do not try that at home, i invented the enabled thing. It really should be the Tk syntax, which I forget.] ie, I created mk-button-ex because, jeez, every button I put in a GUI I /know/ needs its own label and its own command (and the parent thing), but there are other options, too. They have to be supported if the macro is to get used all the time (we want that), but I do not want to make them positional arguments without identifying keywords, because then the code would be unreadable as well as unwritable (from memory). Needless to say, there is more macrology in the expansion. One bit of fun is .tkw. Background: in the GUIs I roll, a widget always knows its parent. I guess you noticed. Anyway, because of that, a rule can kick off code to navigate to any other widget and get information, ie, it pretty much has global scope and that means power. Now one place a rule will often look is up the hierarchy, say to a containing radio group for a radio button. So the first thing I wrote was: (upper self radio-group) -> (container-typed self 'radio-group) Hmmph. I am /always/ upper-ing off self, I am surprised I have not written a macro so I can just do (^upper radio-group). Soon. But since I often look to the containing window in rules, I was looking for something insanely short, shorter than even parentheses would allow, like ".tkw": (define-symbol-macro .tkw (nearest self window)) Nearest is like "upper" except that it is inclusive of the starting point of the search (and, no, I am not happy with the name <g>). And so it goes with Lisp macros. All the tedious boilerplate is hiiden, in ways that cannot be done with functions. Oh, I skipped that point. Look again at how the command (decf (gear-ct .tkw)) gets spliced into the lambda form as so much source code: From: (mk-button-ex ("Remove" (decf (gear-ct .tkw)))) To: (make-instance 'button :fm-parent *parent* :text "remove" :on-command (c? (lambda (self) (decf (gear-ct .tkw)))))) If mk-button-ex were a function, Lisp would try to evaluate (decf (gear-ct .tkw)) which would be pretty sad because the "self" in there would not even exist yet (the form is an /input/ to make-instance of what will become "self" by the time the macro expansion code runs. Which brings us to the idea of every multi-line lambda needing a name. Does this: (lambda (self) (when (plusp (gear-ct .tkw)) (decf (gear-ct .tkw))) Not sure what the Python would be, but maybe: lambda (self): if nearest(self,'window').gear_ct > 0: nearest(self,'window').gear_ct = \ nearest(self,'window').gear_ct - 1 Does that need a name? kenny -- Cells: http://common-lisp.net/project/cells/ "Have you ever been in a relationship?" Attorney for Mary Winkler, confessed killer of her minister husband, when asked if the couple had marital problems. -- http://mail.python.org/mailman/listinfo/python-list