[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how expressive are they?

   > 3. In your HTML from Perl example, if all this was done at "run-time"
   > how did you debug production systems that you did not have access to?
   > (The compile-time vs. run-time distinction for data-driven programs
   > is not a trivial one). 

   Can you explain this question further?  I can't imagine how I would
   debug any system I didn't have access to, regardless of how it worked.

If one is merely generating or transforming a lot of textual data
(dependent on other data) -- the emphasis being on 'data' not
'program' -- then it probably is actually clearer to write them in
terms of lambdas/functions (that will help debugging when you have to
deploy on a system and then debug it there -- i.e. sometimes w/out
access to sources :). With macros, since they work mostly at/before
compile time and work mostly on 'code' .. one has to be careful to
ensure that the resultant code is debuggable. Most people I know,
still rely on ensuring the correctness of macros by inspection of the
expanded code -- which is not at all the same way they approach the
problem of ensuring the correctness of functions -- the references
Anton posted point this out too. 

   > Kragen asks:
   > > Do macros offer *anything* other than shorter programs?
   > Gee.. I'd turn that around and ask of languages that don't have macros
   > .. "what do you offer me in terms of facilities to write shorter
   > programs?" It's not exactly a small advantage :)

   Yes, I find that advantage important, too.

   Do macros offer any other advantages, like better separation of
   concerns, reduction of duplication, etc.?  I have seen several
   assertions that they do reduce duplication in ways that lightweight
   lambda syntax can't, or that they do it more easily, but I haven't
   seen any convincing examples.

   (Here I speak specifically of one kind of duplication: the need to
   explain one decision in two places, so that you must change both
   places if you change the decision, but the program does not
   automatically detect if you forget and change only one place.
   Programming consists largely of removing this kind of duplication.)

I'm confused.. are you talking about duplication or about dependency
tracking support? Macros are no better than functions in that
regard.. and what you are talking about is often left to "tool
support" rather than treated as a base language capability. Personally
speaking, I'm with you -- I've never liked the somewhat arbitrary
separation we have in modern systems where because
IDE's/debuggers/loaders/runtimes tend to be monolithic programs, they
are not available to the programmer to re-use/extend/bug-fix.

   > Anecdotally, I went and grepped through our pretty large code base
   > (the portions that are in Lisp), and was a bit surprised when I
   > didn't see that many macros as I expected to. I'd say 60-70% could
   > probably be replaced in-place w/ closure-style w/ no effect on the
   > callees.. but the remaining might be a bit harder.

   Lisp's lambda syntax might make that refactoring a painful burden on
   the callers, although it might cost less in a language like Smalltalk.

   As a Lisp novice, I'd love to hear about some of the tougher ones.  I
   see 'loop', of course.

The big one in our system is really similar to the define-class that I
think Dan Weinreb pointed out. We have a similar facility that defines
classes based on database tables.. that expands into classes/methods
that define object managers (consider that you may want to maintain a
hash-table of objects in your database that is indexed by it's primary
keys -- which are often n columns where n > 1 :), select/update/delete
transactions, even a matcher function so you can say things like
(lookup-objects object-manager :some-column value1 :some-other-column
value2). That alone saves us oodles of code, but the system also
modifies setf and uses clos/flavors facilities to introduce
"write-restriction" clauses.. so that when a programmer creates an
object of this flavor and does (setf (some-field o) value) the db code
actually kicks in to enqueue transactions to the server etc. And it
does things like associations etc. (should a parent be deleted when
all the children of an n-ary relationship get deleted?) Pretty cool
stuff. (It's like having a Perl facility to modify the semantics of
what Perl does when you do "s = foo;" or "s =~ bar;" :)

   > Trevor -- Personally speaking, I've found the loss of macros really
   > painful on those occasions when I've really needed them -- think "a
   > deadline to get something up and running by 9 am tomorrow, and several
   > pages of repetitive code to write, but no time to write an entire
   > parser/rewriter/pre-processor/code-generator" :) (but I agree that I
   > don't view macros as indispensable as say functions).

   If I had twelve hours to get something up and running and several
   pages of repetitive code to write, in, say, Perl, I'd spend an hour or
   two writing a (Unix-style, string-based) preprocessor.  I imagine a
   Lisp wizard could do the same thing much more quickly, since Lisp has
   READ and WRITE.
You are talking about Lisp and Perl. In Lisp I don't have such
problems.. I was talking about languages w/out real macros -- and when
I sorely missed them, because had I had such facilities it would have
meant a good night's sleep.. instead of hacking yet another
pre-processor and debugging it :)