Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

macro for shorter array syntax

24 views
Skip to first unread message

Tamas Papp

unread,
May 8, 2007, 9:57:54 PM5/8/07
to
Instead of writing

(aref my-array 1 2 3)

and

(setf (aref my-array 1 2 3) 4)

repeatedly inside a function, I thought it would be nice to have the syntax

(access-array (my-array my-access)
...
(my-access 1 2 3)
(setf (my-access 1 2 3) 4)
...)

(I have read this on Graham's website for Arc). I tried implementing
it as a macro:

(defmacro array-access ((array access) &rest body)
`(flet ((,access (&rest indexes)
(apply 'aref ,array indexes)))
,@body))

(defparameter *a* (make-array 5 :initial-contents '(0 1 2 3 4)))

(array-access (*a* a-a)
(a-a 4))

But I don't know

1. what to do about the setf part,

2. avoid the function call overhead (ideally, the macro would just
replace access => aref array in body).

Thanks,

Tamas

--
Posted via a free Usenet account from http://www.teranews.com

Kent M Pitman

unread,
May 8, 2007, 11:55:09 PM5/8/07
to
Tamas Papp <tkp...@gmail.com> writes:

The function call overhead may be imagined. Compilers may inline
the aref call when you compile things. Some will like it if you make
declarations of various kinds. Some may be able to infer what they need
from the call. Some may like it if you declare the flet call to be
something that can/should be inlined. ... or you may also want to
prefer the macro example below.

You can solve your direct question with the following. Note that you'll
want to be using (apply #'aref ...) not (apply 'aref ...), since the
latter is not necessarily defined to work.

(defmacro array-access ((access array) &body body)
(let ((temp (gensym (symbol-name access))))
`(let ((,temp ,array))
(flet ((,access (&rest indexes)
(apply #'aref ,temp indexes))
((setf ,access) (val &rest indexes)
(setf (apply #'aref ,temp indexes) val)))
(declare (inline #',access))
,@body))))

(array-access (foo (make-array 5))
(print (foo 3))
(print (setf (foo 3) 4))
(print (foo 3))
:done)

NIL
4
4
:DONE

(pprint (macroexpand-1 '(array-access (foo (make-array 5))
(print (foo 3))
(print (setf (foo 3) 4))
(print (foo 3))
:done)))

(LET ((#:FOO5952 (MAKE-ARRAY 5)))
(FLET ((FOO (&REST INDEXES)
(APPLY #'AREF #:FOO5952 INDEXES))
((SETF FOO) (VAL &REST INDEXES)
(SETF (APPLY #'AREF #:FOO5952 INDEXES) VAL)))
(DECLARE (INLINE #'FOO))
(PRINT (FOO 3))
(PRINT (SETF (FOO 3) 4))
(PRINT (FOO 3))
:DONE))

I prefer macrolet, with a few caveats...

* Make sure to bind something to the array expression to avoid reevaluation.

* I suggest reversing the args, btw, since the thing you call ACCESS
will be used as a function, so looks more natural at the head of parens,
and more importantly because the thing that's the array is an evaluable
structure and will look much better if you make it not be at the head of
a list, where it looks like a function call. It also makes it look
more like a binding form with (var val) kind of syntax.

* I also suggest using &body instead of &rest in the array-access macro.
Some Lisp IDE's will augment the environment to make
(array-access (foo foo-array)
...)
indent as a body when you do that. When you use &rest, they are
intended to treat it as a function call, and indent it as:
(array-access (foo foo-array)
...)

* And I suggest making it handle multiple bindings so you don't have to
nest them.

(defmacro array-access (bindings &rest body)
(let ((temp-bindings (mapcar #'(lambda (binding)
`(,(gensym (symbol-name (first binding)))
,(second binding)))
bindings)))
`(let ,temp-bindings
(macrolet ,(mapcar #'(lambda (binding temp-binding)
(destructuring-bind (access array) binding
`(,(first binding) (&rest indexes)
`(aref ,',(first temp-binding)
,@indexes))))
bindings temp-bindings)
,@body))))

(let ((foo-array (make-array 3)))
(array-access ((foo foo-array) (bar (make-array 3)))
(dotimes (i 3) (print (list i (foo i) (bar i))))
(dotimes (i 3) (setf (foo i) (* i i)) (setf (bar i) (1+ (foo i))))
(dotimes (i 3) (print (list i (foo i) (bar i))))
foo-array))

(0 NIL NIL)
(1 NIL NIL)
(2 NIL NIL)
(0 0 1)
(1 1 2)
(2 4 5)
#(0 1 4)

(pprint (macroexpand-1 '(array-access ((foo foo-array) (bar (make-array 3)))
(dotimes (i 3) (print (list i (foo i) (bar i))))
(dotimes (i 3) (setf (foo i) (* i i)) (setf (bar i) (1+ (foo i))))
(dotimes (i 3) (print (list i (foo i) (bar i))))
foo-array)))

(LET ((#:FOO5873 FOO-ARRAY) (#:BAR5874 (MAKE-ARRAY 3)))
(MACROLET ((FOO (&REST INDEXES)
`(AREF #:FOO5873 ,@INDEXES))
(BAR (&REST INDEXES)
`(AREF #:BAR5874 ,@INDEXES)))
(DOTIMES (I 3) (PRINT (LIST I (FOO I) (BAR I))))
(DOTIMES (I 3) (SETF (FOO I) (* I I)) (SETF (BAR I) (1+ (FOO I))))
(DOTIMES (I 3) (PRINT (LIST I (FOO I) (BAR I))))
FOO-ARRAY))

Btw, one last note that I recommend but didn't integrate into the
above examples. Call your macro WITH-ARRAY-ACCESS rather than just
ARRAY-ACCESS and you'll make me tons happier. WITH-xxx forms are
common in CL and easy to recognize and read. Making it say
array-access makes it look to someone who didn't see the definition
like you're DOING the array access.

I didn't test the above stuff extensively, but it looks like it
probably works based on the couple of quickie examples I tried.
Caveat emptor. I hope it helps.

Message has been deleted

D Herring

unread,
May 9, 2007, 12:04:06 AM5/9/07
to

First take:
(defmacro access-array (alias &body body)
(let ((b (mapcar (lambda (x)
(cond ((eql (car x)
(cadr alias))
(cons 'aref (cons (car alias)
(cdr x))))
((and (listp x)
x)
(mapcar (lambda (y)
(if (and (listp y)
y)
`(access-array ,alias ,y)
y))
x))
(t x)))
body)))
(if (cadr b)
(cons 'progn b)
(car b))))

Test case:
(access-array (my-array my-access)
(my-access 1 2 3)
(setf (my-access 1 2 3) 4))

expands to
(PROGN
(AREF MY-ARRAY 1 2 3)
(SETF (AREF MY-ARRAY 1 2 3) 4))

Note: This macro needs some rework (e.g. refactor as a macrolet and use
gensym properly) before it would be ready for heavy use. I especially
dislike the need to create a new block to handle multiple nested
expressions.

It might be cleaner to simply define 'my-access as a macro:
(defmacro my-access (&rest idx)
`(aref my-array ,@idx))


(my-access 1 2 3)
(setf (my-access 1 2 3) 4)

(unintern 'my-access)

- Daniel

Kent M Pitman

unread,
May 9, 2007, 12:11:20 AM5/9/07
to
Madhu <eno...@meer.net> writes:

> (defmacro array-access ((array access) &rest body)

> `(macrolet ((,access (&rest indices)
> `(aref ,,array ,@indices)))
> ,@body))

You want ,',array because you don't want the variable array to get
re-evaluated in the inner context.

If you did, then doing:

(defvar *foo* '(error "lose"))

(array-access (*foo* foo)
(foo 0))

would signal an error at runtime as you see here:

(defmacro array-access ((array access) &rest body)

`(macrolet ((,access (&rest indices)
(let ((expansion `(aref ,,array ,@indices)))
(print `((,',access ,@indices) expanded to ,expansion)
*trace-output*)
expansion)))
,@body))
ARRAY-ACCESS

(array-access (*foo* foo)
(print (foo 0)))

((FOO 0) EXPANDED TO (AREF (ERROR "lose") 0))
Error: lose

Madhu

unread,
May 9, 2007, 12:17:10 AM5/9/07
to
* Kent M Pitman <ud51ad...@nhplace.com> :

|
| (defmacro array-access ((access array) &body body)
| (let ((temp (gensym (symbol-name access))))
| `(let ((,temp ,array))
| (flet ((,access (&rest indexes)
| (apply #'aref ,temp indexes))
| ((setf ,access) (val &rest indexes)
| (setf (apply #'aref ,temp indexes) val)))

Dont you have to call the setf expander explicitly here? SETF can't
figure it out at runtime.

| ,@body))))

--
Best Regards
Madhu

fairchil...@gmail.com

unread,
May 9, 2007, 12:26:42 AM5/9/07
to

I'm no expert but would this work for you?

(defmacro with-array ((var array) &body body)
`(macrolet ((,var (&body args)
`(aref ,,array ,@args)))
,@body))

(defparameter *my-array* (make-array '(10 10 10)))

(with-array (v *my-array*)
(setf (v 1 2 3) 100)
(print (v 1 2 3)))

I think the macro might need a gensym on the array parameter.

Good luck!

AnthonyF

Kent M Pitman

unread,
May 9, 2007, 12:30:23 AM5/9/07
to
Madhu <eno...@meer.net> writes:

What can't it figure out? I admit I was in a hurry, and could easily
have made a mistake, but I _think_ I got it right.

It should turn
(setf (foo index) val)
into
(funcall #'(setf foo) val index)

In fact, in general, get-setf-expansion is only useful if you're manipulating
source text, which you're not doing in the FLET case. You need to be in a
macro or automatic programming context, upstream of syntactic analysis, for
this to be useful. It only "worked" for you here in your previous example:

(defmacro array-access ((array access) &rest body) ;NOT RECOMMENDED
`(labels ((,access (&rest indexes)
(apply 'aref ,array indexes))
((setf ,access) (newval &rest indices)
(multiple-value-bind (vars vals new-vars setter accessor)
(get-setf-expansion `(aref ,,array ,@indices))
(apply (compile nil `(lambda ,(nconc new-vars vars) ,setter))
(cons newval vals)))))
,@body))

because you forced a compilation step at runtime, which is completely
artificial and DREADFULLY slow. This is a good way to make your code
orders of magnitude slower than you expect it to be... or maybe you were
trying to wage a campaign of voluntary abstinence against the use of
assignment? :)

Madhu

unread,
May 9, 2007, 12:28:17 AM5/9/07
to
* Kent M Pitman <u8xbyd...@nhplace.com> :

|> (defmacro array-access ((array access) &rest body)
|> `(macrolet ((,access (&rest indices)
|> `(aref ,,array ,@indices)))
|> ,@body))
|
| You want ,',array because you don't want the variable array to get
| re-evaluated in the inner context.

Indeed. I assumed evaluating the array in that context was desired
here. Which was wrong

| (defmacro array-access ((array access) &rest body)
| `(macrolet ((,access (&rest indices)
| (let ((expansion `(aref ,,array ,@indices)))
| (print `((,',access ,@indices) expanded to ,expansion)
| *trace-output*)
| expansion)))
| ,@body))

SO that's how one is supposed do debug MACROLETs!
(I never figured that one out:)
--
Regards
Madhu

Juho Snellman

unread,
May 9, 2007, 12:35:16 AM5/9/07
to

See 5.1.2.5.

--
Juho Snellman

Barry Margolin

unread,
May 9, 2007, 12:41:43 AM5/9/07
to
In article <878xbyo...@pu100877.student.princeton.edu>,
Tamas Papp <tkp...@gmail.com> wrote:

> Instead of writing
>
> (aref my-array 1 2 3)
>
> and
>
> (setf (aref my-array 1 2 3) 4)
>
> repeatedly inside a function, I thought it would be nice to have the syntax
>
> (access-array (my-array my-access)
> ...
> (my-access 1 2 3)
> (setf (my-access 1 2 3) 4)
> ...)

By analogy with WITH-SLOTS and WITH-ACCESSORs, I recommend calling this
WITH-ARRAY.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***

Kent M Pitman

unread,
May 9, 2007, 12:43:28 AM5/9/07
to
Madhu <eno...@meer.net> writes:

The other way is to do it outboard, taking advantage of &ENVIRONMENT info
to force expansion in the right context...

(defmacro debug-macro-call (form &environment env)
(let ((expansion (macroexpand-1 form env)))
(print (list form '=expands-to=> (macroexpand-1 form env))
*trace-output*)
expansion))

(defmacro array-access ((array access) &rest body)
`(macrolet ((,access (&rest indices)
`(aref ,,array ,@indices)))
,@body))

(array-access (*foo* foo)
(debug-macro-call (foo 0)))

((FOO 0) =EXPANDS-TO=> (AREF (ERROR "lose") 0))
Error: lose

Madhu

unread,
May 9, 2007, 12:48:53 AM5/9/07
to
* Kent M Pitman <u4pmmd...@nhplace.com> :

|> | (defmacro array-access ((access array) &body body)
|> | (let ((temp (gensym (symbol-name access))))
|> | `(let ((,temp ,array))
|> | (flet ((,access (&rest indexes)
|> | (apply #'aref ,temp indexes))
|> | ((setf ,access) (val &rest indexes)
|> | (setf (apply #'aref ,temp indexes) val)))
|>
|> Dont you have to call the setf expander explicitly here? SETF can't
|> figure it out at runtime.
|>
|> | ,@body))))
|
| What can't it figure out? I admit I was in a hurry, and could easily
| have made a mistake, but I _think_ I got it right.

(macroexpand-1 '(array-access (*a* a-a) (setf (a-a 1) 666)))
=> (LET ((#:*A*7952 A-A))
(FLET ((*A* (&REST INDEXES)
(APPLY #'AREF #:*A*7952 INDEXES))
((SETF *A*) (VAL &REST INDEXES)
(SETF (APPLY #'AREF #:*A*7952 INDEXES) VAL)))
^^^^^^^^^^^^^^^^^^^^^^
(SETF (A-A 1) 666))), T

The form I was worried about was the (SETF APPLY) in the above
expansion.

| It should turn
| (setf (foo index) val)
| into
| (funcall #'(setf foo) val index)

| In fact, in general, get-setf-expansion is only useful if you're manipulating
| source text, which you're not doing in the FLET case. You need to be in a
| macro or automatic programming context, upstream of syntactic analysis, for
| this to be useful. It only "worked" for you here in your previous example:

[snip]


| because you forced a compilation step at runtime, which is completely
| artificial and DREADFULLY slow. This is a good way to make your code
| orders of magnitude slower than you expect it to be... or maybe you were
| trying to wage a campaign of voluntary abstinence against the use of
| assignment? :)

[Well, the snipped form was meant to be sarcastic, and show general
contempt for the syntax, and intended as disparagement, not as
recommendation of good style :)]

But I didnt think you could get by without getting the setf form at
runtime here.
--
Regards
Madhu

Madhu

unread,
May 9, 2007, 12:53:35 AM5/9/07
to
* Juho Snellman <slrnf42js4...@sbz-30.cs.Helsinki.FI> :

Indeed. Thanks.
--
Madhu

Kent M Pitman

unread,
May 9, 2007, 1:12:51 AM5/9/07
to
Madhu <eno...@meer.net> writes:

Just so you don't think this was an accident, see the following
background material (X3J13 issue SETF-OF-APPLY):

http://www.lispworks.com/documentation/HyperSpec/Issues/iss310_w.htm

Jon Harrop

unread,
May 13, 2007, 2:26:18 AM5/13/07
to
D Herring wrote:
> Tamas Papp wrote:
>> Instead of writing
>>
>> (aref my-array 1 2 3)
>>
>> and
>>
>> (setf (aref my-array 1 2 3) 4)
>>
>> repeatedly inside a function, I thought it would be nice to have the
>> syntax
>>
>> (access-array (my-array my-access)
>> ...
>> (my-access 1 2 3)
>> (setf (my-access 1 2 3) 4)
>> ...)

You can do that by partially applying the array to curried get and set
functions:

let f a ... =
let get = Array.get a
let set = Array.set a
...

> (defmacro access-array (alias &body body)
> (let ((b (mapcar (lambda (x)
> (cond ((eql (car x)
> (cadr alias))
> (cons 'aref (cons (car alias)
> (cdr x))))
> ((and (listp x)
> x)
> (mapcar (lambda (y)
> (if (and (listp y)
> y)
> `(access-array ,alias ,y)
> y))
> x))
> (t x)))
> body)))
> (if (cadr b)
> (cons 'progn b)
> (car b))))

ROTFL.

--
Dr Jon D Harrop, Flying Frog Consultancy
The F#.NET Journal
http://www.ffconsultancy.com/products/fsharp_journal/?usenet

Chris Russell

unread,
May 13, 2007, 11:10:49 AM5/13/07
to
On May 13, 7:26 am, Jon Harrop <j...@ffconsultancy.com> wrote:
> D Herring wrote:
> > Tamas Papp wrote:
> >> Instead of writing
>
> >> (aref my-array 1 2 3)
>
> >> and
>
> >> (setf (aref my-array 1 2 3) 4)
>
> >> repeatedly inside a function, I thought it would be nice to have the
> >> syntax
>
> >> (access-array (my-array my-access)
> >> ...
> >> (my-access 1 2 3)
> >> (setf (my-access 1 2 3) 4)
> >> ...)
>
> You can do that by partially applying the array to curried get and set
> functions:
>
> let f a ... =
> let get = Array.get a
> let set = Array.set a
> ...
Congratulations, that's nearly as concise as the equivalent lisp
(macrolet ((my-access (&body rest) ;Untested
`(aref a ,@rest))))
...)

Now the actual question people are trying to answer on this thread is;
How can we abstract away this cruft so that we never have to look at
it/write it again?

Maybe when you've finished ROTFLing you can let us know what the OCAML
answer is.

Jon Harrop

unread,
May 14, 2007, 2:56:33 AM5/14/07
to
Chris Russell wrote:
> Now the actual question people are trying to answer on this thread is;
> How can we abstract away this cruft so that we never have to look at
> it/write it again?

Adopt currying.

> Maybe when you've finished ROTFLing you can let us know what the OCAML
> answer is.

Already does it.

Chris Russell

unread,
May 14, 2007, 8:17:59 AM5/14/07
to
On May 14, 7:56 am, Jon Harrop <j...@ffconsultancy.com> wrote:
> Chris Russell wrote:
> > Now the actual question people are trying to answer on this thread is;
> > How can we abstract away this cruft so that we never have to look at
> > it/write it again?
>
> Adopt currying.

Well that's great but even with currying it's nicer to read or write:

(with-arrays (x y z w (a-very-long-name short))
....)

then:

let xg = Array.get x
let xs = Array.set x
let yg = Array.get y
let ys = Array.set y
let zg = Array.get z
let zs = Array.set z
let wg = Array.get w
let ws = Array.set w
let shortg = Array.get a-very-long-name
let shorts = Array.set a-very-long-name
....

Which is why people have written the longer macros earlier up thread,
and why I was asking what you could do in ocaml to save yourself from
having to write this.

Jon Harrop

unread,
May 14, 2007, 7:54:48 PM5/14/07
to
Chris Russell wrote:
> let xg = Array.get x
> let xs = Array.set x
> let yg = Array.get y
> let ys = Array.set y
> let zg = Array.get z
> let zs = Array.set z
> let wg = Array.get w
> let ws = Array.set w
> let shortg = Array.get a-very-long-name
> let shorts = Array.set a-very-long-name
> ....
>
> Which is why people have written the longer macros earlier up thread,
> and why I was asking what you could do in ocaml to save yourself from
> having to write this.

You might try:

let xg, yg, zg = map3 get (x, y, z)

but you'd probably just use "x.(i)" instead of "Array.get x i" anyway,
because it's shorter. That notation only applies to arrays but you can
write macros to add new syntaxes. I once wrote a macro to support
functional arrays (trees) but it is quite tedious to have to reinvent
syntax yourself all the time.

In F# you can userload the "x.[i]" syntax, which is then used for lists,
arrays, sets and even hash tables. But there are no F# macros so you can't
extend the syntax.

Raffael Cavallaro

unread,
May 15, 2007, 12:03:04 AM5/15/07
to
On 2007-05-14 19:54:48 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> But there are no F# macros so you can't
> extend the syntax.

I can't believe you think you're going to get any traction for such a
language in c.l.l.

Jon Harrop

unread,
May 15, 2007, 4:20:21 AM5/15/07
to

I don't think customised syntax (or EVAL) is so important. I am starting to
appreciate run-time types though... :-)

Raffael Cavallaro

unread,
May 15, 2007, 10:57:37 AM5/15/07
to
On 2007-05-15 04:20:21 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> I don't think customised syntax (or EVAL) is so important.

Clearly *you* don't think macros are important else you would never
have given F# a second glance, much less be touting it here. My point
is that the overwhelming majority of Common Lisp users *do* think that
macros are important, and so will have zero interest in F#. This being
the case - that Common Lisp users will have no interest in a macro-less
language like F#, it's a bit mystifying that you continue to advocate
it here.


> I am starting to
> appreciate run-time types though... :-)

Maybe there's hope for you yet ;^)

Jon Harrop

unread,
May 15, 2007, 12:48:47 PM5/15/07
to
Raffael Cavallaro wrote:
> On 2007-05-15 04:20:21 -0400, Jon Harrop <j...@ffconsultancy.com> said:
>> I don't think customised syntax (or EVAL) is so important.
>
> Clearly *you* don't think macros are important else you would never
> have given F# a second glance, much less be touting it here. My point
> is that the overwhelming majority of Common Lisp users *do* think that
> macros are important,

I don't think that is true.

> and so will have zero interest in F#.

The registration page for the F# Journal asks people what their language
background is and Lisp/Scheme is the third most popular after C++ and C#.
So there are a significant number of Lisp/Scheme programmers interested in
F#. The same is true of OCaml.

I believe that many people in the Lisp community are perfectly open-minded
when it comes to other languages. Only a very vocal minority give extremely
defensive replies that are seen here so often.

The eye opener is always seeing how easily you can do things in other
languages, like the symbolic simplifier I posted. Most people don't want to
have to reinvent basic syntax (like array accessing) and pattern matching
themselves. They just want to pick a decent GP language and get on with
some work.

Dan Bensen

unread,
May 15, 2007, 2:31:54 PM5/15/07
to
> Raffael Cavallaro wrote:
>> My point is that the overwhelming majority of Common Lisp users
>> *do* think that macros are important,

Jon Harrop wrote:
> I don't think that is true.

I think you're a troll.

--
Dan
www.prairienet.org/~dsb/

Raffael Cavallaro

unread,
May 15, 2007, 3:39:57 PM5/15/07
to
On 2007-05-15 12:48:47 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> Most people don't want to
> have to reinvent basic syntax (like array accessing) and pattern matching
> themselves. They just want to pick a decent GP language and get on with
> some work.

If one is only using lisp macros to "reinvent basic syntax" then one is
largely missing their point. Their real power is allowing one to define
domain specific languages. Anyone who thinks "I wish there were a
language as powerful as Common Lisp but without those annoying macros"
is missing much of the power of Common Lisp.

For those who need a concrete example, I suggest Peter Siebel's
_Practical Common Lisp_ , chapters 7 & 8 (macro basics), 24 (building a
dsl from macros), and 25 (using the dsl macros from the previous
chapter in a real working example).

Kent M Pitman

unread,
May 15, 2007, 7:09:08 PM5/15/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> Raffael Cavallaro wrote:
> > On 2007-05-14 19:54:48 -0400, Jon Harrop <j...@ffconsultancy.com> said:
> >> But there are no F# macros so you can't
> >> extend the syntax.
> >
> > I can't believe you think you're going to get any traction for such a
> > language in c.l.l.
>
> I don't think customised syntax (or EVAL) is so important.

I think the phrasing that will help you is

"I don't think I've found a need for customized syntax (or EVAL) myself."

That phrase states a fact about yourself and your use.

The sentence you've chosen states a fact that remarks on other people's
usage and that suggests other people's prior statements that this is
important is wrong. Do you mean to do that?

Raffael Cavallaro

unread,
May 16, 2007, 1:10:32 AM5/16/07
to
On 2007-05-15 19:09:08 -0400, Kent M Pitman <pit...@nhplace.com> said:

> The sentence you've chosen states a fact that remarks on other people's
> usage and that suggests other people's prior statements that this is
> important is wrong. Do you mean to do that?

Yes, he really is that presumptuous.

Jon Harrop

unread,
May 16, 2007, 4:54:34 AM5/16/07
to
Raffael Cavallaro wrote:
> If one is only using lisp macros to "reinvent basic syntax" then one is
> largely missing their point. Their real power is allowing one to define
> domain specific languages. Anyone who thinks "I wish there were a
> language as powerful as Common Lisp but without those annoying macros"
> is missing much of the power of Common Lisp.

Absolutely, but Lisp is in the unique position of having no syntax to start
with so programmers are likely to extend the syntax using macros for
operations that already have custom syntax in other languages. For example,
this whole thread is redundant in most other languages because they provide
a built-in syntax for array access.

Jon Harrop

unread,
May 16, 2007, 4:57:04 AM5/16/07
to

The objective evidence is: macros are common in Lisp and rare in OCaml.

Jon Harrop

unread,
May 16, 2007, 5:08:52 AM5/16/07
to
Kent M Pitman wrote:
> I think the phrasing that will help you is
>
> "I don't think I've found a need for customized syntax (or EVAL) myself."

That does not help.

> That phrase states a fact about yourself and your use.

I am not making a statement about myself. I am making a statement about the
rarity of macros in languages with non-trivial syntax that support macros,
like OCaml.

> The sentence you've chosen states a fact that remarks on other people's
> usage and that suggests other people's prior statements that this is
> important is wrong. Do you mean to do that?

Yes.

I have created custom syntaxes using macros and I appreciate that they can
be useful, so your statement does not apply to me.

If a language provides the most common forms of syntax (array element
access, hash table lookup, curried anonymous functions, pattern matching
syntax, try finally etc.) then the need for macros is greatly reduced. So
much so that other language features become more important.

You are rightly demanding evidence for this. Well, Lisp is not a new idea.
Macros have been around for a long time and they never got serious traction
(e.g. compared to static typing).

A few languages provide both non-trivial syntax and macros (e.g. OCaml and
Mathematica). The use of macros in other languages is tiny compared to
Lisp. There are probably <100 OCaml macros out there compared to millions
in Lisp.

I deliberately phrased my statement to be about the relative importance of
macros because macros are essential in Lisp but basically redundant in most
other general-purpose programming languages because all the common cases
are already covered.

Message has been deleted

Jon Harrop

unread,
May 16, 2007, 7:24:03 AM5/16/07
to
java...@gmail.com wrote:
> You seem to completely miss the reason why Lispers stay with Lisp.

They don't.

> There is certainly no Lisper out there not having tried any sort of
> other languages, and most of them turned back to Lisp.

That is certainly true for diehard Lispers, but they are comparatively rare.
Most readers of c.l.l are curious and not devoted.

John Thingstad

unread,
May 16, 2007, 7:31:59 AM5/16/07
to
On Wed, 16 May 2007 10:54:34 +0200, Jon Harrop <j...@ffconsultancy.com>
wrote:

> Raffael Cavallaro wrote:
>> If one is only using lisp macros to "reinvent basic syntax" then one is
>> largely missing their point. Their real power is allowing one to define
>> domain specific languages. Anyone who thinks "I wish there were a
>> language as powerful as Common Lisp but without those annoying macros"
>> is missing much of the power of Common Lisp.
>
> Absolutely, but Lisp is in the unique position of having no syntax to
> start
> with so programmers are likely to extend the syntax using macros for
> operations that already have custom syntax in other languages. For
> example,
> this whole thread is redundant in most other languages because they
> provide
> a built-in syntax for array access.
>

Analyze this! http://home.chello.no/~jthing/games/tictactoe.html

--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/

Dan Bensen

unread,
May 16, 2007, 7:50:01 AM5/16/07
to
java...@gmail.com wrote:
> The basic motivation for Lispers is not one of convenience (all of
> your statements reduce to that) but instead one of philosophy.

Nonsense. Convenience is exactly the reason for macros.
The whole point is to avoid unnecessary repetition of code.
The "philosophy" of Lisp is that macros, among other things, are
convenient for large projects with repeated patterns that aren't
supported in other languages.

> It's not how often you need some specific feature (that is simply
> convenience), it is the good feeling beeing able to use it when
> needed! This fact makes it possible to think in theoretical directions
> which simply wouldn't be possible with some inferior tool.


> BTW, it is (in practice) very difficult to really convince people of
> the superiority of Lisp, because the larger the project, the more you
> see the obvious advantages. But large projects can never be presented
> in reduced form as practical examples, you see...
>
> Some like Convenience Traps, others know better.
> Some like Fast Food, others taste better.
>
> -JO
>


--
Dan
www.prairienet.org/~dsb/

Message has been deleted

Pascal Costanza

unread,
May 16, 2007, 8:12:55 AM5/16/07
to
Jon Harrop wrote:

> If a language provides the most common forms of syntax (array element
> access, hash table lookup, curried anonymous functions, pattern matching
> syntax, try finally etc.) then the need for macros is greatly reduced. So
> much so that other language features become more important.

The good thing about macros is not so much being able to add common
forms, but rather about adding special-purpose forms.

See http://www.cl-http.org:8002/mov/dsl-in-lisp.mov for a good illustration.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/

Tim Bradshaw

unread,
May 16, 2007, 8:16:29 AM5/16/07
to
On May 16, 10:08 am, Jon Harrop <j...@ffconsultancy.com> wrote:

> I deliberately phrased my statement to be about the relative importance of
> macros because macros are essential in Lisp but basically redundant in most
> other general-purpose programming languages because all the common cases
> are already covered.

So, for instance, you can embed SQL and XML seamlessly in all these
languages? That's a pretty common case. Curiously, when I did this
kind of thing in Java a couple of years ago I found it pretty non-
seamless[*]. I must have been missing something. Probably should
have used ML, or Objective Braindeath or something rather than
sticking with Java, which as everyone knows isn't really general-
purpose.

--tim

[*] I think closures are due to go into Java 7 actually, and people
talk about adding a macro system.

Kent M Pitman

unread,
May 16, 2007, 11:39:46 AM5/16/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> Raffael Cavallaro wrote:
> > On 2007-05-15 19:09:08 -0400, Kent M Pitman <pit...@nhplace.com> said:
> >> The sentence you've chosen states a fact that remarks on other people's
> >> usage and that suggests other people's prior statements that this is
> >> important is wrong. Do you mean to do that?
> >
> > Yes, he really is that presumptuous.
>
> The objective evidence is: macros are common in Lisp and rare in OCaml.

This is a data point or a conclusion, but not an argument. It's like
saying "the objective evidence is that people who live near the
equator spend more time outdoors and people who live farther north do
not." Is this a comment on what lifestyle is better or on who prefers
to live where or on who grew up where or ...? It seems to me to be
subject to so much spin as to be nearly vacuous, notwithstanding the
fact that it is, in fact, objective evidence. Evidence of what?

Your remark has the vague syntactic trappings of science in using a
term like objective evidence, but it is in fact a sentence fragment
taken out of context--possibly from a scientific discussion, possibly
not. What science is about, if that's what you're attempting to do
here, is falsifiability. Incidentally, I don't mean to say science is
necessary here. It's fine to just say "I like x." and be done with
it. But when you start speaking for others and sounding like you want
to be awarded a credential for doing so, you want to say on what basis
your remarks rely, or whether they are just personal analysis. When
you use terms like "objective evidence", you appear to be invoking the
firm irrefutability of science, something that extends beyond personal
opinion. And yet, if you've made no falsifiable claim, you haven't
done the thing that scientists do--to put themselves on the line.

This is what's remarkable about the present debate on Darwin's theory.
The anti-science crowd always points to the remark "it's only a
theory". But that's the point. It can't be a science if it's not a
theory. There are no laws because we don't know the mechanisms of
enforcement of any law, so even the strongest laws of physics we have
are, by definition, theories. Only a religion is non-falsifiable,
because it relies on no premises, and asserts itself as simply
axiomatic. And yet, discussion points to itself in a circular debate
that confuses those who do not keep their terms straight. The Bible
exists, proclaims itself true, and asserts it is not a theory, while
Science is just a theory, hence it loses out in a debate with someone
who doesn't understand that Science rests for its success on its
willingness to be inspected and tested, to be predictive, etc.

So with regard to your remark about Lisp and OCaml, does this make a
conclusion about the language being better, or about the community
that selects the language. What specific testable claim does it make?
I don't see one, yet I see the hint that one is implied and that any
response to this will be met with argument, as if someone had unfairly
criticized what you said... when in fact you have not put yourself on
the line at all.

I will make a claim [1]: Macros are useful to me. They have been useful
to the community. I would not personally like programming without
them. I have had many opportunities in my career. I do it daily now,
including in functional languages now, and I hate it. I find it
clumsy and verbose and not to-the-point.

I will make a further claim [2]: Macros are useful to other people, too.

I will make a further claim [3]: Some people don't like or want macros.

I will make an observation [A] about these three claims: They are not
in conflict.

I will make another observation [B]: A claim [B'] that macros were NOT
useful and desirable to people or could be happily dispensed with in
the world WOULD be in conflict with my claims.

I will make another observation [C]: A claim [C'] that functional
languages that served people who didn't want macros could be dispensed
with in the world WOULD also be in conflict with my claims.

I am not making the claim C' alluded to in observation C; are you
making the claim B' alluded to in observation B? If you are not, I
don't see the import of your original remark (so one languages uses
macros and one doesn't--what does that show?); if you are making the
claim B', I don't see that you have offered adequate evidence in
support of this surprising and strong claim.

The following article, though now a bit dated, contains most of the
things I would probably say beyond this point, so I won't bother to
repeat them here:

More Than Just Words: Lambda, the Ultimate Political Party
http://www.nhplace.com/kent/PS/

Kent M Pitman

unread,
May 16, 2007, 12:02:41 PM5/16/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> Raffael Cavallaro wrote:
> > If one is only using lisp macros to "reinvent basic syntax" then
> > one is largely missing their point. Their real power is allowing
> > one to define domain specific languages. Anyone who thinks "I wish
> > there were a language as powerful as Common Lisp but without those
> > annoying macros" is missing much of the power of Common Lisp.
>
> Absolutely, but Lisp is in the unique position of having no syntax
> to start with

Actually, Lisp does not have "no syntax" to start with. It has a
syntax of a different kind, one you that perhaps you don't approve of,
which is perhaps why you choose to refer to it as if it were not there.

Far from having no syntax to start with, Lisp has both reader syntax
and s-expres pre-defined (and, incidentally, modifiable) form.

What it doesn't have, and not because it's left it out, but because
it's organized differently, is a forced notion of primary syntax
organized around a particular non-extensible set of operators.

I would make the comparison to King Arthur choosing the Round Table
for his knights, yielding the primacy of his would-be seat at the head
of the table, so that his knights would not feel second-class. To
speak about this as if there was no organization would be wrong; there
was an organization, but simply not one that gave undue authority to
the first things.

And, indeed, there is historical basis for seeing that this is so.
One of the common requests users ask of infix languages is "how do I
make something like that?" Some languages finally offer things like
the goofy operator+ notation for customizing overloads, but few
languages (Lisp, CGOL, TeX, and SGML come to mind as exceptions) offer
ways to override the primitive parse characteristics adding actual new
names with interesting parse properties.

> so programmers are likely to extend the syntax using
> macros for operations that already have custom syntax in other
> languages.

Sort of like how the US has a messy problem of choosing its leader and
how this problem is solved in other countries that have dictators.
Problem neatly solved, requiring no reinforcement of the details.
It's enough that details have been unalterably been pre-defined. It
stands as self-evident that this is better. Mmmmm. Good point.
Strong debate point won here.

> For example, this whole thread is redundant in most other languages
> because they provide a built-in syntax for array access.

Then you mistake this thread for a discussion about array syntax.

I'll go out on a limb rather thank taking a poll and risk speaking for
others when I say that many of us who are contributing would not do so
if we thought that.

"Give a man an array access syntax and he will notate array
accesses happily for a day. Teach him how to create syntax of
his own and he will notate happily for a lifetime."

-- with apologies to Confucius or Anonymous or whoever
said this originally (probably in some other language,
before we learned we had the power to make our own)

Harald Hanche-Olsen

unread,
May 16, 2007, 1:08:57 PM5/16/07
to
+ Kent M Pitman <pit...@nhplace.com>:

| "Give a man an array access syntax and he will notate array
| accesses happily for a day. Teach him how to create syntax of
| his own and he will notate happily for a lifetime."

8)

| -- with apologies to Confucius or Anonymous or whoever
| said this originally (probably in some other language,
| before we learned we had the power to make our own)

Quite possibly, but not certainly, Laozi (aka Lao Tsu):

http://en.wikiquote.org/wiki/Laozi#Attributed

--
* Harald Hanche-Olsen <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
when there is no ground whatsoever for supposing it is true.
-- Bertrand Russell

Jon Harrop

unread,
May 16, 2007, 12:52:51 PM5/16/07
to
Kent M Pitman wrote:
> What it doesn't have, and not because it's left it out, but because
> it's organized differently, is a forced notion of primary syntax
> organized around a particular non-extensible set of operators.

None of what you've said applies to OCaml, which was my point.

Jon Harrop

unread,
May 16, 2007, 1:03:24 PM5/16/07
to
Kent M Pitman wrote:

> Jon Harrop <j...@ffconsultancy.com> writes:
>> The objective evidence is: macros are common in Lisp and rare in OCaml.
>
> This is a data point or a conclusion, but not an argument.

It is a counterexample to the assumption that the utility of macros in Lisp
can be extrapolated to other languages.

OCaml has shown that macros are not very useful in ML.

> are you making the claim B' alluded to in observation B?

No, I am not.

> If you are not, I don't see the import of your original remark (so one
> languages uses macros and one doesn't--what does that show?);

That macros are useful in Lisp but much less so in OCaml and, consequently,
Lisp programmers should not disregard other languages because they lack
macros.

Dan Bensen

unread,
May 16, 2007, 1:36:57 PM5/16/07
to
>> Jon Harrop <j...@ffconsultancy.com> writes:
>>> The objective evidence is: macros are common in Lisp and rare in OCaml.

> Kent M Pitman wrote:
>> This is a data point or a conclusion, but not an argument.

Jon Harrop wrote:
> It is a counterexample to the assumption that the utility of macros
> in Lisp can be extrapolated to other languages.

You haven't shown that. To a large degree, macros aren't used in other
languages because they're less feasible, not because they're less
useful. Another reason is that people who need macros don't bother
with those other languages in the first place. :)

--
Dan
www.prairienet.org/~dsb/

Tim Bradshaw

unread,
May 16, 2007, 1:43:07 PM5/16/07
to
On 2007-05-16 18:03:24 +0100, Jon Harrop <j...@ffconsultancy.com> said:

> OCaml has shown that macros are not very useful in ML.

Yes. because they are so hard because the language is already full of syntax.

Joe Marshall

unread,
May 16, 2007, 2:01:27 PM5/16/07
to
On May 16, 2:08 am, Jon Harrop <j...@ffconsultancy.com> wrote this
howler:

>
> Macros have been around for a long time and they never got serious traction
> (e.g. compared to static typing).

http://www.google.com/search?q=site%3Aciteseer.ist.psu.edu+macro

Oh wait, I forgot. ``Few people write C any more.''

Tim Bradshaw

unread,
May 16, 2007, 2:00:48 PM5/16/07
to
On 2007-05-16 18:43:07 +0100, Tim Bradshaw <t...@tfeb.org> said:
>
> Yes. because they are so hard because the language is already full of syntax.

I thought I was just taking the piss here, but I looked at the manual.
I mean, really: it's a it obvious why no one uses the bloody things.
Look at this:

# let t = [< '"I"; '"say"; s; '"as"; '"an"; '"example" >];;

it's like Perl except designed by someone who liked lots of weird
squiggly characters.

Run away.

Rob St. Amant

unread,
May 16, 2007, 2:08:20 PM5/16/07
to
Dan Bensen <rando...@cyberspace.net> writes:

Agreed. I think that this snippet, from elsewhere in this thread,

> let xg, yg, zg = map3 get (x, y, z)

suggests that macros would be useful (though I don't know the
language: OCaml?) If we imagine that the data structures are
arbitrary rather than built into the language, and potentially
different from each other, it seems reasonable to want to build an
abstraction above them, one that doesn't involve introducing something
like a mapping function, which strikes me as a workaround that ideally
doesn't need to be visible.

Jon Harrop

unread,
May 16, 2007, 2:10:34 PM5/16/07
to

Raffael Cavallaro

unread,
May 16, 2007, 2:55:12 PM5/16/07
to
On 2007-05-16 12:52:51 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> None of what you've said applies to OCaml, which was my point.

Nice try, but your point was, and I quote:

"Lisp is in the unique position of having no syntax to start

with..."

Which is, as Kent explains, simply false.

Lisp has *simpler* syntax than OCaml, making lisp macros easier to
write than OCaml macros. This is why macros are much more commonly used
in Common Lisp than in OCaml. It's not that OCaml is so perfect that
macros aren't needed. Rather it is because OCaml's built in syntax is
so complex that writing macros is unnecessarily complicated when
compared to a language with simple syntax like Common Lisp.

Joe Marshall

unread,
May 16, 2007, 3:09:37 PM5/16/07
to
On May 16, 4:24 am, Jon Harrop <j...@ffconsultancy.com> wrote:

> java....@gmail.com wrote:
> > You seem to completely miss the reason why Lispers stay with Lisp.
>
> They don't.

Yet in message <44d9d10f$0$60354$ed26...@ptn-nntp-reader03.plus.net>
you wrote:
>Interestingly, I think the vast majority of functional programmers stick to
>the language they are introduced to. Very few people seem to bother
>learning Lisp once they've learned OCaml and vice versa.

So which is it?

Furthermore, in that same message you state:
> I know about 10 OCaml programmers IRL and one Lisp programmer.

You seem to be extrapolating from a rather small sample space.


Don Geddis

unread,
May 16, 2007, 3:08:34 PM5/16/07
to
Jon Harrop <j...@ffconsultancy.com> wrote on Wed, 16 May 2007:
> If a language provides the most common forms of syntax (array element
> access, hash table lookup, curried anonymous functions, pattern matching
> syntax, try finally etc.) then the need for macros is greatly reduced.
[...]

> I deliberately phrased my statement to be about the relative importance of
> macros because macros are essential in Lisp but basically redundant in most
> other general-purpose programming languages because all the common cases
> are already covered.

But Lisp programmers don't use macros to reimplement the "common" syntax
cases that are provided by default in other languages. It is not the case
(as you seem to believe) that Lisp programmers are running around constantly
reimplementing macros to create a ("missing") syntax for array access and
hash table lookup.

Since you don't seem to understand the purposes to which Lisp programmers
put the power of macros, your whole thesis that "a language having built-in
syntax for common cases would greatly reduce the need for macros" is moot.

-- Don
_______________________________________________________________________________
Don Geddis http://don.geddis.org/ d...@geddis.org
Whenever I see a poor person on the street, I want to go up and grab him by the
collar and shout, "Hey, buddy, get your act together!" Then when I see a rich
guy, I want to walk up to him and politely say, "Excuse me, but could you
please get your act together?" -- Deep Thoughts, by Jack Handey [1999]

Jon Harrop

unread,
May 16, 2007, 3:35:23 PM5/16/07
to
Don Geddis wrote:
> But Lisp programmers don't use macros to reimplement the "common" syntax
> cases that are provided by default in other languages. It is not the case
> (as you seem to believe) that Lisp programmers are running around
> constantly reimplementing macros to create a ("missing") syntax for array
> access and hash table lookup.

This thread is an obvious counter-example.

> Since you don't seem to understand the purposes to which Lisp programmers
> put the power of macros, your whole thesis that "a language having
> built-in syntax for common cases would greatly reduce the need for macros"
> is moot.

That is based upon information about OCaml.

Jon Harrop

unread,
May 16, 2007, 3:36:36 PM5/16/07
to
Joe Marshall wrote:
> On May 16, 4:24 am, Jon Harrop <j...@ffconsultancy.com> wrote:
>> java....@gmail.com wrote:
>> > You seem to completely miss the reason why Lispers stay with Lisp.
>>
>> They don't.
>
> Yet in message <44d9d10f$0$60354$ed26...@ptn-nntp-reader03.plus.net>
> you wrote:
>>Interestingly, I think the vast majority of functional programmers stick
>>to the language they are introduced to. Very few people seem to bother
>>learning Lisp once they've learned OCaml and vice versa.
>
> So which is it?

Those are not conflicting statements: both.

> Furthermore, in that same message you state:
>> I know about 10 OCaml programmers IRL and one Lisp programmer.
>
> You seem to be extrapolating from a rather small sample space.

What did I extrapolate from that?

Jon Harrop

unread,
May 16, 2007, 3:59:22 PM5/16/07
to
Raffael Cavallaro wrote:
> Lisp has *simpler* syntax than OCaml,

Yes.

> making lisp macros easier to write than OCaml macros.

I disagree and here is a counter example, a macro for infix +, -, * and /
with integers and brackets (a simple calculator syntax) with precedence
written in OCaml:

EXTEND
test: [ [ e = expr; EOI -> e ] ];
expr: [ "plus" LEFTA
[ e1 = expr; "+"; e2 = expr -> e1 + e2
| e1 = expr; "-"; e2 = expr -> e1 - e2 ]
| "mult" LEFTA
[ e1 = expr; "*"; e2 = expr -> e1 * e2
| e1 = expr; "/"; e2 = expr -> e1 / e2 ]
| [ e = INT -> int_of_string e
| "("; e = expr; ")" -> e ] ];
END;;

That doesn't seem outrageously difficult to me. What is the equivalent Lisp?

Extending the pattern matcher with this, and support for expression
sequences represented as balanced binary trees was easy enough.

Now look at the way Lispers use macros:

Array syntax:
this thread
http://groups.google.co.uk/group/comp.lang.lisp/msg/a7b256636b61f950?hl=en&
http://groups.google.co.uk/group/comp.lang.lisp/msg/41332f3af8f2ae60?hl=en&

Pattern matcher:
http://groups.google.co.uk/group/comp.lang.lisp/msg/25366074b6a513fe?hl=en&

Optimization:
http://www.ffconsultancy.com/languages/ray_tracer/code/5/ray.lisp

Currying:
http://groups.google.co.uk/group/comp.lang.lisp/msg/42f9b9577667306d?hl=en&

The same topics come up here over and over, and each time everyone posts a
new macro to implement an old syntax.

Kent M Pitman

unread,
May 16, 2007, 9:48:44 PM5/16/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> That doesn't seem outrageously difficult to me. What is the equivalent Lisp?

IMO, this example isn't particularly productive. My point is
succinctly summed up by the phrase "apples and oranges". But I'll
elaborate anyway.

For example, is your question asked with or without extending Lisp to
hypothesize the existence of an infix parser?

How is OCaml on adding readmacros, which Lisp can do easily. I bet if
OCaml had a readmacro facility, the act of writing an individual
readmacro would be simple. But adding a readmacro facility is a
non-trivial injection into a parsed syntax. So it's not going to be
pretty. I would not ask that of a parsed language. I would simply
observe that parsed languages have certain useful advantages and so do
Lispy languages; I prefer the latter, which is why I use Lisp for lots
of things. If you don't, then perhaps you are better placed with
another language or perhaps you should extend Lisp to accommodate
parsed syntax, which can be done. And having done this several times
myself, I can tell you that extensions such as you describe are just as
easy to write once you hypothesize the existence of a parser at all.
Hence the remark about "apples and oranges".

I'm not familiar with the grammar of OCaml, though it looks very like
ML, and in fact I'm not sure its details matter--I'm pretty confident
that the Lisp reader can be modified to have OCaml syntax, to include
the ability to write syntax extensions in similar form to what you've
just written.

Are you confident you can modify the OCaml reader to accept Lisp
syntax? If not, then what is the relevance of the fact that each can
do something the other can't in some uninteresting syntactic way.
We're confident that using macros is useful to us, and we're happy
using macros. No one is trying to tell you not to use OCaml and not
to avoid macros. But I think the observation someone (perhaps more
than one person) made about the fact that languages where macros are
painful or restricted or non-existent will attract different
personalities than languages where macros are easy and general is spot
on. Until you have accounted for differences in preference between
people who use languages, stats on how people use certain languages in
isolation are not useful science.

In deciding whether people would prefer Lisp or Scheme, I often pose
questions about how they like to express themselves, including
questions about whether they prefer functional abstraction or macro
abstraction, in order to place them in a community that will be most
happy for them. I don't think Scheme people would be happy with CL,
nor vice versa, but I don't consider that fact an a priori criticism
of either language.

I think there is room for some interesting dialog between language
communities, but I think taking potshots randomly is not the way to do
that.

Good experimental data is something one takes the trouble to create
control groups for. Good abstract arguments are things where one
takes the trouble to list their dependent assumptions and to abstract
away from incidentals.

Gabriel and I had enormous difficulty in writing our paper on
namespaces because it kept looking like a comparison of Lisp and
Scheme rather than of single namespace vs dual namespace. Even now,
people still tend to read it that way, and like many debates, they
support their home team and have to read carefully to see that the
debate has legitimate points on both sides. But my introduction of
the terms Lisp1 and Lisp2 to substitute for CL and Scheme at least got
us to the point where the debate was close to balanced, since it was
possible for people to imagine a Scheme with 2 namespaces (ISLISP is
sort of close to that in certain ways) and or a CL with one namespace
(Dylan is sort of close to that in certain ways). But my point isn't
to open those debates--just to say that having a serious debate is
hard work on the part of the debate partners, being fair to one
another. Since it's you who seems to want to debate everything about
the language, you could start by doing your homework better before
being critical... and when being critical, you could help by being
articulate and not making people have to infer what you are
criticizing and on what basis.

We aren't going out of our forum to push Lisp on you--you're coming
into our forum to learn about the language, so the burden is not on us
to convince you to stay. A language forum does not exist so that people
can justify their existence to others; it exists so that people who want
to come there voluntarily can meet with a friendly community who are
supportive and helpful. That doesn't mean we can't stand critical
discussion, but it does mean that there should be a point--a way we are
asked to change or grow--and one that is realistic and accommodates the
needs of the community. I don't see any such constructive suggestion
underlying this post, nor many others I've read from you.

If you don't like the language, by all means, avail yourself of the
brightly lit red EXIT light... but if you wish to stay, please engage
the language in the same productive and upbeat fashion requested of
others. Learn the language on its own terms. It is not other
languages. (There are other languages for the purpose of being other
languages. Lisp exists for the purpose of being itself.)

> Extending the pattern matcher with this, and support for expression
> sequences represented as balanced binary trees was easy enough.
>
> Now look at the way Lispers use macros:

> Array syntax:[...]
> Pattern matcher:[...]
> Optimization:[...]
> Currying:[...]


> The same topics come up here over and over, and each time everyone posts a
> new macro to implement an old syntax.

You do a lot of your "debating" by merely citing odd observations and
then jumping to bizarre, unsupported conclusions. I've got to say,
I'm close to the end of my tolerance for this because I don't feel the
language has anything to answer for, and I think a lot of what you're
doing is not resulting in you being any happier nor anyone else being
enriched by your questions. But I'll go through it one more time,
just as evidence that these observations are insufficiently supported,
so you and others looking on don't think I'm being evasive for not
answering, even though at some ponit I will start not answering and it
might otherwise look like I was just afraid to answer rather than
simply bored...

I sense this same sense of tedium in others responding to you. If I
were you, I would think hard about whether you've gotten what you
wanted from the valuable resource which is the patience of many who
have responded to you here, and I would ask myself, is it time to
modify my approach or ask the last few questions I'd like the answer
to before those resources shut down. Because you're offering very
little value and consuming great quantities of people as resources,
and I don't see that equation balancing for the extended time. Just a
personal suggestion.

Now, returning to your sort-of-scientific-looking observations above:

First, as to the question of the particular topics that come up: They
are typical early programming issues, but not necessarily evidence of
what people write macros about. So I'm not sure what you're
concluding about macros overall from these. If you want to make claims
about how people really use macros, you have to look in another place
than a forum where people ask lots of newbie questions. Here are
some things I've written macros for:

- A macro that took Augmented Transition Network (ATN) grammars as
arguments and expanded into a state machine for processing sentences
in the grammar. This would be possible, but a pain, to express in
functional notation because it would be full of words unrelated to
the domain.

- A macro that implemented FORTRAN-like call-by-reference semantics on a
body of code so that I could read in FORTRAN code and embed Lisp code
in the middle. This is a pain to do functionally both because of the
syntactic nuisance of having notations in the middle that were not
relevant to the domain code, and also because the proper expansion
needed to be mediated by code that made intelligent decisions about
whether to apply FORTRAN or Lisp semantics at any given point.

- Macros to implement facilities like LOOP and DEFMETHOD as part of language
substrate (emphasizing that large, non-trivial transformations might be
made from source code to compiled code).

- Macros that write macros that write macros (emphasizing the ability to
reflectively invoke Lisp as part of the expansion process).

- One-shot macros that are used just to initialize constant data
(emphasizing that macros are not a major programming project and are
often useful even for a one-off situation as a way of making a
single computation clearer).

- Macros that implement embedded languages.

- A macro language for manipulating HTML, that includes partial evaluation
so that structural representations of HTML that will do nothing more than
be written to a stream is done by string-out in many places rather than
first being consed.

Second, as to the question of there being more than one response that
comes in response to the newbie questions, I refer you to my previous
response on the issue of teaching people how to solve their own
problems. People often respond here about how to write things not
because they can't and don't create libraries, but because they want
newbies to know that they aren't at the mercy of the libraries. The
solutions are in range to mortals to write themselves.

Further, seeing many opinions on different ways to do something is not
symptomatic of failure. The movie industry is not in trouble because
people disagree on what the best movie is. It's _lack_ of choice, not
_choice_, that would be more symptomatic of a problem.

C.R. Kirkwood-Watts

unread,
May 16, 2007, 9:54:53 PM5/16/07
to
__ Jon Harrop <j...@ffconsultancy.com> _____
:

| I disagree and here is a counter example, a macro for infix +, -, *
| and / with integers and brackets (a simple calculator syntax) with
| precedence written in OCaml:
|
| EXTEND
| test: [ [ e = expr; EOI -> e ] ];
| expr: [ "plus" LEFTA
| [ e1 = expr; "+"; e2 = expr -> e1 + e2
| | e1 = expr; "-"; e2 = expr -> e1 - e2 ]
| | "mult" LEFTA
| [ e1 = expr; "*"; e2 = expr -> e1 * e2
| | e1 = expr; "/"; e2 = expr -> e1 / e2 ]
| | [ e = INT -> int_of_string e
| | "("; e = expr; ")" -> e ] ];
| END;;

I don't know OCaml, and so I'm a little confused. But, trying the
above in

Objective Caml version 3.09.2

I just get a syntax error. Maybe I'm missing a package or
something.

Anyway, what is it supposed to do again? Add infix syntax to an
infix language?

Chris.

Andrew Reilly

unread,
May 16, 2007, 10:08:34 PM5/16/07
to

Macros are used (heavily) in some of the most significant languages on the
planet: C, C++ and assembler. Not good macro systems, but essential none
the less.

--
Andrew

Kent M Pitman

unread,
May 16, 2007, 10:17:19 PM5/16/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> Don Geddis wrote:
> > But Lisp programmers don't use macros to reimplement the "common" syntax
> > cases that are provided by default in other languages. It is not the case
> > (as you seem to believe) that Lisp programmers are running around
> > constantly reimplementing macros to create a ("missing") syntax for array
> > access and hash table lookup.
>
> This thread is an obvious counter-example.

Nonsense. In making this claim, you are implying that our willingness
to engage this thread in discussion implies agreement to the idea that
this is a typical use.

That's like saying that high school English classes are typical of the
use of English encountered in life. Are Shakespeare, Dickens, Poe, or
Twain are good examples of how people use English. No. They are what
they are, and they are chosen for teaching for reasons of pragmatics
and scope, not because they are appropriate topics for word usage
counts of "typical English", which is the kind of bogus analysis you
are appearing to apply routinely here.

There is more to researching a topic than pulling it up in Google and
looking at the number of page counts in the upper right corner.

> > Since you don't seem to understand the purposes to which Lisp
> > programmers put the power of macros, your whole thesis that "a
> > language having built-in syntax for common cases would greatly
> > reduce the need for macros" is moot.
>
> That is based upon information about OCaml.

OCaml is an unbound term here, incidentally. It is not required
reading for anyone on this forum. It's always great when someone
wants to read about a new thing, but please be sparing in your
comparisons. This is not comp.lang.lisp.vs.ocaml. This is a forum
for the discussion of Lisp, and passive aggressively suggesting that
you are right unless someone cares to learn enough about OCaml for you
to be satisfied that they have responded adequately is no way to win
support for either your positions or your language. People come here
to discuss Lisp and can tolerate limited degrees of references to the
outside. The number of posts in which you respond "well, OCaml
doesn't do it that way" is getting toxically tedious.

The usual answer for "Lisp doesn't have a way to do that syntactic
thing" is "well, what domain problem are you trying to solve, and
maybe there is another syntactic way of solving that problem". Do you
have a domain problem you're trying to solve or are you just supposing
that if you did, you would be ill-served by Lisp?

Joe Marshall

unread,
May 16, 2007, 10:29:21 PM5/16/07
to
On May 16, 12:36 pm, Jon Harrop <j...@ffconsultancy.com> wrote:
> Joe Marshall wrote:
> > On May 16, 4:24 am, Jon Harrop <j...@ffconsultancy.com> wrote:
> >> java....@gmail.com wrote:
> >> > You seem to completely miss the reason why Lispers stay with Lisp.
>
> >> They don't.
>
> > Yet in message <44d9d10f$0$60354$ed261...@ptn-nntp-reader03.plus.net>

> > you wrote:
> >>Interestingly, I think the vast majority of functional programmers stick
> >>to the language they are introduced to. Very few people seem to bother
> >>learning Lisp once they've learned OCaml and vice versa.
>
> > So which is it?
>
> Those are not conflicting statements: both.

This appears to me to be a direct and obvious contradiction. Perhaps
you would enlighten us as to what exactly you meant?

> > Furthermore, in that same message you state:
> >> I know about 10 OCaml programmers IRL and one Lisp programmer.
>
> > You seem to be extrapolating from a rather small sample space.
>
> What did I extrapolate from that?

I don't want to presume too much, so I'll just say that that sentence
was in the same paragraph as the two preceeding ones.

Joe Marshall

unread,
May 16, 2007, 10:40:33 PM5/16/07
to
On May 16, 12:59 pm, Jon Harrop <j...@ffconsultancy.com> wrote:
>
> I disagree and here is a counter example, a macro for infix +, -, * and /
> with integers and brackets (a simple calculator syntax) with precedence
> written in OCaml:
>
> EXTEND
> test: [ [ e = expr; EOI -> e ] ];
> expr: [ "plus" LEFTA
> [ e1 = expr; "+"; e2 = expr -> e1 + e2
> | e1 = expr; "-"; e2 = expr -> e1 - e2 ]
> | "mult" LEFTA
> [ e1 = expr; "*"; e2 = expr -> e1 * e2
> | e1 = expr; "/"; e2 = expr -> e1 / e2 ]
> | [ e = INT -> int_of_string e
> | "("; e = expr; ")" -> e ] ];
> END;;

Doesn't OCaml already have infix?

> The same topics come up here over and over, and each time everyone posts a
> new macro to implement an old syntax.

Indeed.

Tim Bradshaw

unread,
May 17, 2007, 1:41:44 AM5/17/07
to
On 2007-05-16 20:35:23 +0100, Jon Harrop <j...@ffconsultancy.com> said:

> This thread is an obvious counter-example.

And we've fallen right into another of his little traps.

I must say I miss the CLL of old. By now Erik would have
comprehensively torn this twit's head off in the most amusing way. And
we got a better quality loony - people like Ilias who were clearly
actually mad rather than this guy who's like some kind of terminator -
infinitely and unremittingly boring but he absolutely will not stop
until he's sucked the life out of us all.

I guess the good point is that anyone doing the classic "google someone
before you consider using their services" is going to get some useful
data.

Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Dan Bensen

unread,
May 17, 2007, 5:16:01 AM5/17/07
to
> On Wed, 16 May 2007 12:36:57 -0500, Dan Bensen wrote:
>> To a large degree, macros aren't used in other languages
>> because they're less feasible, not because they're less useful.

Andrew Reilly wrote:
> Macros are used (heavily) in some of the most significant languages on the
> planet: C, C++ and assembler. Not good macro systems, but essential none
> the less.

Good point, although I didn't necessarily mean *all* other languages,
and I still don't think they're used as much as in Lisp. The main
reason I turned to Lisp is that many, or even most, people in the C++
world discourage the use of macros, and Lisp seems to be the only
alternative.

--
Dan
www.prairienet.org/~dsb/

Message has been deleted
Message has been deleted
Message has been deleted

Matthias Benkard

unread,
May 17, 2007, 5:42:34 AM5/17/07
to
> I disagree and here is a counter example, a macro for infix +, -, * and /
> with integers and brackets (a simple calculator syntax) with precedence
> written in OCaml:

What's that macro good for? What does it do? Is it like a Lisp macro
or something completely different?

Rainer Joswig

unread,
May 17, 2007, 5:45:29 AM5/17/07
to
In article <f2gpuo$kgf$1$830f...@news.demon.co.uk>,
Tim Bradshaw <t...@tfeb.org> wrote:

He, there is a civilized way to treat them:

1) give them a chance and see if they are willing to learn something
or correct their behavior
2) if not: mark them as a troll and kill-file them

I think Jon Harrop has now reached stage two.
His contributions to comp.lang.lisp are mostly off-topic and
self-advertising.

Jon Harrop is trolling.

--
http://lispm.dyndns.org

Message has been deleted

Pascal Costanza

unread,
May 17, 2007, 7:04:35 AM5/17/07
to

In Lisp, it is also a good idea to be careful with adding new macros.
The best approach is to design libraries with functional abstractions,
and then provide macros as syntactic sugar on top.


Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/

Alain Picard

unread,
May 17, 2007, 8:41:30 AM5/17/07
to
Jon Harrop <j...@ffconsultancy.com> writes:

> Raffael Cavallaro wrote:

>> My point is that the overwhelming majority of Common Lisp users
>> *do* think that macros are important,
>
> I don't think that is true.

So - an experienced lisp user tells you what the typical experienced
lisp user thinks, but you, the inexperienced lisp user, simply think
that he's wrong? You don't see anything wrong with that?

Do you realize that the picture you're painting of yourself is that of
a complete, utter fool? Surely that is not your intention?

Let me give you a hint: Raffael is correct.

Cheers,
--ap

Geoff Wozniak

unread,
May 17, 2007, 8:53:57 AM5/17/07
to
On May 16, 9:48 pm, Kent M Pitman <pit...@nhplace.com> wrote:
> If you want to make claims about how people really use macros, you
> have to look in another place than a forum where people ask lots of
> newbie questions. Here are some things I've written macros for:
>

I thought it might be nice to list two of the things I've written
macros for that are not of the "let's fix the array syntax" variety.
I've only been writing Lisp code for two years and in a purely
academic setting.

- A pattern matcher (!) that matches over sequences allowing for the
expression of dependent patterns. Furthermore, the patterns
themselves are objects capturing the current continuation of the match
and can be used to find all possible matches of a pattern to a
sequence. The patterns can match arbitrary functional transformations
on the sub-elements,so matching something like [x y] where y =
(reverse x) is easy to express.

Oddly enough, I started writing this in OCaml as I was a big OCaml fan
at the time. This project is what lead me to Common Lisp. (I still
like OCaml, I just don't feel the need to use it.)

- A mini-language for functions that encapsulate a specific control
flow whose subcomponents can be reordered, extended or reimplemented.

There are others, mostly related to conveniently expressing control
flow. When I first started using Lisp, I thought about writing macros
for making array access and variable update look for "natural" until I
realized that it was a bad idea. It would make my code starkly
different than other code with respect to the basic elements of the
language. I didn't want to mentally translate standard idioms to my
own.

Raffael Cavallaro

unread,
May 17, 2007, 11:02:57 AM5/17/07
to
On 2007-05-16 15:59:22 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> I disagree and here is a counter example, a macro for infix +, -, * and /
> with integers

Why would anyone bother with a syntax extension that only handled
machine integers? If I truly wanted infix I would simply load an
existing infix read-macro library.


> That doesn't seem outrageously difficult to me. What is the equivalent Lisp?

(load (compile-file "infix.lisp"))

Your OCaml macro is very limited in utility (only handles machine
integers, doesn't do exponentiation, etc).
F# doesn't even have this macro capability, yet you continue to insist
that it will interest lisp users.

> The same topics come up here over and over, and each time everyone posts a
> new macro to implement an old syntax.

No, not everyone does not. Most intelligent users simply point to the
several existing libraries for these purposes (infix, pattern matching,
etc.) This is your typical straw man argument again - point to usenet
posts from people who are mostly just spitballing instead of existing,
powerful libraries.

Raffael Cavallaro

unread,
May 17, 2007, 11:35:22 AM5/17/07
to
On 2007-05-16 15:35:23 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> Don Geddis wrote:
>> But Lisp programmers don't use macros to reimplement the "common" syntax
>> cases that are provided by default in other languages. It is not the case
>> (as you seem to believe) that Lisp programmers are running around
>> constantly reimplementing macros to create a ("missing") syntax for array
>> access and hash table lookup.
>
> This thread is an obvious counter-example.

Actually, to the thoughtful observer, this thread is proof positive
that lisp programmers just about *never* do that. The language has been
in existence for half a century, macros have been written for decades,
and there are well-worn libraries for infix (which few people use very
often), regex, etc., and yet no lisper has come forward to point to a
"standard" macro for transforming array syntax. Why? Because lispers
don't often feel the need to transform lisp array syntax.

Macros are much more usefully employed to provide domain specific
constructs thus allowing one to program the solution to the problem in
the language of the language of the problem domain itself. Anyone who
has used lisp for a while simply doesn't care to make the "common"
syntax cases of lisp look like their equivalents in C or Perl or
Python. With regard to macros, we're concerned with making sexps look
like the terminology and usage of the *problem domain*, not making
sexps look like c or python.


In part your presumption is to blame here - since you don't actually
bother to learn lisp or lisp culture (i.e., how the languae is used,
what libraries there are, etc.) you assume that real world lisp usage
is accuratley reflected in usenet threads. In reality, a large
proportion of discussion here takes the following form which is *not*
reflective of the use to which experienced lisp programmers put the
language:

nub: (unstated assumption: lisp is like c/perl/python/etc. but with
different syntax)
"How do I make lisp look like what I'm used to?"

lisper1: "Don't do that, use the language as other lispers use it."

nub: "But it would be so much more convenient!"

lisper2: "if you really want that you could write this macro"
(unstated: I'd rarely or never use this myself, but If you really want
it...)

nub2: "I need pattern matching!"

lisper1: "Use one of these three libraries."

lisper2: "Gee, I wonder how far we could get with pattern matching if
we limited ourselves to ..." (unstated: clearly this is not as full
featured or well tested or elegant as one of the existing libraries but
...)

harrop: "All lispers ever do is reinvent syntax that already exists in
OCaml!" (unstated: I don't really understand how experienced lispers
use lisp, and I'm really mostly interested in making lisp look bad so I
can drum up some F# business!)

Pierre R. Mai

unread,
May 17, 2007, 11:57:55 AM5/17/07
to
On 2007-05-17 13:04:35 +0200, Pascal Costanza <p...@p-cos.net> said:

> Dan Bensen wrote:
>> Good point, although I didn't necessarily mean *all* other languages,
>> and I still don't think they're used as much as in Lisp. The main
>> reason I turned to Lisp is that many, or even most, people in the C++
>> world discourage the use of macros, and Lisp seems to be the only
>> alternative.
>
> In Lisp, it is also a good idea to be careful with adding new macros.
> The best approach is to design libraries with functional abstractions,
> and then provide macros as syntactic sugar on top.

Which is sound advice: Take for example an embedded language for the
implementation of an interpreter for a commercially relevant discrete
subset of the MATLAB/Simulink modelling language. Simulink is mostly
based on individual blocks, which are connected together to form
models. The semantics can for the most part be reduced to the semantics
of the individual block types.

Hence an ideal language for implementing an interpreter for Simulink
models would allow one to define block types (here called node types,
for uninteresting reasons) directly, like e.g. so:

(define-node-type discrete-filter ()
(:match (10 "tllib/Discrete Filter"))
(:parameters (numerator element-default-typed-vector "num")
(denominator element-default-typed-vector "denom")
(output-spec type-spec "output"))
(:inputs (input typed-value))
(:state
(input-history (make-vector (1- (length numerator))
(convert 0.0d0 output-spec)))
(output-history (make-vector (1- (length denominator))
(convert 0.0d0 output-spec))))
(:outputs
(output
(let ((acc-spec (widen-type-spec input)))
(typed-/
(typed--
(vector-accumulate numerator input-history acc-spec :start1 1
:initial-value
(typed-* input (svref numerator 0) acc-spec))
(vector-accumulate denominator output-history acc-spec :start1 1)
acc-spec)
(svref denominator 0)
output-spec))))
(:update-state
(vector-shift-right input input-history)
(vector-shift-right output output-history)))


The actual implementation of the define-node-type macro ends up defining:

- a new CLOS class discrete-filter-node, which is an instance of a
special standard-node-class metaclass (with various MOP extensions)
with slots for the various parameter and state instance variables, as
well as "automatic" slots for the input and output vectors.
- Various methods specialized on this class for setup, output
calculation and state updating code, where the body of the methods is
wrapped in various flet, macrolet, with-slots, symbol-macrolet, and
handler-bind forms to provide a suitable environment for the execution
of the forms supplied by the :state, :outputs and :update-state forms.
- A couple of methods eql-specialized the class itself for parameter
parsing and instance allocation purposes, as well as for matching of
this node to blocks in the model, or for dependency analysis and
circularity detection logic.

So the actual implementation of the functionality provided by
define-node-type is mostly achieved through functional libraries, MOP
hackery, etc., and it is indeed still possible to define new node types
by hand via defclass, defmethod and various globally-defined macro
helpers, but a node definition is much more concise (usually < 1 page
of code vs. >=3 pages of code).

For the most part, this post is also intended to give another example
for what macros are used for in practice, for those who are really
interested, and not just wanting to convince themselves that macros (or
Lisp in general) has nothing interesting to offer them, which is fine
by me, but would of course be less distracting if they did this in some
group other than c.l.l.

Personally, what I get from Lisp's macros is the ability to easily
define new languages to my liking and suitable for the problem at hand,
without most of the tedious parts of the compiler construction business
this would imply in other languages, and program in them, which results
in compact, to-the-point code, rather than trying to use a
general-purpose language to do the same by foot, which results in lots
of boiler-plate code, with the interesting bits sprinkled in between,
in usually homeopathic doses.

This freedom also results in a different approach to design and
programming, IMHO: When faced with a problem like the one above, I
usually sit down, and analyze the problem space until I can start to
envisage the language I want to solve it in. That is, I would start to
write the actual define-node-type form above, and massage it until it
seemed to capture the intent I want to convey, for a couple of
interesting cases. Only then would I start to think about the macrology
and the infrastructure needed to implement define-node-type, and start
design and implementation of the domain-specific language.

Regs, Pierre.

PS: For other instances of practical uses to which macros are put, one
can look at many interesting libraries on common-lisp.net, or for
example at most of the internals of the SBCL or CMUCL compilers, which
would be much more verbose, without the use of macros (though some uses
of macros in Python-the-compiler could nowadays be replaced with simple
CLOS code, many cannot).

Kent M Pitman

unread,
May 17, 2007, 12:02:56 PM5/17/07
to
Pascal Costanza <p...@p-cos.net> writes:

> In Lisp, it is also a good idea to be careful with adding new
> macros. The best approach is to design libraries with functional
> abstractions, and then provide macros as syntactic sugar on top.

While I think it's often useful to do as you say, I'm uncomfortable
with a blanket piece of advice of this sort, which appears to me to be
"dogma" because it doesn't say why you would or wouldn't.

I think what makes something useful cannot be "do X 90% of the time
and Y 10% of the time". Because that's usually code for situation X'
that calls for X comes up 90% of the time in my personal experience,
and calls for solution X as a consequence of property, P(X'), not as a
consequence of its frequency. Some people may see P(X') all the time,
and should be doing X 100% of the time, and some may see it never and
should be doing X 0% of the time. Useful advice, it seems to me, is
about P(...), which you haven't spoken to at all.

Special forms are available in Lisp in a way that is not invasive and
so claiming that using them sparingly is good seems bizarre and cries
out for more explanation.

I would be perfectly comfortable with this alternate formulation:

Where you perceive there might be a call for a functional
entry point, it can be useful to design the functional interface
and then to layer a macro abstraction above it for people who
don't like the functional syntax.

But note that this advice is based on situational information and
doesn't attempt to attach unmotivated shame to the use of macros.

I'm also comfortable with observing that sometimes redefinition
without recompilation is enhanced by having thus modularized the
system, since often the macro syntax will not change when a functional
change is made, and a modular redefinition of the underlying function
is cheap to make without recompilation. But that's an implementation
choice, and has to be sometimes weighed against other factors (for
example, it may inhibit certain inline analysis in ways that are
undesirable in some applications, so it is not an automatic win, just
a worthy thing to consider).

Some reading this thread may not have seen my 1980 paper on the matter:

http://www.nhplace.com/kent/Papers/Special-Forms.html

Message has been deleted

Raffael Cavallaro

unread,
May 17, 2007, 12:18:54 PM5/17/07
to
On 2007-05-17 11:57:55 -0400, Pierre R. Mai <pm...@acm.org> said:

> Personally, what I get from Lisp's macros is the ability to easily
> define new languages to my liking and suitable for the problem at hand,
> without most of the tedious parts of the compiler construction business
> this would imply in other languages, and program in them, which results
> in compact, to-the-point code, rather than trying to use a
> general-purpose language to do the same by foot, which results in lots
> of boiler-plate code, with the interesting bits sprinkled in between,
> in usually homeopathic doses.

This is one of the best, and funniest descriptions of the usefulness of
macros I've ever read.

Pascal Costanza

unread,
May 17, 2007, 12:49:03 PM5/17/07
to
Kent M Pitman wrote:
> Pascal Costanza <p...@p-cos.net> writes:
>
>> In Lisp, it is also a good idea to be careful with adding new
>> macros. The best approach is to design libraries with functional
>> abstractions, and then provide macros as syntactic sugar on top.
>
> While I think it's often useful to do as you say, I'm uncomfortable
> with a blanket piece of advice of this sort, which appears to me to be
> "dogma" because it doesn't say why you would or wouldn't.

I agree with what you say, and I am sorry if my wording suggests
otherwise. Thanks a lot for the clarification.

Jon Harrop

unread,
May 17, 2007, 12:58:31 PM5/17/07
to
Geoff Wozniak wrote:
> I thought it might be nice to list two of the things I've written
> macros for that are not of the "let's fix the array syntax" variety.
> I've only been writing Lisp code for two years and in a purely
> academic setting.

I am very interested in these examples and would really appreciate it if you
could elaborate on them.

> - A pattern matcher (!) that matches over sequences allowing for the
> expression of dependent patterns. Furthermore, the patterns
> themselves are objects capturing the current continuation of the match
> and can be used to find all possible matches of a pattern to a
> sequence. The patterns can match arbitrary functional transformations
> on the sub-elements,so matching something like [x y] where y =
> (reverse x) is easy to express.

How is this different to "Foo(x, y) when y = rev x -> ..."?

I did something similar for a Mathematica implementation but opted to write
an interpreter rather than use macros, as RJF did in his Lisp
implementation for example.

> - A mini-language for functions that encapsulate a specific control
> flow whose subcomponents can be reordered, extended or reimplemented.

Could this not be implemented in terms of combinators?

> There are others, mostly related to conveniently expressing control
> flow. When I first started using Lisp, I thought about writing macros
> for making array access and variable update look for "natural" until I
> realized that it was a bad idea.

Yes.

> It would make my code starkly
> different than other code with respect to the basic elements of the
> language. I didn't want to mentally translate standard idioms to my
> own.

This is exactly the downside of forking the language syntax.

--
Dr Jon D Harrop, Flying Frog Consultancy
The F#.NET Journal
http://www.ffconsultancy.com/products/fsharp_journal/?usenet

Jon Harrop

unread,
May 17, 2007, 1:02:51 PM5/17/07
to
Andrew Reilly wrote:
> On Wed, 16 May 2007 12:36:57 -0500, Dan Bensen wrote:
>> Jon Harrop wrote:
>>> It is a counterexample to the assumption that the utility of macros
>> > in Lisp can be extrapolated to other languages.
>>
>> You haven't shown that. To a large degree, macros aren't used in other

>> languages because they're less feasible, not because they're less
>> useful.

I was referring to languages that implement macros. So I don't think their
feasibility can be in question.

>> Another reason is that people who need macros don't bother
>> with those other languages in the first place. :)

But nobody "needs" macros, they just want them because they can make life
easier.

> Macros are used (heavily) in some of the most significant languages on the
> planet: C, C++ and assembler. Not good macro systems, but essential none
> the less.

In this context, I think "macro" refers specifically to the use of macros to
implement syntax extensions. So C's macros don't count, they are deprecated
in C++ and comparatively nobody programs in assembler any more.

Rainer Joswig

unread,
May 17, 2007, 2:03:54 PM5/17/07
to
In article <5b3cbrF...@mid.dfncis.de>,

Pierre R. Mai <pm...@acm.org> wrote:

> This freedom also results in a different approach to design and
> programming, IMHO: When faced with a problem like the one above, I
> usually sit down, and analyze the problem space until I can start to
> envisage the language I want to solve it in. That is, I would start to
> write the actual define-node-type form above, and massage it until it
> seemed to capture the intent I want to convey, for a couple of
> interesting cases. Only then would I start to think about the macrology
> and the infrastructure needed to implement define-node-type, and start
> design and implementation of the domain-specific language.

That's surely one approach.

I often try to follow a more bottom-up approach:

* find some basic representation
* model some example problems
* define the basic operators
* play around

From there I see how I can make the whole thing more
compact and get rid of any exposed machinery.
I then have some declarative mechanism up and running.

Next I would piece by piece add features to the declarative
form and its implementation as I (or the client)
need it in the application.

Generally I prefer functional abstraction, because
it is much easier to debug. Just looking at some
of my code (a 100kb file), there is heavy use
of predefined macros, looks like almost every form
is using some macro ;-) - but I have defined myself
only one macro.

>
> Regs, Pierre.
>
> PS: For other instances of practical uses to which macros are put, one
> can look at many interesting libraries on common-lisp.net, or for
> example at most of the internals of the SBCL or CMUCL compilers, which
> would be much more verbose, without the use of macros (though some uses
> of macros in Python-the-compiler could nowadays be replaced with simple
> CLOS code, many cannot).

--
http://lispm.dyndns.org

Pascal Costanza

unread,
May 17, 2007, 2:11:46 PM5/17/07
to
Jon Harrop wrote:

>>> Another reason is that people who need macros don't bother
>>> with those other languages in the first place. :)
>
> But nobody "needs" macros, they just want them because they can make life
> easier.

"Making life easier" is a pretty good goal for a programming language.

Pierre R. Mai

unread,
May 17, 2007, 2:37:58 PM5/17/07
to
On 2007-05-17 20:03:54 +0200, Rainer Joswig <jos...@lisp.de> said:

> In article <5b3cbrF...@mid.dfncis.de>,
> Pierre R. Mai <pm...@acm.org> wrote:
>
>> This freedom also results in a different approach to design and
>> programming, IMHO: When faced with a problem like the one above, I
>> usually sit down, and analyze the problem space until I can start to
>> envisage the language I want to solve it in. That is, I would start to
>> write the actual define-node-type form above, and massage it until it
>> seemed to capture the intent I want to convey, for a couple of
>> interesting cases. Only then would I start to think about the macrology
>> and the infrastructure needed to implement define-node-type, and start
>> design and implementation of the domain-specific language.
>
> That's surely one approach.
>
> I often try to follow a more bottom-up approach:
>
> * find some basic representation
> * model some example problems
> * define the basic operators
> * play around
>
> From there I see how I can make the whole thing more
> compact and get rid of any exposed machinery.
> I then have some declarative mechanism up and running.
>
> Next I would piece by piece add features to the declarative
> form and its implementation as I (or the client)
> need it in the application.

I absolutely agree, actually: Many pieces of the massaging and problem
space analysing I alluded to above, as well as most of the actual
language implementation work and usage of the language will follow the
bottom-up approach you describe. It is just that fairly early on,
unless we are talking about a more "traditional" problem space, I will
switch into "language design mode", and try to envisage the language I
want to end up in, work towards that, rather than just trying to solve
the problem in the language as is.

Additionally building functional and OO abstractions is just as much
part of defining that language as is the macrology, which can of course
be thought of as "just" syntactic sugar on top, except that it can turn
out to be a fairly thick layer of fairly opaque sugar, in cases where
that's needed (and a thin icing on the cake in lots of other cases,
e.g. a couple of with-* and simple def-* like macros).

>
> Generally I prefer functional abstraction, because
> it is much easier to debug. Just looking at some
> of my code (a 100kb file), there is heavy use
> of predefined macros, looks like almost every form
> is using some macro ;-) - but I have defined myself
> only one macro.

Certainly one shouldn't fall into the trap of trying to do more than is
necessary in ones macros (which is probably one of the lessons learned
just after the initial exhilaration of learning about macros wears
off). And functional decomposition is most useful in defining macros as
well, e.g. the actual definition of define-node-type above is just:

(defmacro define-node-type (name (&rest supers) &rest clauses)
(let* ((name (pmsf-lib:symbolicate name '#:-node))
(clauses (canonicalize-define-node-type-clauses name clauses)))
`(progn
(defclass ,name (,@supers)
(,@(make-node-type-slot-specs clauses))
(:metaclass standard-node-class)
,@(make-node-type-option-specs clauses))
,@(make-node-type-method-forms name clauses))))


Of course the source files that contain the definitions of the helper
functions and class definitions is around 1KLOC of code...

Regs, Pierre.

Jon Harrop

unread,
May 17, 2007, 2:49:03 PM5/17/07
to
Pascal Costanza wrote:
> Jon Harrop wrote:
>>>> Another reason is that people who need macros don't bother
>>>> with those other languages in the first place. :)
>>
>> But nobody "needs" macros, they just want them because they can make life
>> easier.
>
> "Making life easier" is a pretty good goal for a programming language.

Absolutely.

Jon Harrop

unread,
May 17, 2007, 2:54:10 PM5/17/07
to
Matthias Benkard wrote:
>> I disagree and here is a counter example, a macro for infix +, -, * and /
>> with integers and brackets (a simple calculator syntax) with precedence
>> written in OCaml:
>
> What's that macro good for? What does it do?

It replaces the entire syntax with one of a simple calculator.

> Is it like a Lisp macro or something completely different?

Like a Lisp macro in the sense that it introduces syntax. In this case, the
syntax is already in the language so it is pointless in OCaml but I thought
it might be a good example to try in Lisp (implementing trivial infix
syntax) just for the purposes of comparison.

Jon Harrop

unread,
May 17, 2007, 3:55:15 PM5/17/07
to
Kent M Pitman wrote:
> For example, is your question asked with or without extending Lisp to
> hypothesize the existence of an infix parser?

I mean: what does the implementation of a Lisp macro that provides minimal
infix syntax look like?

> How is OCaml on adding readmacros, which Lisp can do easily.

I think they are the equivalent of camlp4 quotations.

Raffael Cavallaro

unread,
May 17, 2007, 6:30:50 PM5/17/07
to
On 2007-05-17 14:54:10 -0400, Jon Harrop <j...@ffconsultancy.com> said:

> In this case, the
> syntax is already in the language so it is pointless in OCaml but I thought
> it might be a good example to try in Lisp (implementing trivial infix
> syntax) just for the purposes of comparison.

I think one theme of this thread is that lisp macros aren't put to
their most powerful use by implementing trivial syntax modifications.
Rather, they are valued because they allow programmers to define
syntactically simple constructs that expand to large complex bodies of
code that they would otherwise have to repeatedly type as boilerplate.

In this specific case of infix syntax, the most widely used reader
macro implements the following 30-odd infix constructs, which I think
you'll agree is not trivial - it also includes c-style array syntax
btw. Moreover, since it works on top of common lisp, it works for
fixnums, bignums, rationals, floats and complex numbers where
applicable, and not just machine integers.

;;; Operators:
;;;
;;; NOTE: == is equality, = is assignment (C-style).
;;;
;;; \ quoting character: x\-y --> x-y
;;; ! lisp escape !(foo bar) --> (foo bar)
;;; ; comment
;;; x = y assignment (setf x y)
;;; x += y increment (incf x y)
;;; x -= y decrement (decf x y)
;;; x *= y multiply and store (setf x (* x y))
;;; x /= y divide and store (setf x (/ x y))
;;; x|y bitwise logical inclusive or (logior x y)
;;; x^y bitwise logical exclusive or (logxor x y)
;;; x&y bitwise logical and (logand x y)
;;; x<<y left shift (ash x y)
;;; x>>y right shift (ash x (- y))
;;; ~x ones complement (unary) (lognot x)
;;; x and y conjunction (and x y)
;;; x && y conjunction (and x y)
;;; x or y disjunction (or x y)
;;; x || y disjunction (or x y)
;;; not x negation (not x)
;;; x^^y exponentiation (expt x y)
;;; x,y sequence (progn x y)
;;; (x,y) sequence (progn x y)
;;; also parenthesis (x+y)/z --> (/ (+ x y) z)
;;; f(x,y) functions (f x y)
;;; a[i,j] array reference (aref a i j)
;;; x+y x*y arithmetic (+ x y) (* x y)
;;; x-y x/y arithmetic (- x y) (/ x y)
;;; -y value negation (- y)
;;; x % y remainder (mod x y)
;;; x<y x>y inequalities (< x y) (> x y)
;;; x <= y x >= y inequalities (<= x y) (>= x y)
;;; x == y equality (= x y)
;;; x != y equality (not (= x y))
;;; if p then q conditional (when p q)
;;; if p then q else r conditional (if p q r)
;;;

;;; Precedence:
;;;
;;; The following precedence conventions are obeyed by the infix operators:
;;; [ ( !
;;; ^^
;;; ~
;;; * / %
;;; + -
;;; << >>
;;; < == > <= != >=
;;; &
;;; ^
;;; |
;;; not
;;; and
;;; or
;;; = += -= *= /=
;;; ,
;;; if
;;; then else
;;; ] )
;;;
;;; Note that logical negation has lower precedence than numeric comparison
;;; so that "not a<b" becomes (not (< a b)), which is different from the
;;; C precedence conventions. You can change the precedence conventions by
;;; modifying the value of the variable *operator-ordering*.

Geoff Wozniak

unread,
May 17, 2007, 7:24:27 PM5/17/07
to
On May 17, 12:58 pm, Jon Harrop <j...@ffconsultancy.com> wrote:

> Geoff Wozniak wrote:
> > - A pattern matcher (!) that matches over sequences allowing for the
> > expression of dependent patterns. Furthermore, the patterns
> > themselves are objects capturing the current continuation of the match
> > and can be used to find all possible matches of a pattern to a
> > sequence. The patterns can match arbitrary functional transformations
> > on the sub-elements,so matching something like [x y] where y =
> > (reverse x) is easy to express.
>
> How is this different to "Foo(x, y) when y = rev x -> ..."?
>

[x y] describes a match over any sequence where x and y represent a
subsequence of the sequence being matched. For example, it would
match all of the following. ('=' should be read as "is bound to")

"0110" => x = "01", y = "10"
'(0 1 1 0) => x = '(0 1), y = '(1 0)
#(0 1 1 0) => x = #(0 1), y = #(1 0)
#*0110 => x = #*01, y = #*10
etc.

The macro itself merely describes the pattern language. The pattern
matcher itself is all functional, but interacting with it via the
functional interface is tedious. (And there was no technical reason I
switched to Lisp from OCaml -- I just didn't enjoy working on it in
OCaml.)

Frederic Beal

unread,
May 18, 2007, 12:03:23 AM5/18/07
to
On 2007-05-17, Jon Harrop <j...@ffconsultancy.com> wrote:
>> How is OCaml on adding readmacros, which Lisp can do easily.
>
> I think they are the equivalent of camlp4 quotations.

Did you bother to check what a reader macro is ?

By the way, when I wrote my first Lisp macro, it was like this :
* read 5 min a tutorial
* write a not-so-trivial example of macro (it would expand
(power x #'* 5) into something like
(let* ((x1 (* x x))
(x2 (* x1 x1))
(x3 (* x x2)))
x3)
(took ~30 min, I wasn't much at ease with Lisp at that time)
* run and use.

I tried to do the same thing in OCaml, which was a language I had been
using for > 5 years
* read 1 hour the tutorial on ocamlp4
* try to code a trivial example
* fail miserably
* get upset

In Lisp, defining a macro is painless, thanks to the s-exps.
In OCaml, defining a macro is a pain in the ass, thanks to strong typing
and an invasive syntax.

And, and, and, let's take another example : the *where* thing, which
is very, very convenient in Haskell but absent from OCaml
(e.g. you would write in pseudo-ocaml
let power16 x = ret
where ret = p8 * p8
and p8 = p4 * p4
and p4 = p2 * p2
and p2 = x * x;;)
because it enables you to think top-bottom and not bottom up.

You can make such a macro, sure, because "a where b" is nothing more than
"let rec b in a". But... it will BREAK the indentation algorithm of your
editor, because of course where is now special syntax, and the hard-coded
rules won't apply. I find this *most* annoying.

As a conclusion, yes, the OCaml macro system is a good thing, but it is
sooo expensive in terms of programmation effort that you will think twice
before taking one hour to implement a small utility that will integrate
into existing code as well as a dead toad on a wedding cake.

--
Frederic

Pascal Costanza

unread,
May 18, 2007, 4:12:15 AM5/18/07
to
Jon Harrop wrote:
> Kent M Pitman wrote:
>> For example, is your question asked with or without extending Lisp to
>> hypothesize the existence of an infix parser?
>
> I mean: what does the implementation of a Lisp macro that provides minimal
> infix syntax look like?

(defmacro infix (head &body tail)
(if tail
`(infix (,(car tail) ,head ,(cadr tail)) ,@(cddr tail))
head)))

How do you add minimal support for prefix syntax to OCaml?

Dan Bensen

unread,
May 18, 2007, 5:20:37 AM5/18/07
to
Pascal Costanza wrote:
> Jon Harrop wrote:
>> I mean: what does the implementation of a Lisp macro that provides
>> minimal
>> infix syntax look like?
> (defmacro infix (head &body tail)
> (if tail
> `(infix (,(car tail) ,head ,(cadr tail)) ,@(cddr tail))
> head)))
> How do you add minimal support for prefix syntax to OCaml?

It's trivial:
(+) x y
(*) a b
etc.
although it doesn't handle optional args. For that,
you would need a separate function that takes a list.

I wouldn't get too worked up over trivial character-level examples
like this. Lisp macros don't particularly excel at character twiddling.
As Frederic Beal said, WHERE is a better example. It makes a bigger
difference in the code, and can ben done within the standard Lisp
sexpr convention.

Rafael Cavallaro said it even better:


> Macros are much more usefully employed to provide domain specific

> constructs thus allowing one to program the solution to the problem


> in the language of the language of the problem domain itself. Anyone
> who has used lisp for a while simply doesn't care to make the
> "common" syntax cases of lisp look like their equivalents in C
> or Perl or Python. With regard to macros, we're concerned with
> making sexps look like the terminology and usage of the
> *problem domain*, not making sexps look like c or python.

My understanding is that Camlp4 is one of the best macro systems
outside of Lisp. You won't get anywhere arguing that Lisp can
do low-level character manipulation any better. The real advantages
to Lisp macros are things like LOOP and CLOS. How in the world would
one implement those things in OCaml? Is Camlp4 even Turing complete?
(It might be, I'd like to know.) How expressive is it? It can't
possible comapare to the entire Lisp language. For instance, suppose
you wanted to implement CLOS-style generics and methods in OCaml.
Would that be possible in Camlp4? How hard would it be?

The Common Lisp design is optimized for large, complex programs
being written by capable, professional programmers who don't whine
about little symantic issues just because they've never seen them.
It's not an algebraic-style script-kiddie language. Let the troll
have his superficial syntactic crumbs and sugary treats. What Lisp
has that he's missing is more substantial, more meaty. It allows
huge swaths of code to be automatically written by a single form.
It's not about relief of minor inconveniences to a beginner or
nonprogrammer, it's about saving hundreds, maybe even thousands,
of expensive professional programmers' man-hours because they
don't have to keep copying, pasting, and maintaining code that can
be encapsulated once and used at will. That's the primary argument
supporting Lisp over other languages. Other issues should be
left alone. IMHO.

--
Dan
www.prairienet.org/~dsb/

Jon Harrop

unread,
May 18, 2007, 7:34:36 AM5/18/07
to
Raffael Cavallaro wrote:
> On 2007-05-17 14:54:10 -0400, Jon Harrop <j...@ffconsultancy.com> said:
>> In this case, the
>> syntax is already in the language so it is pointless in OCaml but I
>> thought it might be a good example to try in Lisp (implementing trivial
>> infix syntax) just for the purposes of comparison.
>
> I think one theme of this thread is that lisp macros aren't put to
> their most powerful use by implementing trivial syntax modifications.

Sure, but I doubt anyone will both translating a big macro from one language
into another just for the purposes of this discussion. So we're stuck with
simpler examples.

> In this specific case of infix syntax, the most widely used reader
> macro implements the following 30-odd infix constructs, which I think
> you'll agree is not trivial - it also includes c-style array syntax
> btw. Moreover, since it works on top of common lisp,

Yes. We could compare the source code to this infix macro in Lisp with
something equivalent in OCaml. As it is mostly duplication, can you post a
subset of that infix macro that implements something similar to the OCaml
macro I posted?

> it works for
> fixnums, bignums, rationals, floats and complex numbers where
> applicable, and not just machine integers.

Using other number types in OCaml is trivial: just replace int with num in
the macro I gave and the operators, e.g. "+" with "+/".

Jon Harrop

unread,
May 18, 2007, 7:43:13 AM5/18/07
to
Dan Bensen wrote:
> Pascal Costanza wrote:
>> Jon Harrop wrote:
>>> I mean: what does the implementation of a Lisp macro that provides
>>> minimal
>>> infix syntax look like?
>> (defmacro infix (head &body tail)
>> (if tail
>> `(infix (,(car tail) ,head ,(cadr tail)) ,@(cddr tail))
>> head)))

How does this handle the operator precedences and associativities?

>> How do you add minimal support for prefix syntax to OCaml?
>
> It's trivial:
> (+) x y
> (*) a b

I think Pascal wants to write in s-expr notation rather than prefix, so:

(+ x y)

This is also trivial to add to OCaml. You can guess just by rewriting the
macro I gave:

[ "("; "+"; e1 = expr; e2 = expr; ")" -> e1 + e2
...

and so on. If you want to support argument lists then:

[ "("; "+"; es = expr_list; ")" -> e1 + e2
...

if you want to defer function lookup for application to run-time then
something like:

[ "("; op; es = expr_list; ")" -> apply op e1 e2
...

This doesn't seem any harder or easier than writing a Lisp macro to me.

> etc.
> although it doesn't handle optional args. For that,
> you would need a separate function that takes a list.

That isn't really syntax related.

> My understanding is that Camlp4 is one of the best macro systems
> outside of Lisp. You won't get anywhere arguing that Lisp can
> do low-level character manipulation any better. The real advantages
> to Lisp macros are things like LOOP and CLOS. How in the world would
> one implement those things in OCaml?

Probably in exactly the same way.

> Is Camlp4 even Turing complete?

Yes.

> (It might be, I'd like to know.) How expressive is it?

Exactly the same as Lisp, AFAIK.

Jon Harrop

unread,
May 18, 2007, 7:54:15 AM5/18/07
to
Geoff Wozniak wrote:
> On May 17, 12:58 pm, Jon Harrop <j...@ffconsultancy.com> wrote:
>> How is this different to "Foo(x, y) when y = rev x -> ..."?
>
> [x y] describes a match over any sequence where x and y represent a
> subsequence of the sequence being matched.

This is exactly like Mathematica. Having seen Richard Fateman's Lisp
implementation, WRI were expecting me to write something similar using
macros and basing my implementation upon OCaml itself. This didn't even
occur to me and I went straight for a full-blown JIT compiler from day one.

> For example, it would
> match all of the following. ('=' should be read as "is bound to")
>
> "0110" => x = "01", y = "10"
> '(0 1 1 0) => x = '(0 1), y = '(1 0)
> #(0 1 1 0) => x = #(0 1), y = #(1 0)
> #*0110 => x = #*01, y = #*10
> etc.
>
> The macro itself merely describes the pattern language. The pattern
> matcher itself is all functional, but interacting with it via the
> functional interface is tedious. (And there was no technical reason I
> switched to Lisp from OCaml -- I just didn't enjoy working on it in
> OCaml.)

Right. I did something similar to make writing Mathematica interpreters
easier in OCaml by extending the pattern matcher to support matching over
balanced binary trees.

If you wrote a pattern match like:

| [:x; y:] -> ...

then it would macro expand into:

| Node(Node(Empty, x, Empty), y, Empty)
| Node(Empty, x, Node(Empty, y, Empty)) -> ...

I implemented the pattern matcher functionally rather than using macros.

Tim Bradshaw

unread,
May 18, 2007, 8:09:50 AM5/18/07
to
On May 18, 10:20 am, Dan Bensen <randomg...@cyberspace.net> wrote:

> It's not about relief of minor inconveniences to a beginner or
> nonprogrammer, it's about saving hundreds, maybe even thousands,
> of expensive professional programmers' man-hours because they
> don't have to keep copying, pasting, and maintaining code that can
> be encapsulated once and used at will. That's the primary argument
> supporting Lisp over other languages. Other issues should be
> left alone. IMHO.

I can give a nice first-hand example of this. We have a documentation
preparation system loosely known as DTML (some bits of which I have
mentioned before). We used it to prepare training materials and other
stuff. DTML basically is lisp macros: the flow is actually something
like:

- markup typed by us (was once sexps, is now TML);
- parsed trivially into sexps;
- sexps are rewritten using a lot of quasiquotation type stuff;
- end result is a sexp representation of (normally) HTML;
- emitted as HTML;
- converted to PS and hence to PDF;
- goes to printer (never, ever give out machine readable versions of
stuff like this to people. They will almost always steal it.)

The rewriting bit is (for these purposes) the interesting bit - the
parser is trivial, it just takes something easier to type than sexps
(which in turn are easier to type than XML/HTML, even for text
markup!). The rewriting isn't, I suppose, technically, Lisp macros:
they're not defined with DEFMACRO, but in any useful sense they are
Lisp macros: if Lisp didn't have such good support for macros they
couldn't be written.

DTML is pretty rudimentary in glamorous application terms. But it
wasn't meant to be cool, it was meant to do a job. That job was to
provide a system for document preparation which can support people who
are doing this job approximately an order of magnitude faster than
average.

We used DTML to produce hundreds of pages of polished (it went to
customers, and not as an added-value thing, as what they paid for),
and very technical documentation in small single-digit numbers of
weeks. You can't do this with Word, and you definitely can't do it
typing XML because there is simply too much non-text to type - TML is
optimised to have hardly any markup overhead (one of the remaining
annoyances is that you need to hit shift too often).

Note, I'm not claiming that DTML somehow magically made us 10 times as
productive: it didn't. In order to produce documentation at that rate
you have to be able to type good English really, really fast, and most
people just can't do that. (I'm reasonably good, but my partner is
probably at least twice as fast as me.) However, people who *can* do
that need tools that don't get in the way. DTML is such a tool, and
DTML depends intimately on Lisp macros.

There are other places where similar things apply: the Unix command
line is a good example. It's basically this hostile thing which naive
users hate. But that isn't who it was designed to support, and the
people who it was designed to support love it because you can get so
much done so quickly: (cat yppasswd; getent passwd) | awk -F: '{print
$3, $1}' |sort -k 1 -u | perl passwd2sql | sqlite3 idmap.db

--tim

It is loading more messages.
0 new messages