From: Jacek Generowicz
Subject: Constructing symbols
Date: 
Message-ID: <g0k81r3669.fsf@scumbag.ecs.soton.ac.uk>
Greetings from a lisp neophyte.

Is there a way to construct a symbol from strings (or other symbols)
for use in macros such as defun or defclass ?

I've been trying things along the following lines, but without
earth-shattering success . . .

(make-symbol (concatenate 'string (string 'foo) "-BAR")) 

What I am really trying to do is to automate the mixing in of a mixin
into a whole bunch of classes.

I find myself repeatedly having to do something similar to

(defclass foo-with-bar (foo bar)
  (some-more-stuff))

which I would like to substitute with

(defmacro barify (other) . . . )
(barify foo)  ->  <class foo-bar>
(barify baz)  ->  <class foo-baz>
etc.

I wouldn't be surprised if this is completely misguided, and would
welcome constructive or edifying comments.

Thanks,

Jacek

From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfw1ynzmlpi.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> Greetings from a lisp neophyte.

Welcome.
 
> Is there a way to construct a symbol from strings (or other symbols)
> for use in macros such as defun or defclass ?
> 
> I've been trying things along the following lines, but without
> earth-shattering success . . .
> 
> (make-symbol (concatenate 'string (string 'foo) "-BAR")) 

This won't end up with the symbol interned.  Instead of MAKE-SYMBOL,
use INTERN, and then you'll be able to type the symbol.
 
Note, of course, that INTERN will intern in the current package,
the value of *PACKAGE*, unless you specify another package as the
second argument.  Often just using the current package is fine, so a
one-argument call to INTERN may be fine, but you should not do this
without understanding the consequences.

Btw, personally, I often use 
 (format nil "~A-BAR" 'foo)
but a lot of people don't like that because it exposes the uppercase
nature of the language.  And someone at Xanalys pointed out to me that
using PRINC gets printer control variables like *PRINT-LINES* involved;
in practice I've never been bitten by that, but it's a potential problem.

Once in a while I write something like
 (defun symbolconc (&rest pieces)
    (intern (apply #'concatenate 'string (mapcar #'string pieces))))
so I can just do
 (symbolconc 'foo '-bar)

SYMBOLCONC is the traditional name for this operation, going way back to
macro packages that used to be popular in the 70's.  [It went away because
of a fight over what package to use.  Some people said use the prevailing
package, but that made some programs unpredictable if *package* could vary.
Some people said use the package of the first arg, but that had the weird
property that if you did (symbolconc 'set x) you ended up trying to intern
int the CL package because SET was inherited from the CL package.  The
DEFCLASS style of just specifying symbols was the result; see more 
discussion below.]


> What I am really trying to do is to automate the mixing in of a mixin
> into a whole bunch of classes.

Ah, well, that's a potentially entirely different issue....
 
> I find myself repeatedly having to do something similar to
> 
> (defclass foo-with-bar (foo bar)
>   (some-more-stuff))
> 
> which I would like to substitute with
> 
> (defmacro barify (other) . . . )
> (barify foo)  ->  <class foo-bar>
> (barify baz)  ->  <class foo-baz>
> etc.

Ok.  Even when you do this, though, the modern style is to make barify
take the names of the symbols rather than you composing them.  This is
useful both for "grep" purposes [since a search will turn up a
reference to foo-bar for (barify foo-bar foo) but not for (barify foo)]
and also because it doesn't risk getting the symbol in the wrong package.

DEFSTRUCT uses the old-style where it manufactures symbols all over the 
place. DEFCLASS is the new-style, where for each thing it makes for you,
you have to give it the name of the thing.

> I wouldn't be surprised if this is completely misguided, and would
> welcome constructive or edifying comments.

Not completely misguided.  But it's the sort of thing that has a lot of
subtlety in it.  
From: Jacek Generowicz
Subject: Re: Constructing symbols
Date: 
Message-ID: <g0d77jqp4u.fsf@scumbag.ecs.soton.ac.uk>
Kent M Pitman <······@world.std.com> writes:

> Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> 
> > Greetings from a lisp neophyte.
> 
> Welcome.

Thank you.

> > (make-symbol (concatenate 'string (string 'foo) "-BAR")) 
> 
> This won't end up with the symbol interned.

I'm all too aware of that.

> Instead of MAKE-SYMBOL, use INTERN, and then you'll be able to type
> the symbol.

Do you mean something like this?

(let ((new-symbol (intern "foo-bar")))
  (setf (symbol-function new-symbol) (lambda (x) (1+ x))))

(foo-bar 12) -> 13

That's a stage further than I have got so far.

> Note, of course, that INTERN will intern in the current package,
> the value of *PACKAGE*, unless you specify another package as the
> second argument.

Good to know. Thanks.

> Btw, personally, I often use 
>  (format nil "~A-BAR" 'foo)
> but a lot of people don't like that because it exposes the uppercase
> nature of the language.

I don't see why this would be a Bad Thing.

>  And someone at Xanalys pointed out to me that
> using PRINC gets printer control variables like *PRINT-LINES* involved;
> in practice I've never been bitten by that, but it's a potential problem.

And this is because princ is used by format ?

> Once in a while I write something like
>  (defun symbolconc (&rest pieces)
>     (intern (apply #'concatenate 'string (mapcar #'string pieces))))

I like it.

> so I can just do
>  (symbolconc 'foo '-bar)
> 
> SYMBOLCONC is the traditional name for this operation, going way back to
> macro packages that used to be popular in the 70's.  [It went away because
> of a fight over what package to use.  Some people said use the prevailing
> package, but that made some programs unpredictable if *package* could vary.
> Some people said use the package of the first arg, but that had the weird
> property that if you did (symbolconc 'set x) you ended up trying to intern
> int the CL package because SET was inherited from the CL package.

What would have been wrong with specifying the package in an
(optional) argument, as in the case of intern itself ?

> The
> DEFCLASS style of just specifying symbols was the result; see more 
> discussion below.]
> 
> 
> > What I am really trying to do is to automate the mixing in of a mixin
> > into a whole bunch of classes.
> 
> Ah, well, that's a potentially entirely different issue....

Thought as much . . . but then I hoped to learn something about
maniputlating symbols, even if it isn't the best way to solve my
problem (so much to learn, and life is so short).

> > I find myself repeatedly having to do something similar to
> > 
> > (defclass foo-with-bar (foo bar)
> >   (some-more-stuff))
> > 
> > which I would like to substitute with
> > 
> > (defmacro barify (other) . . . )
> > (barify foo)  ->  <class foo-bar>
> > (barify baz)  ->  <class foo-baz>
> > etc.
> 
> Ok.  Even when you do this, though, the modern style is to make barify
> take the names of the symbols rather than you composing them.  This is
> useful both for "grep" purposes

A good point. Though in this case I am tempted to do something like

(dolist (class '(foo baz qux etc))
	(barify class))

> and also because it doesn't risk getting the symbol in the wrong package.

I don't immediately see how it helps to remedy this.

> DEFSTRUCT uses the old-style where it manufactures symbols all over the 
> place.

?

> > I wouldn't be surprised if this is completely misguided, and would
> > welcome constructive or edifying comments.
> 
> Not completely misguided.  But it's the sort of thing that has a lot of
> subtlety in it.  

Seems to be generally true of lisp. (Well, generally true of most
languages, but lisp is introducing me to new kinds of subtleties.)


OK, I still feel I'm missing quite a bit here.

Could you criticize/improve the following pseudo-lisp, which is
intended to help me achieve my stated goal?

(defmacro barify (class &body some-other-stuff)
  `(defclass (intern (format nil "~a-BAR" ,class)) ()
     ,@some-other-stuff))

In particular, I do not see how to make defclass use the new symbol I
intern; with defun I could get around it with the use of
symbol-function.

Thanks,

Jacek
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwofr3z1k2.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> Kent M Pitman <······@world.std.com> writes:
> > >
> > > (make-symbol (concatenate 'string (string 'foo) "-BAR")) 
> > 
> > This won't end up with the symbol interned. [...]
> > Instead of MAKE-SYMBOL, use INTERN, and then you'll be able to type
> > the symbol.
> 
> Do you mean something like this?
> 
> (let ((new-symbol (intern "foo-bar")))
>   (setf (symbol-function new-symbol) (lambda (x) (1+ x))))
> 
> (foo-bar 12) -> 13

Yes, certainly.  But intern is also importnat so you can even deal
with data you can name from the keyboard. e.g.,
 (eq 'foo-bar (intern "FOO-BAR")) => T
Contrast this with
 (eq 'foo-bar (make-symbol "FOO-BAR")) => NIL

> That's a stage further than I have got so far.

Sounds like you'll get there.
 
> > Btw, personally, I often use 
> >  (format nil "~A-BAR" 'foo)
> > but a lot of people don't like that because it exposes the uppercase
> > nature of the language.
> 
> I don't see why this would be a Bad Thing.

A lot of people think that uppercase is synonymous with "antiquated",
"funny-looking", "slow", "cumbersome", "ugly", and "spawn of Satan".

There are some legit objections to uppercase like that it's harder to
type on a normal keyboard.  But for as often as it comes up, this is a
really tiny issue.

> >  And someone at Xanalys pointed out to me that
> > using PRINC gets printer control variables like *PRINT-LINES* involved;
> > in practice I've never been bitten by that, but it's a potential problem.
> 
> And this is because princ is used by format ?

Well, really the problem is WRITE.  But yes.  FORMAT's ~A calls PRINC
calls WRITE.
 
> > Once in a while I write something like
> >  (defun symbolconc (&rest pieces)
> >     (intern (apply #'concatenate 'string (mapcar #'string pieces))))
> 
> I like it.
> 
> > so I can just do
> >  (symbolconc 'foo '-bar)
> > 
> > SYMBOLCONC is the traditional name for this operation, going way back to
> > macro packages that used to be popular in the 70's.  [It went away because
> > of a fight over what package to use.  Some people said use the prevailing
> > package, but that made some programs unpredictable if *package* could vary.
> > Some people said use the package of the first arg, but that had the weird
> > property that if you did (symbolconc 'set x) you ended up trying to intern
> > int the CL package because SET was inherited from the CL package.
> 
> What would have been wrong with specifying the package in an
> (optional) argument, as in the case of intern itself ?

Well, since the function I supplied has a rest argument, the "optional" 
argument would need to be first, rather than last.  Most people would
make it required rather than optional, though with dynamic typing  you could
make it optional if you didn't mind that you had to pass a real package object.
People are used to substituting package names for packages in most places,
but here it would be ambiguous.
 (symbolconc *package* 'foo '-bar)
is fine but
 (symbolconc (package-name *package*) 'foo '-bar)
presumably would return CL-USERFOO-BAR or whatever.
 
> > The
> > DEFCLASS style of just specifying symbols was the result; see more 
> > discussion below.]
> > 
> > 
> > > What I am really trying to do is to automate the mixing in of a mixin
> > > into a whole bunch of classes.
> > 
> > Ah, well, that's a potentially entirely different issue....
> 
> Thought as much . . . but then I hoped to learn something about
> maniputlating symbols, even if it isn't the best way to solve my
> problem (so much to learn, and life is so short).

It's quite important to understand how all this works so you know when you
might want to use it, so you can debug problems created by others, etc.

And a lot of good work DOES get done with symbolconc'd symbols, don't get
me wrong.  Style rules are funny things. They are trade-offs to consider.
One doesn't always buy every one for every application.  They are just things
you should weigh...
 
> > > I find myself repeatedly having to do something similar to
> > > 
> > > (defclass foo-with-bar (foo bar)
> > >   (some-more-stuff))
> > > 
> > > which I would like to substitute with
> > > 
> > > (defmacro barify (other) . . . )
> > > (barify foo)  ->  <class foo-bar>
> > > (barify baz)  ->  <class foo-baz>
> > > etc.
> > 
> > Ok.  Even when you do this, though, the modern style is to make barify
> > take the names of the symbols rather than you composing them.  This is
> > useful both for "grep" purposes
> 
> A good point. Though in this case I am tempted to do something like
> 
> (dolist (class '(foo baz qux etc))
>       (barify class))

This won't work with a macro.  Maybe you meant:

 (defmacro barify* (classes)
   `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
      t))
 (barify foo baz qux ;normally spelled  quux, but i guess you like 3letters
         etc)

Then again, you could always do:

 (defmacro barify* (class-pairs)
   `(progn ,@(mapcar #'(lambda (pair) `(barify ,@pair)) class-pairs)
      t))
 (barify* (foo-bar foo)
          (baz-bar baz)
          (qux-bar qux)
          (etc-bar etc))
 
> > and also because it doesn't risk getting the symbol in the wrong package.
> 
> I don't immediately see how it helps to remedy this.

Because you can pick any old symbol you want, even one with no package or
synbol-name relation to other. e.g.,

 (barify* (fu-bahr foo))
 
> > DEFSTRUCT uses the old-style where it manufactures symbols all over the 
> > place.
> 
> ?

See the :conc-name option.

 (defstruct kons kar kdr)

defaults its accessor names to kons-kar and kons-kdr.  You can use 
:conc-name to affect this.

In this case, though, since accessors are generic, a lot of people
use (:conc-name nil) because they want generic accessor names, not
ones that have a type name in front.

> > > I wouldn't be surprised if this is completely misguided, and would
> > > welcome constructive or edifying comments.
> > 
> > Not completely misguided.  But it's the sort of thing that has a lot of
> > subtlety in it.  
> 
> Seems to be generally true of lisp. (Well, generally true of most
> languages, but lisp is introducing me to new kinds of subtleties.)

It intends to allow you to be as blunt or subtle as you like.
It's quite flexible.  But you have to know when to recognize subtlety.
 
> OK, I still feel I'm missing quite a bit here.
> 
> Could you criticize/improve the following pseudo-lisp, which is
> intended to help me achieve my stated goal?
> 
> (defmacro barify (class &body some-other-stuff)
>   `(defclass (intern (format nil "~a-BAR" ,class)) ()
>      ,@some-other-stuff))

Feel free to variables to help you make sub-problems and to document what
you are doing.  

Also, from a technical standpoint, you're missing a , in front of the intern
and you dno't need it it front of class in the subform as a consequence.

 (defmacro barify (class &body some-other-stuff)
   `(defclass ,(intern (format nil "~a-BAR" class)) ()
      ,@some-other-stuff))

or, perhaps:

 (defmacro barify (class &body barified-class-options)
   (let ((barified-class-name (intern (format nil "~a-BAR" class))))
     `(defclass ,barified-class-name ()
        ,@barified-class-options)))

or:

 (defmacro barify (class &body class-options)
   (setf class-options (copy-list class-options))
   (let* ((class-option (assoc :class class-options))
          (class-name
            (or (second class-option)
                (intern (format nil "~a-BAR" class)))))
     (when class-option 
       (setq class-options (delete class-option class-options)))
     `(defclass ,class-name ()
        ,@class-options)))

> In particular, I do not see how to make defclass use the new symbol I
> intern; with defun I could get around it with the use of
> symbol-function.

You have to do the call to INTERN at macroexpand time (inside the comma)
not at DEFCLASS time, since DEFCLASS does not evaluate that argument.
From: Jacek Generowicz
Subject: Re: Constructing symbols
Date: 
Message-ID: <g0d77i1l3u.fsf@scumbag.ecs.soton.ac.uk>
Kent M Pitman <······@world.std.com> writes:

>                  But intern is also importnat so you can even deal
> with data you can name from the keyboard. e.g.,
>  (eq 'foo-bar (intern "FOO-BAR")) => T

Hmmm. OK . . . the hyperspec says the following about intern:

  If a symbol whose name is the same as string is already accessible in
  package, it is returned.

Which relieves the unease I had on first seeing your example. Or does
it? Maybe not . . . I still have doubts about what intern does.

(unintern 'foo-bar)
(eq 'foo-bar 'foo-baz)
(is-interned-p 'foo-bar)  => nil ?
(eq 'foo-bar (intern "FOO-BAR"))
(is-interned-p 'foo-bar)  => t ? 

[What do I mean by is-interned-p ?]

> > (dolist (class '(foo baz qux etc))
> >       (barify class))
> 
> This won't work with a macro.

Yup.

>  Maybe you meant:
> 
>  (defmacro barify* (classes)
>    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
>       t))

Is there not an implicit progn ?

Is the t there only to specify the return value ?

>  (barify foo baz qux ;normally spelled  quux, but i guess you like 3letters
>          etc)
> 
> Then again, you could always do:
> 
>  (defmacro barify* (class-pairs)
>    `(progn ,@(mapcar #'(lambda (pair) `(barify ,@pair)) class-pairs)
>       t))
>  (barify* (foo-bar foo)
>           (baz-bar baz)
>           (qux-bar qux)
>           (etc-bar etc))

Good suggestion.

> > (defmacro barify (class &body some-other-stuff)
> >   `(defclass (intern (format nil "~a-BAR" ,class)) ()
> >      ,@some-other-stuff))

> Also, from a technical standpoint, you're missing a , in front of the intern
> and you dno't need it it front of class in the subform as a consequence.
> 
>  (defmacro barify (class &body some-other-stuff)
>    `(defclass ,(intern (format nil "~a-BAR" class)) ()
>       ,@some-other-stuff))

I think that you have just removed a mind-clot I had about the comma
operator. But now I really am more puzzled about intern. Maybe my
ideas about it need to ferment a bit more.

>  (defmacro barify (class &body class-options)
>    (setf class-options (copy-list class-options))
>    (let* ((class-option (assoc :class class-options))
>           (class-name
>             (or (second class-option)
>                 (intern (format nil "~a-BAR" class)))))
>      (when class-option 
>        (setq class-options (delete class-option class-options)))
>      `(defclass ,class-name ()
>         ,@class-options)))

(barify foo ((stuff))) -> (defclass foo-bar () ((stuff)))
(barify foo ((stuff) (:class 'quux))) - > (defclass quux () ((stuff)))

?

Thanks for all your input. Much appreciated.

Jacek
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwbsn124un.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> >                  But intern is also importnat so you can even deal
> > with data you can name from the keyboard. e.g.,
> >  (eq 'foo-bar (intern "FOO-BAR")) => T
> 
> Hmmm. OK . . . the hyperspec says the following about intern:
> 
>   If a symbol whose name is the same as string is already accessible in
>   package, it is returned.
> 
> Which relieves the unease I had on first seeing your example. Or does
> it? Maybe not . . . I still have doubts about what intern does.
> 
> (unintern 'foo-bar)
> (eq 'foo-bar 'foo-baz)
> (is-interned-p 'foo-bar)  => nil ?

Typing 'foobar makes a new such symbol.  READ creates symbols
that you name which did not previously exist as interned, unexported
symbols of the current package.

> (eq 'foo-bar (intern "FOO-BAR"))
> (is-interned-p 'foo-bar)  => t ? 
> 
> [What do I mean by is-interned-p ?]

(defun is-interned-p (symbol &optional (package *package*))
  (check-type symbol symbol)
  (multiple-value-bind (present-symbol status)
      (find-symbol (symbol-name symbol) package)
    (and status (eq symbol present-symbol))))

You might find it mroe useful to do

 (unintern 'foo-bar)
 (find-symbol "FOO-BAR")
 => NIL, NIL
 'foo-bar ;for side-effect of making the symbol again
 => FOO-BAR
 (find-symbol "FOO-BAR")
 => FOO-BAR, :INTERNAL

> >  Maybe you meant:
> > 
> >  (defmacro barify* (classes)
> >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> >       t))
> 
> Is there not an implicit progn ?

Well, that's an explicit progn.

The result of a macro is always a single form.  To return multiple
forms, put them in a progn.

I returned t here because it annoys me to see

 (def-foo a b c)
 => c

It makes me worry it failed to process A and B.

I could also have returned ',classes but I chose not to for
fairly arbitrary reasons.

> >  (defmacro barify (class &body some-other-stuff)
> >    `(defclass ,(intern (format nil "~a-BAR" class)) ()
> >       ,@some-other-stuff))
> 
> I think that you have just removed a mind-clot I had about the comma
> operator. But now I really am more puzzled about intern. Maybe my
> ideas about it need to ferment a bit more.

When you get a coherent question, do ask.
 
> >  (defmacro barify (class &body class-options)
> >    (setf class-options (copy-list class-options))
> >    (let* ((class-option (assoc :class class-options))
> >           (class-name
> >             (or (second class-option)
> >                 (intern (format nil "~a-BAR" class)))))
> >      (when class-option 
> >        (setq class-options (delete class-option class-options)))
> >      `(defclass ,class-name ()
> >         ,@class-options)))
> 
> (barify foo ((stuff))) -> (defclass foo-bar () ((stuff)))
> (barify foo ((stuff) (:class 'quux))) - > (defclass quux () ((stuff)))
> 
> ?

Almost. &body gets all remaining arguments as a list, no need for extra
parens around them.  ,@ splices that list back into the defclass.

 (barify foo (:class quux))
 (barify foo (stuff) (:class quux))
 (barify foo (:metaclass my-metaclass) (:class quux))

The idea was to let you override the default class name if you
needed to avoid some name conflict but wanted the same functionality.
The idea is that ordinarily you wouldn't specify this, and it wouldn't
take up any syntactic space.

I picked :class by analogy to the fact that you can already specify
:metaclass.

By the way, there's a bug in my expansion.  You presumably want
 `(defclass ,class-name (bar) 
    ,@class-options)
That is, you want to mix in the BAR class.  Otherwise it's not very
barified.  That's what I get for not testing this code before sending
it out. Sorry.

> Thanks for all your input. Much appreciated.

Happy to be of help.
From: Jacek Generowicz
Subject: Re: Constructing symbols
Date: 
Message-ID: <g0hewtf6g4.fsf@scumbag.ecs.soton.ac.uk>
Kent M Pitman <······@world.std.com> writes:

> Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> 
> > Kent M Pitman <······@world.std.com> writes:

> > (eq 'foo-bar (intern "FOO-BAR"))
> > (is-interned-p 'foo-bar)  => t ? 
> > 
> > [What do I mean by is-interned-p ?]
> 
> (defun is-interned-p (symbol &optional (package *package*))
>   (check-type symbol symbol)
>   (multiple-value-bind (present-symbol status)
>       (find-symbol (symbol-name symbol) package)
>     (and status (eq symbol present-symbol))))

I hadn't realized that I mis-spelled it qutie that badly !

> Typing 'foobar makes a new such symbol.  READ creates symbols
> that you name which did not previously exist as interned, unexported
> symbols of the current package.

[and]

>  (unintern 'foo-bar)
>  (find-symbol "FOO-BAR")
>  => NIL, NIL
>  'foo-bar ;for side-effect of making the symbol again
>  => FOO-BAR
>  (find-symbol "FOO-BAR")
>  => FOO-BAR, :INTERNAL

So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
or are there further issues ?

> > >  (defmacro barify* (classes)
> > >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> > >       t))
> > 
> > Is there not an implicit progn ?
> 
> Well, that's an explicit progn.
> 
> The result of a macro is always a single form.  To return multiple
> forms, put them in a progn.

Don't think I follow . . .

(defmacro series-1 ()
  (print 'one) 
  (print "two"))

(defmacro series-2 ()
  (progn
    (print 'one)
    (print "two")))

(series-1) => "two"
(series-2) => "two"

Both have the same side-effects.


> I returned t here because it annoys me to see
> 
>  (def-foo a b c)
>  => c
> 
> It makes me worry it failed to process A and B.

That is what I inferred.

> > >  (defmacro barify (class &body class-options)
> > >    (setf class-options (copy-list class-options))
> > >    (let* ((class-option (assoc :class class-options))
> > >           (class-name
> > >             (or (second class-option)
> > >                 (intern (format nil "~a-BAR" class)))))
> > >      (when class-option 
> > >        (setq class-options (delete class-option class-options)))
> > >      `(defclass ,class-name ()
> > >         ,@class-options)))
> > 
> > (barify foo ((stuff))) -> (defclass foo-bar () ((stuff)))
> > (barify foo ((stuff) (:class 'quux))) - > (defclass quux () ((stuff)))
> > 
> > ?
> 
> Almost. &body gets all remaining arguments as a list, no need for extra
> parens around them.

Indeed, thanks. (I still get Lost In Superfluous Parentheses from time
to time :-)

>  (barify foo (:class quux))
>  (barify foo (stuff) (:class quux))
>  (barify foo (:metaclass my-metaclass) (:class quux))
> 
> The idea was to let you override the default class name if you
> needed to avoid some name conflict but wanted the same functionality.
> The idea is that ordinarily you wouldn't specify this, and it wouldn't
> take up any syntactic space.

Yup.

> I picked :class by analogy to the fact that you can already specify
> :metaclass.

Lost me here.

> By the way, there's a bug in my expansion.  You presumably want
>  `(defclass ,class-name (bar) 
>     ,@class-options)
> That is, you want to mix in the BAR class.  Otherwise it's not very
> barified.  That's what I get for not testing this code before sending
> it out. Sorry.

No problem, I spotted this and forgave you immediately.

Tanks,

Jacek
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwhewtq8ne.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
> or are there further issues ?

No!  When (read) is done and it returns (quote foobar), regardless of whether
an evaluation occurs, the symbol has been created.

> > > >  (defmacro barify* (classes)
> > > >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> > > >       t))
> > > 
> > > Is there not an implicit progn ?
> > 
> > Well, that's an explicit progn.
> > 
> > The result of a macro is always a single form.  To return multiple
> > forms, put them in a progn.
> 
> Don't think I follow . . .
> 
> (defmacro series-1 ()
>   (print 'one) 
>   (print "two"))

The above macro will print the symbol ONE, then the string "two", and
since PRINT returns its argument, any use of the macro will expand into
the string "two" (after doing those two calls to PRINT).

> (defmacro series-2 ()
>   (progn
>     (print 'one)
>     (print "two")))

The above macro will do the same thing.  Putting PROGN around the defmacro
does not change the effect.

> (series-1) => "two"
> (series-2) => "two"
> 
> Both have the same side-effects.

But what I did was different

 (defmacro series-3 ()
   `(progn (print 'one)
           (print "two")))

returns a single expression which is the PROGN.  No side-effect occurs at
macro expansion time.  At runtime, the single PROGN behaves like two 
statements, i.e., the two print statements, and both of those print statements
occur.

Here's what I had written:

> >  (defmacro barify* (classes)
> >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> >       t))

Back to your currrent post:

> > I returned t here because it annoys me to see
> > 
> >  (def-foo a b c)
> >  => c
> > 
> > It makes me worry it failed to process A and B.
> 
> That is what I inferred.
> Indeed, thanks. (I still get Lost In Superfluous Parentheses from time
> to time :-)

Don't ever add them if you don't know what they are for.
 
> >  (barify foo (:class quux))
> >  (barify foo (stuff) (:class quux))
> >  (barify foo (:metaclass my-metaclass) (:class quux))
> > 
> > The idea was to let you override the default class name if you
> > needed to avoid some name conflict but wanted the same functionality.
> > The idea is that ordinarily you wouldn't specify this, and it wouldn't
> > take up any syntactic space.
> 
> Yup.
> 
> > I picked :class by analogy to the fact that you can already specify
> > :metaclass.
> 
> Lost me here.

I could have chosen a keyword like :name or :class-name.
However, the BARIFY macro passes its other options through to DEFCLASS, so
I tried to pick a keyword that was consistent in style and meaning with
other DEFCLASS options.  Since DEFCLASS takes a :metaclass argument already,
and not a :metaclass-name, argument, for example, I assumed :class was the
right name for the class itself.
 
From: Jacek Generowicz
Subject: Re: Constructing symbols
Date: 
Message-ID: <g0hewsnbvd.fsf@scumbag.ecs.soton.ac.uk>
Kent M Pitman <······@world.std.com> writes:

> Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> 
> > So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
> > or are there further issues ?
> 
> No!  When (read) is done and it returns (quote foobar), regardless of whether
> an evaluation occurs, the symbol has been created.

Excuse my poor use of lisp-speak. What I meant was "typing 'foobar at
the prompt is equivalent to typing (intern "FOOBAR")", though I guess
there is plenty wrong with that, too.

Does the process you describe above create the symbol by a call to
intern ?  I guess I am not entirely sure what is meant by creating a
symbol.

> > Don't think I follow . . .
> > 
> > (defmacro series-1 ()
> >   (print 'one) 
> >   (print "two"))
> 
> The above macro will print the symbol ONE, then the string "two", and
> since PRINT returns its argument, any use of the macro will expand into
> the string "two" (after doing those two calls to PRINT).
> 
> > (defmacro series-2 ()
> >   (progn
> >     (print 'one)
> >     (print "two")))
> 
> The above macro will do the same thing.  Putting PROGN around the defmacro
> does not change the effect.
> 
> > (series-1) => "two"
> > (series-2) => "two"
> > 
> > Both have the same side-effects.
> 
> But what I did was different
> 
>  (defmacro series-3 ()
>    `(progn (print 'one)
>            (print "two")))
> 
> returns a single expression which is the PROGN.  No side-effect
> occurs at macro expansion time.  At runtime, the single PROGN
> behaves like two statements, i.e., the two print statements, and
> both of those print statements occur.

But the output will not differ between the 3 cases unless I compile
the code . . . and call the macro inside a loop ?

> Here's what I had written:
> 
> > >  (defmacro barify* (classes)
> > >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> > >       t))

So, (barify* (foo baz)) -> (progn (barify foo) (barify baz) t)
but omitting the progn would only give t [even though it would have
called (barify foo) (barify baz) at macroexpansion time] ?

Is there a way to see the form returned by a macroexpansion ? [There
is bound to be at least one lisp-speak solecism in that queston.]

I guess I should read the books again more carefully, instead of
polluting the NG, but it is good to get feedback to my naff ideas.

> Back to your currrent post:
> 
> > > I returned t here because it annoys me to see
> > > 
> > >  (def-foo a b c)
> > >  => c
> > > 
> > > It makes me worry it failed to process A and B.
> > 
> > That is what I inferred.
> > Indeed, thanks. (I still get Lost In Superfluous Parentheses from time
> > to time :-)
> 
> Don't ever add them if you don't know what they are for.

I had just temporarily forgotten that &body/&rest make a list of what
follows. I guess that this sort of thing will happen less and less as
I write more lisp.

> > > I picked :class by analogy to the fact that you can already specify
> > > :metaclass.
> > 
> > Lost me here.
> 
> the BARIFY macro passes its other options through to DEFCLASS,

Crystal clear now.

Thanks again,

Jacek
From: Duane Rettig
Subject: Re: Constructing symbols
Date: 
Message-ID: <4ae2k8tp1.fsf@beta.franz.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> > 
> > > So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
> > > or are there further issues ?
> > 
> > No!  When (read) is done and it returns (quote foobar), regardless of whether
> > an evaluation occurs, the symbol has been created.
> 
> Excuse my poor use of lisp-speak. What I meant was "typing 'foobar at
> the prompt is equivalent to typing (intern "FOOBAR")", though I guess
> there is plenty wrong with that, too.
> 
> Does the process you describe above create the symbol by a call to
> intern ?  I guess I am not entirely sure what is meant by creating a
> symbol.

I think you've just experienced a lisp-ism, where the lisp-y way is
to not only determine _what_ happens, but also _when_ it happens.
The answer to your question is that yes, intern is called in both
situations, but it is very important to distinguish when that call
is made.  At top-level, you are typing to a read-eval-print loop.
Each of these pieces of the loop is itself implemented in lisp.
Thus, any lisp functionality might be called at any one of the read,
eval, or print stages.  It is important to distinguish precisely when
an operation occurs, because it may be that you will get unexpected
results in other situations, such as when no reading is actually
being done.

Other "times" that lispers need to distinguish are compile-time,
macroexpand time (which occurs at either compile or eval time),
load time (at the loading of a file).  This is off the top of my
head, so others can probably think of other "times" that are
important.

Other languages don't care when things occur.  Lisp does.

In your examples, both eventually call intern.  However, the
explicit call calls intern at eval time, and the typing in
of the name occurs at read-time.  You will find that making
the distinction will help in later, more complex dealings with
lisp code (and figuring out why it doesn't work as expected).

-- 
Duane Rettig          Franz Inc.            http://www.franz.com/ (www)
1995 University Ave Suite 275  Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253   ·····@Franz.COM (internet)
From: Tim Bradshaw
Subject: Re: Constructing symbols
Date: 
Message-ID: <ey3u20r6y5p.fsf@cley.com>
* Duane Rettig wrote:
> Other "times" that lispers need to distinguish are compile-time,
> macroexpand time (which occurs at either compile or eval time),
> load time (at the loading of a file).  This is off the top of my
> head, so others can probably think of other "times" that are
> important.

I think this notion of times - times when arbitrary Lisp code can run
- is very important to understanding Lisp.  In a course I recently
gave I had a section on this.  From memory the times I had were:

    read time
    macroexpansion time
    compile time
    compiler-macroexpansion time
    load time
    run time

I missed print time, at least.

--tim
From: Duncan Harvey
Subject: Re: Constructing symbols
Date: 
Message-ID: <1ew4br3.gga90d127okgiN%spam@hubris2.demon.co.uk>
Tim Bradshaw <···@cley.com> wrote:

> I think this notion of times-  times when arbitrary Lisp code can run
> - is very important to understanding Lisp.  In a course I recently
> gave I had a section on this.  From memory the times I had were:
> 
>     read time
>     macroexpansion time
>     compile time
>     compiler-macroexpansion time
>     load time
>     run time

All good stuff.

> I missed print time, at least.

What happens then then?  (An 'output' stage?!  We don' need your
steenkin' batch processing! ;-)

Can you intercede/participate in the print step of the R-E-P-L?  OK,
sure your PRINT-OBJECT methods can be called.  But does this really
qualify as a separate Lisp 'time'?  Especially as printing can occur at
any, err, time.  (Really, as a new(ish)bie I would like to know.)

-- 
Duncan Harvey
"Smiling and waving. Before letting himself fall."
                       -- Anja Garbarek, The Diver
From: Tim Bradshaw
Subject: Re: Constructing symbols
Date: 
Message-ID: <ey34rsq73uq.fsf@cley.com>
* Duncan Harvey wrote:

> Can you intercede/participate in the print step of the R-E-P-L?  OK,
> sure your PRINT-OBJECT methods can be called.  But does this really
> qualify as a separate Lisp 'time'?  Especially as printing can occur at
> any, err, time.  (Really, as a new(ish)bie I would like to know.)

Well, you can intercede pretty thoroughly by the use of pprint
dispatch tables, but I'm not really sure if print-time is as
significant a time as the others.

--tim
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwelruaw1z.fsf@world.std.com>
····@hubris2.demon.co.uk (Duncan Harvey) writes:

> Tim Bradshaw <···@cley.com> wrote:
> 
> > I think this notion of times-  times when arbitrary Lisp code can run
> > - is very important to understanding Lisp.  In a course I recently
> > gave I had a section on this.  From memory the times I had were:
> > 
> >     read time
> >     macroexpansion time
> >     compile time
> >     compiler-macroexpansion time
> >     load time
> >     run time
> 
> All good stuff.

I've been advocating this use of "times" in language instruction for a lon
time.  A key to understanding the importance of dynamic languages is 
understanding that decisions are to be made at the earliest "time" where all
the information is available to make a correct decision.  Once you understand
this, you are armed to understand why static languages are often the wrong
thing--simply defining that the information IS available at compile time
doesn't mean it really is, and explains numerous bugs.  I think if this
were integrated into general language teaching, we'd have an easier time
marketing...
 
> > I missed print time, at least.
> 
> What happens then then?  (An 'output' stage?!  We don' need your
> steenkin' batch processing! ;-)

PRINT-OBJECT (and PPRINT) processing happens then.

It's something other languages (e.g., C) may not do.

 (defclass watch () ())

 (defmethod print-object ((watch watch) stream)
   (if (or *print-readably* *print-escape*)
       (print-unreadable-object (watch stream :type t :identity t)
         (prin1 (time-string watch) stream))
       (format t "You see a ~A.  As you look closer, you see it's ~A."
               (short-description watch) (time-string watch))))

 (defmethod short-description ((watch watch))
   (format nil "beautiful ~(~A~)" (class-name (class-of watch))))

 (defmethod time-string ((watch watch))
   (format nil "around ~D o'clock"
     (nth-value 2 (get-decoded-time))))

 (defclass wrist-watch (watch) ())
 (defclass pocket-watch (watch) ())


 (defvar *my-watch* (make-instance 'pocket-watch))

 (princ *my-watch*)
 You see a beautiful pocket-watch.  As you look closer, you see it's around 11 o'clock.
 #<POCKET-WATCH "around 11 o'clock" 20425664>
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfw8zi1l7lt.fsf@world.std.com>
Kent M Pitman <······@world.std.com> writes:

> ····@hubris2.demon.co.uk (Duncan Harvey) writes:
> 
> > Tim Bradshaw <···@cley.com> wrote:
> > 
> > > I think this notion of times-  times when arbitrary Lisp code can run
> > > - is very important to understanding Lisp.  In a course I recently
> > > gave I had a section on this.  From memory the times I had were:
> > > 
> > >     read time
> > >     macroexpansion time
> > >     compile time
> > >     compiler-macroexpansion time
> > >     load time
> > >     run time
> > 
> > All good stuff.
> 
> I've been advocating this use of "times" in language instruction for a lon
> time.  A key to understanding the importance of dynamic languages is 
> understanding that decisions are to be made at the earliest "time" where all
> the information is available to make a correct decision.  Once you understand
> this, you are armed to understand why static languages are often the wrong
> thing--simply defining that the information IS available at compile time
> doesn't mean it really is, and explains numerous bugs.  I think if this
> were integrated into general language teaching, we'd have an easier time
> marketing...

I got private email asking me to expand on this issue a little.  

The vector of "times" I specify often includes other elements like
"machine purchase time", "machine design time" (that's when the speed
of certain operations is optimized), operating system design and
purchase times, etc.

It's pretty easy for most people to see that binding the choice of
whether my start-menu should be in the top-right or bottom-left of
my window is too early to do at the time I decide on a Macintosh
label vs a PC.  

Hardware purchase time is a little early to decide I want software
from Microsoft, but that used to be an uncomfortably-coupled purchase.

Anyway, the point is that you sometimes get forced to make a decision
at a weird time that you're not really ready to.  Look at the set of
odd questions you have to ask when buying a PC.  "Will I be able to
connect a low-priced printer or scanner to this machine?"  What kind
of question is that?  Still, I had to go through that with my mom
buying a Mac.  She really wants a Mac, but I've advised her to finally
knuckle under and buy a PC because she just can't get the peripherals
she needs later for the Mac.  You'd THINK that this was something one
could delay decision-making on until the purchase time of the outboard
device, but not necessarily so.

Now for the same thing at the programming level...

In Lisp, you can just do
  (loop for i from 0 do (print i))
and you can let your program run for hours and the value of I will get
very big.  You didn't want to make a decision about how big at the time
you wrote the program.  Why should you?  How long you let the program
run should determine the maximum size, or what kind of data you feed it.
If you *want* to write a more restrictive program, you have that option
in Lisp.  But by default you write something general.

Programs don't compile in C if you don't type-declare things.  That means
you get the same choice as in Lisp EXCEPT that the "choice" is defined to
be answered  by "use fixnums".  There is realistically no other option.
So you're going to shoehorn your program, even if it is utterly general,
into a jacket that is overtight just because the language DEFINES that
this is so.  The trick is to get people to the point that they understand
that their concept is more general, and that only the language is what stands
between them and something more general.

People are used to thinking that since the machine has only arithmetic of
a certain size, that their choice is to use that or do nothing.  But it's
been a long time since we had to program in machine language, and there are
more options than to do things that just mirror the instruction set.  We can
build up abstractions that are bigger than that, and we should teach people
to want that.

Java is sort of the intermediate case since you *can* type-declare
everything object, but there is strong cultural and language bias
making it hard to do this.  The syntax of Integer is very cumbersome,
making you really, really, not want to build integers; you can tell by
the syntax of ints that you are supposed to be using them.

I hope that makes it more clear what I'm getting at.  If not, please
ask specific questions.

[Incidentally, there are some places in Lisp that are not as general as
they ought to be.  That all the pathname operations default to :case :local
rather than :case :common irks me, btw.  This is not a "precision" issue
in the traditional sense, but is similar--you're directly opting for 
non-portable programs and have to ask for portability.  Goes against the
design of the language, IMO.  And some string things default to narrow
strings, but at least there is a REALLY serious efficiency concern there.
Still, I'm caused to wonder if perhaps we shouldn't have done more like
we did for floats, with special variables that control the allocation 
dynamically by programs...  In spite of all this, though, at least we as
a community care about these issues.  More than you get in other languages.]

Lisp is a language that is about catering to what people want to say.
Other languages, like C, strike me as languages that want people to cater
to what they have to offer.  I'd rather people stress computers than computers
stress people.
From: Duncan Harvey
Subject: Re: Constructing symbols
Date: 
Message-ID: <1ew8ywg.1c0f5fa1t91v28N%spam@hubris2.demon.co.uk>
Kent M Pitman <······@world.std.com> wrote:

> PRINT-OBJECT (and PPRINT) processing happens then [print time].
> 
> It's something other languages (e.g., C) may not do.
> 
>  (defclass watch () ())
>  [..code for watches..] 
> 
>  (defvar *my-watch* (make-instance 'pocket-watch))
> 
>  (princ *my-watch*)
>  You see a beautiful pocket-watch.  As you look closer, you see it's
>  around 11 o'clock.
>  #<POCKET-WATCH "around 11 o'clock" 20425664>

 > (princ *my-watch*)
 You see a beautiful pocket-watch.  As you look closer, you see it's
 around 22 o'clock.
 #<POCKET-WATCH "around 22 o'clock" #xA10586>

:-)

I'm trying to get a handle on what delineates a 'time'.  If I, apologies
for the lame example, add:

  (defmethod wind-watch ((watch wrist-watch))
    (format t "You fumble with the recessed twisty thing."))

  (defmethod wind-watch ((watch pocket-watch))
    (format t "You wind up the ~A." (short-description watch)))

  > (wind-watch *my-watch*)
  You wind up the beautiful pocket-watch.
  NIL

Do we now have a 'winding time'?  If not, why not?  

The other times identified thus far (read, load, etc.) are different in
character from run time (e.g. program state has not yet been fully
established, you're performing program transformation not the
computation proper).  To me print time doesn't yet seem so.  What
information is available at print time that is not available at other
times?

OTOH, Lisp is a programmable programming language, so why shouldn't I
define my own times?  Hmmm.
-- 
Duncan Harvey
"Smiling and waving. Before letting himself fall."
                       -- Anja Garbarek, The Diver
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwpubb2dqf.fsf@world.std.com>
····@hubris2.demon.co.uk (Duncan Harvey) writes:

> Kent M Pitman <······@world.std.com> wrote:
> 
> > PRINT-OBJECT (and PPRINT) processing happens then [print time].
> > 
> > It's something other languages (e.g., C) may not do.
> > 
> >  (defclass watch () ())
> >  [..code for watches..] 
> > 
> >  (defvar *my-watch* (make-instance 'pocket-watch))
> > 
> >  (princ *my-watch*)
> >  You see a beautiful pocket-watch.  As you look closer, you see it's
> >  around 11 o'clock.
> >  #<POCKET-WATCH "around 11 o'clock" 20425664>
> 
>  > (princ *my-watch*)
>  You see a beautiful pocket-watch.  As you look closer, you see it's
>  around 22 o'clock.
>  #<POCKET-WATCH "around 22 o'clock" #xA10586>
> 
> :-)
> 
> I'm trying to get a handle on what delineates a 'time'.  If I, apologies
> for the lame example, add:
> 
>   (defmethod wind-watch ((watch wrist-watch))
>     (format t "You fumble with the recessed twisty thing."))
> 
>   (defmethod wind-watch ((watch pocket-watch))
>     (format t "You wind up the ~A." (short-description watch)))
> 
>   > (wind-watch *my-watch*)
>   You wind up the beautiful pocket-watch.
>   NIL
> 
> Do we now have a 'winding time'?  If not, why not?  

There's one "time" for every instant of forever.

However, for programming, the materially interesting ones are the ones that
occur with "added information" having occurred in the interim, such that
pre-computing a response would yield a less-good answer than computing
at the moment.

I would say "wind-watch time" isn't interesting in this realm because
information isn't injected.  I'd say "set-watch time" is, perhaps, interesting.

> The other times identified thus far (read, load, etc.) are different in
> character from run time (e.g. program state has not yet been fully
> established, you're performing program transformation not the
> computation proper).  To me print time doesn't yet seem so.  What
> information is available at print time that is not available at other
> times?

The information that makes the correctly printed time occur.  It can't
be cached.
 
> OTOH, Lisp is a programmable programming language, so why shouldn't I
> define my own times?  Hmmm.

Exactly.

This is a subjective issue.  The critical thing is to resist computing
information at the wrong time, not to enumerate all the right times.
Lisp allows you to extend the set of times; other languages encourage
you to restrict the set.  It's the pressure left or the pressure right
that is the real issue.
From: Tim Bradshaw
Subject: Re: Constructing symbols
Date: 
Message-ID: <ey37kxjdntr.fsf@cley.com>
* Duncan Harvey wrote:

> The other times identified thus far (read, load, etc.) are different in
> character from run time (e.g. program state has not yet been fully
> established, you're performing program transformation not the
> computation proper).  To me print time doesn't yet seem so.  What
> information is available at print time that is not available at other
> times?

Although I think the notion of a `time' that Kent is getting at is
broader, the notion I was after was fairly narrow, and something like
this: 

    A `time' (in my sense) is a time during the construction or
    running of a program where user-defined code gets to run in the
    process of some action by the system.

This is obviously pretty vague.  But something like read-time
obviously fits this definition.  So does macro-expansion time.  And
so, I think does print time. Other things that might qualify are
class-redefinition time for instance, and probably instance
initialization time &c.

Obviously this definition is really no good - who gets to define what
`the system' is for instance?  However the reason I think that this
definition is useful is that it helps people understand the various
interesting points at which you can intervene in the construction and
running of a Lisp program which are not available to you in most other
languages.  The various macro-expansion times are perhaps the most
ovious examples, but things like print time are also good examples -
if only because few other languages define a print protocol in Lisp's
sense, let alone allow user intervention in that protocol.

--tim
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwg0ccv66t.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> > 
> > > So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
> > > or are there further issues ?
> > 
> > No!  When (read) is done and it returns (quote foobar), regardless
> > of whether an evaluation occurs, the symbol has been created.
> 
> Excuse my poor use of lisp-speak. What I meant was "typing 'foobar
> at the prompt is equivalent to typing (intern "FOOBAR")", though I
> guess there is plenty wrong with that, too.

I'm not trying to correct your speech because I'm pedantic.  Learning all
the terms is part and parcel of learning all the actions that happen.  When
youd describe things right, you'll understand it better.  If you are blurry,
you'll miss important details.  I'm not fussy about how people say it when
I know they understand, but it's a teaching tactic that I'm pushy about
wording while people learn.  Don't feel bad.  And don't mind the "!" in there;
just trying to keep you awake.
 
> Does the process you describe above create the symbol by a call to
> intern ?  I guess I am not entirely sure what is meant by creating a
> symbol.

Yes.  The reader scans a token, decides whether it's a number or a symbol.
If it's a symbol, it finds the package marker, if any, and separates that.
Then it interns the symbol.  This process is carefully described in the 
syntax documentation in the Common Lisp HyperSpec.  It's even kind of
readable and perhaps worth your taking a peek at.
 
> > > Don't think I follow . . .
> > > 
> > > (defmacro series-1 ()
> > >   (print 'one) 
> > >   (print "two"))
> > 
> > The above macro will print the symbol ONE, then the string "two", and
> > since PRINT returns its argument, any use of the macro will expand into
> > the string "two" (after doing those two calls to PRINT).
> > 
> > > (defmacro series-2 ()
> > >   (progn
> > >     (print 'one)
> > >     (print "two")))
> > 
> > The above macro will do the same thing.  Putting PROGN around the defmacro
> > does not change the effect.
> > 
> > > (series-1) => "two"
> > > (series-2) => "two"
> > > 
> > > Both have the same side-effects.
> > 
> > But what I did was different
> > 
> >  (defmacro series-3 ()
> >    `(progn (print 'one)
> >            (print "two")))
> > 
> > returns a single expression which is the PROGN.  No side-effect
> > occurs at macro expansion time.  At runtime, the single PROGN
> > behaves like two statements, i.e., the two print statements, and
> > both of those print statements occur.
> 
> But the output will not differ between the 3 cases unless I compile
> the code . . . and call the macro inside a loop ?

Hmmm.

You should not think of compilation as the interesting question.  All code
has a syntactic-processing step, whether compiled or not.  In an interactive
mode, that step is blurred together with execution, but the processes are
distinct.  You are sharing the same console for the syntactic-expansion as
for the execution interactively, so you may think it has the same output,
but conceptually in the unquoted case, the "macroexpansion time" is very
different than the runtime.  For example, it can happen that even an 
interpreter will make a pre-pass to expand all the macros, so if you
do:

 (progn (print (series-1)) (print (series-2)))

you'll see

 ONE
 "two"
 ONE
 "two"  ;syntactic pre-processing ends here
 "two"
 "two"

or it can happen that it does the syntactic-preprocessing lazily and you'll
see:

 ONE    ;expansion time of the first macro
 "two"  ;ditto
 "two"  ;execution of first macro
 ONE    ;expansion second macro
 "two"  ;ditto
 "two"  ;execution of second macro

and probably in a loop you'll not get multiple re-processing of a macro.
in old lisp, you could have. i'm not sure if we removed that for modern
cl.

by contrast, the printing in my series-3 will always have

  (print (series-3))

show

 ONE
 "two"
 "two"

because the expansion defers all output.  

In general, a macro should not do output except to print a warning.
And then it should only call WARN or do output to *ERROR-OUTPUT*.

> > Here's what I had written:
> > 
> > > >  (defmacro barify* (classes)
> > > >    `(progn ,@(mapcar #'(lambda (class) `(barify ,class)) classes)
> > > >       t))
> 
> So, (barify* (foo baz)) -> (progn (barify foo) (barify baz) t)
> but omitting the progn would only give t [even though it would have
> called (barify foo) (barify baz) at macroexpansion time] ?
> 
> Is there a way to see the form returned by a macroexpansion ? [There
> is bound to be at least one lisp-speak solecism in that queston.]

(pprint (macroexpand-1 '(barify foo)))

Macros are iteratively expanded until they become non-macros.  See 
CLHS for the description of MACROEXPAND vs MACROEXPAND-1.

> I guess I should read the books again more carefully, instead of
> polluting the NG, but it is good to get feedback to my naff ideas.

Yes, but that's ok.  People here don't mind answering as long as the people
they are answering for are really reading and really trying to do some work
between asking the questions, as you obviously are.
 
> > Back to your currrent post:
> > 
> > > > I returned t here because it annoys me to see
> > > > 
> > > >  (def-foo a b c)
> > > >  => c
> > > > 
> > > > It makes me worry it failed to process A and B.
> > > 
> > > That is what I inferred.
> > > Indeed, thanks. (I still get Lost In Superfluous Parentheses from time
> > > to time :-)
> > 
> > Don't ever add them if you don't know what they are for.
> 
> I had just temporarily forgotten that &body/&rest make a list of what
> follows. I guess that this sort of thing will happen less and less as
> I write more lisp.

That's the hope.
 
> > > > I picked :class by analogy to the fact that you can already specify
> > > > :metaclass.
> > > 
> > > Lost me here.
> > 
> > the BARIFY macro passes its other options through to DEFCLASS,
> 
> Crystal clear now.

Great.
From: Jacek Generowicz
Subject: Re: Constructing symbols
Date: 
Message-ID: <g07kxnrdrb.fsf@scumbag.ecs.soton.ac.uk>
Kent M Pitman <······@world.std.com> writes:

> Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> 
> > Kent M Pitman <······@world.std.com> writes:
> > 
> > > Jacek Generowicz <···@ecs.soton.ac.uk> writes:
> > > 
> > > > So evaluating 'foobar is equivalent to evaluating (intern "FOOBAR") ?
> > > > or are there further issues ?
> > > 
> > > No!  When (read) is done and it returns (quote foobar), regardless
> > > of whether an evaluation occurs, the symbol has been created.
> > 
> > Excuse my poor use of lisp-speak. What I meant was "typing 'foobar
> > at the prompt is equivalent to typing (intern "FOOBAR")", though I
> > guess there is plenty wrong with that, too.
> 
> I'm not trying to correct your speech because I'm pedantic.

I'm sorry, I didn't mean to imply that at all.

> Learning all the terms is part and parcel of learning all the
> actions that happen.  When youd describe things right, you'll
> understand it better.  If you are blurry, you'll miss important
> details.  I'm not fussy about how people say it when I know they
> understand, but it's a teaching tactic that I'm pushy about wording
> while people learn.

Couldn't agree more. I want to be corrected. I just feel a bit
self-conscious about writing nonsense, and apologize for it.

> Don't feel bad.  And don't mind the "!" in there; just trying to
> keep you awake.

Thanks - it's healthier than coffee :-)

> > Does the process you describe above create the symbol by a call to
> > intern ?  I guess I am not entirely sure what is meant by creating a
> > symbol.

From what I read last night somewhere (On Lisp ?) I inferred that
`creating a symbol' is pretty much a synonym for intern. (Correction
welcome). It also implied (and so have you) that any symbol I ever
type (into the R-E-P loop) is interned; so as I play around, I am
filling the package with (useless) symbols. I guess that there's no
problem with that, but it surprised me a little.

> Yes.  The reader scans a token, decides whether it's a number or a symbol.
> If it's a symbol, it finds the package marker, if any, and separates that.
> Then it interns the symbol.

> This process is carefully described in the 
> syntax documentation in the Common Lisp HyperSpec.  It's even kind of
> readable

Kind of :-)

No, it looks quite good, but with my level of knowledge it is too
tempting to follow too many hyperlinks, and get absolutely nowhere.

I guess I will have to keep coming back to it, and make slow progress.

Your 3 line summary above certainly helps to focus on the big picture,
though.

> > > > (defmacro series-1 ()
> > > >   (print 'one) 
> > > >   (print "two"))

> > > > (defmacro series-2 ()
> > > >   (progn
> > > >     (print 'one)
> > > >     (print "two")))

> > >  (defmacro series-3 ()
> > >    `(progn (print 'one)
> > >            (print "two")))

> You should not think of compilation as the interesting question.  All code
> has a syntactic-processing step, whether compiled or not.  In an interactive
> mode, that step is blurred together with execution, but the processes are
> distinct.  You are sharing the same console for the syntactic-expansion as
> for the execution interactively, so you may think it has the same output,
> but conceptually in the unquoted case, the "macroexpansion time" is very
> different than the runtime.  For example, it can happen that even an 
> interpreter will make a pre-pass to expand all the macros, so if you
> do:
> 
>  (progn (print (series-1)) (print (series-2)))
> 
> you'll see
> 
>  ONE
>  "two"
>  ONE
>  "two"  ;syntactic pre-processing ends here
>  "two"
>  "two"
> 
> or it can happen that it does the syntactic-preprocessing lazily and you'll
> see:
> 
>  ONE    ;expansion time of the first macro
>  "two"  ;ditto
>  "two"  ;execution of first macro
>  ONE    ;expansion second macro
>  "two"  ;ditto
>  "two"  ;execution of second macro
> 
> and probably in a loop you'll not get multiple re-processing of a macro.
> in old lisp, you could have. i'm not sure if we removed that for modern
> cl.
> 
> by contrast, the printing in my series-3 will always have
> 
>   (print (series-3))
> 
> show
> 
>  ONE
>  "two"
>  "two"
> 
> because the expansion defers all output.  
> 
> In general, a macro should not do output except to print a warning.
> And then it should only call WARN or do output to *ERROR-OUTPUT*.

A helpful discussion, thanks.

> > Is there a way to see the form returned by a macroexpansion ? [There
> > is bound to be at least one lisp-speak solecism in that queston.]
> 
> (pprint (macroexpand-1 '(barify foo)))

Aaaaaaaaaargh !  THE QUOTE !  I've been trying this so many times
without the quote. Even now it took me while to spot what was going
wrong. Let's hope this teaches me a good lesson.

> > I guess I should read the books again more carefully, instead of
> > polluting the NG, but it is good to get feedback to my naff ideas.
> 
> Yes, but that's ok.  People here don't mind answering as long as the people
> they are answering for are really reading and really trying to do some work
> between asking the questions, as you obviously are.

I just wish I had more time to spend on it. Thank you for YOUR time.

Hmm . . . I've just inadvertently created the macro nil. Does this
have any interesting consequences I should know about ?
From: Kent M Pitman
Subject: Re: Constructing symbols
Date: 
Message-ID: <sfwelrv4nu9.fsf@world.std.com>
Jacek Generowicz <···@ecs.soton.ac.uk> writes:

> From what I read last night somewhere (On Lisp ?) I inferred that
> `creating a symbol' is pretty much a synonym for intern. (Correction
> welcome).

Well, strictly, creating a symbol is done by MAKE-SYMBOL.
It constructs a datastructure of appropriate type and name.

Creating an *interned* symbol is done by INTERN.  Approximately,
INTERN might better be called FIND-OR-MAKE-SYMBOL-IN-PACKAGE where
package defaults to the current package.  Interns job is to protect the
illusion that all symbols exist already.  They actually come into creation
when you name them, but unless you use an introspective tool like
FIND-SYMBOL, you really can't tell if the symbol was there before or not.
If INTERN finds a symbol, it means someone previously made the symbol
and arranged it to be present in the current package, and it uses that.
If it doesn't find the symbol, it creates it and gives it a home package
of the current package and makes the symbol a local of the current package.

> It also implied (and so have you) that any symbol I ever
> type (into the R-E-P loop) is interned;

Yes, that' what I meant about giving you the illusion they were always
there.

> so as I play around, I am
> filling the package with (useless) symbols.

Yes, though the GC can remove them if there are no pointers to them.
Don't spend any time worrying about this unless you are image-building
an application for delivery.

> I guess that there's no
> problem with that, but it surprised me a little.

That's natural.

> > > Is there a way to see the form returned by a macroexpansion ? [There
> > > is bound to be at least one lisp-speak solecism in that queston.]
> > 
> > (pprint (macroexpand-1 '(barify foo)))
> 
> Aaaaaaaaaargh !  THE QUOTE !  I've been trying this so many times
> without the quote. Even now it took me while to spot what was going
> wrong. Let's hope this teaches me a good lesson.

Soon it will be second nature.  But it takes some training.
People are naturally used to the concept of quotation from English, but
they are not used to rigorously notating it.  (Actually, there are myriad
inflected notations verbally, and as many typesetting conventions for
quoting textually...)
 
> > > I guess I should read the books again more carefully, instead of
> > > polluting the NG, but it is good to get feedback to my naff ideas.
> > 
> > Yes, but that's ok.  People here don't mind answering as long as the people
> > they are answering for are really reading and really trying to do some work
> > between asking the questions, as you obviously are.
> 
> I just wish I had more time to spend on it. Thank you for YOUR time.
> 
> Hmm . . . I've just inadvertently created the macro nil. Does this
> have any interesting consequences I should know about ?

it means you've violated the standard. You're not suposed to make macro
or function or variable or ... definitions for any of the 978 names in
the CL package.  Some implementations won't let you try.  But on the 
other hand, no meaning is assigned to any operator named NIL, so no 
problem is likely to occur  unless you load the code of someone else who
also gave NIL a function or macro definition, since they will clobber yours,
presumably incompatibly, and only one of yours will be available.