From: Georg Westenberger
Subject: [newbie] lambda?
Date: 
Message-ID: <379C70AA.9743DD5@gmx.de>
Hi there!

I'm quite new to Lisp. I'm currently playing around with
different Lisp and Scheme interpreters and noticed something
odd. The following was a session in XLISP-Plus 2.1g.

> ((lambda (x) (+ 3 x)) 5)            
8                                     
> (setq fnc (lambda (x) (+ 3 x)))     
#<Closure: #de7a686>                  
> (fnc 4)                             
error: unbound function - FNC         <----- Why???
> (apply fnc '(5))                    
8

Why can't I apply fnc directly? I know how to use defun,
but shouldn't this above work, too?
However, this is no problem in Scheme, because it's the
normal way to define functions in Scheme.

Thanks in advance.
Georg

From: Fernando Mato Mira
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <379C8899.11EA9086@iname.com>
Georg Westenberger wrote:

> Hi there!
>
> I'm quite new to Lisp. I'm currently playing around with
> different Lisp and Scheme interpreters and noticed something
> odd. The following was a session in XLISP-Plus 2.1g.
>
> > ((lambda (x) (+ 3 x)) 5)
> 8
> > (setq fnc (lambda (x) (+ 3 x)))
> #<Closure: #de7a686>
> > (fnc 4)
> error: unbound function - FNC         <----- Why???
> > (apply fnc '(5))
> 8
>
> Why can't I apply fnc directly? I know how to use defun,
> but shouldn't this above work, too?
> However, this is no problem in Scheme, because it's the
> normal way to define functions in Scheme.

Scheme is a Lisp-1 (one namespace for everything),
CL is a Lisp-N with N > 1
[do class names qualify it as N > 2]?

1: variable bindings
2: function bindings

So, in CL you'll have to do:

(funcall fnc 4)

The expression in the CAR of an application is not evaluated, but
searched in operator space,
so the same happens elsewhere:

Scheme: ((lambda (x) x) 1)

CL: (funcall (lambda (x) x) 1)


Yes, you're allowed to think that's ugly :->
From: Rainer Joswig
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <joswig-2607991818060001@194.163.195.67>
In article <·················@iname.com>, Fernando Mato Mira <········@iname.com> wrote:

> Scheme: ((lambda (x) x) 1)
> 
> CL: (funcall (lambda (x) x) 1)
> 
> 
> Yes, you're allowed to think that's ugly :->

MCL:

? ((lambda (x) x) 1)
1
From: Daniel Barlow
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <87yag36z7q.fsf@tninkpad.telent.net>
······@lavielle.com (Rainer Joswig) writes:

> In article <·················@iname.com>, 
        Fernando Mato Mira <········@iname.com> wrote:
> > Scheme: ((lambda (x) x) 1)
> > CL: (funcall (lambda (x) x) 1)
> MCL:
> 
> ? ((lambda (x) x) 1)
> 1

CLHS:
http://www.harlequin.com/education/books/HyperSpec/Body/sym_lambda.html

I'm pretty sure this was mentioned in this very newsgroup a few months
ago, but don't remember enough to try looking in dejanews

-dan
From: Kent M Pitman
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <sfwso6bi4uz.fsf@world.std.com>
Daniel Barlow <···@tninkpad.telent.net> writes:

> ······@lavielle.com (Rainer Joswig) writes:
> 
> > In article <·················@iname.com>, 
>         Fernando Mato Mira <········@iname.com> wrote:
> > > Scheme: ((lambda (x) x) 1)
> > > CL: (funcall (lambda (x) x) 1)
> > MCL:
> > 
> > ? ((lambda (x) x) 1)
> > 1
> 
> CLHS:
> http://www.harlequin.com/education/books/HyperSpec/Body/sym_lambda.html
> 
> I'm pretty sure this was mentioned in this very newsgroup a few months
> ago, but don't remember enough to try looking in dejanews


CL permits any of the syntaxes

     a. ((lambda (x) x) 1)
 OR
     b. (funcall (lambda (x) x) 1)
 OR
     c. (funcall (function (lambda (x) x)) 1)
 OR 
     d. (funcall #'(lambda (x) x) 1)

d is just readmacro shorthand for c.
b invokes a macro named LAMBDA which after expansion leaves c.
a is fundamentally different native syntax handled by special exception.

Notation B was added specifically for Scheme compatibility.

In general, (lambda ...) is done mostly compatibly with Scheme, except
that the dotted notation for rest lists is not done.  You have to write
(lambda (x &rest y) ...) not (lambda (x . y) ...).

Where CL differs from Scheme is in the use of *named* functions.

  (f f)             ;call funbinding[F] on varbinding[F].
  (funcall f f)     ;call varbinding[F] on varbinding[F].
  (f #'f)           ;call funbinding[F] on funbinding[F].
  (funcall f #'f)   ;call varbinding[F] on funbinding[F].

  (funcall #'f #'f) ;call funbinding[F] on funbinding[F]. [same as (f #'f)]
  (funcall #'f f)   ;call funbinding[F] on varbinding[F]. [same as (f f)]

Scheme has only one namespace (for variables and functions together).
Lisp has several namespaces (one for variables, one for functions, and
some other less visible ones for things like block names and tagbodies).

Lisps are partitioned, by definition, into families subscripted by the number
of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL
is often called a Lisp2 (since it has separated functions and values) but
is really some number higher than that (at least 4; I never made a thorough
check to see if there were any other namespaces; if someone knows others
besides blocks and go-tags, do mention them).

You have to be clear about when you mean one thing and when you mean
another.  For example, in Scheme:

 ((lambda (list) (list list list)) cons) 
 => (#<function cons> . #<function cons>)

In CL
 ((lambda (list) (list list list)) #'cons)
 => (#<function cons> #<function cons>)
 
This is because CL also allows you to say (all without changing
the variable name):

 ((lambda (list) (funcall list list list)) #'cons)
 => (#<function cons> . #<function cons>)

 ((lambda (list) (funcall list #'list #'list)) #'cons)
 => (#<function list> . #<function list>)

 ((lambda (list) (list #'list #'list)) #'cons)
 => (#<function list> #<function list>)

In Scheme, you have to do things like

 ((lambda (lst) (list lst lst)) cons)
 ((lambda (lst) (lst list list)) cons)
 etc.

to get these same effects.

A lot of what drives the decision to have used the different notation
in CL has to do with how often you expect to see functional arguments
and how strongly you want their use to be case-marked.  Functions  are
not passed as much as args in CL as in Scheme; we use keywords for much
of what Scheme uses functions for.  Not all, but much.  As a consequence,
CL users are used to seeing functions really mean what they think they
mean and only variables suddenly "mean something surprising".  In Scheme,
the fact that a choice of variable name can affect the meaning of your
whole program is commonplace, and people are used to looking for it.
But it would be unsettling to a CL programmer.
From: Fernando Mato Mira
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <379D82A2.94AFD6EF@iname.com>
Kent M Pitman wrote:

> In general, (lambda ...) is done mostly compatibly with Scheme, except
> that the dotted notation for rest lists is not done.  You have to write
> (lambda (x &rest y) ...) not (lambda (x . y) ...).

Talking about LET et al, have you taken a look at:

http://srfi.schemers.org/srfi-5/
From: William Deakin
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <379EF626.9F0C7221@pindar.com>
Kent M Pitman wrote:

> Lisps are partitioned, by definition, into families subscripted by the number
> of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL is
> often called a Lisp2 (since it has separated functions and values) but is
> really some number higher than that (at least 4; I never made a thorough
> check to see if there were any other namespaces; if someone knows others
> besides blocks and go-tags, do mention them).

In the section cunningly entitled 'The Seven Name Spaces', Norvig [1] states that
in CL there are the following seven namespaces:

1) functions and macros;
2) lexical variables;
3) special variables;
4) data types;
5) labels for go statements;
6) block names for return-from statments;
7) symbols inside quoted expression. eg. the tag name space used by catch throw.

As to whether this is a complete list I am unable to say,I

:-) will

[1] 'Paradigms of Artificial Intelligence Programming: Case Studies in Common
Lisp', second printing pp. 836-7.
From: Kent M Pitman
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <sfw7lnku5ba.fsf@world.std.com>
William Deakin <·····@pindar.com> writes:

> In the section cunningly entitled 'The Seven Name Spaces', Norvig [1] states that
> in CL there are the following seven namespaces:
> 
> 1) functions and macros;
> 2) lexical variables;
> 3) special variables;
> 4) data types;
> 5) labels for go statements;
> 6) block names for return-from statments;
> 7) symbols inside quoted expression. eg. the tag name space used by catch throw.
> 
> As to whether this is a complete list I am unable to say,I

Thanks.  I guess some of these I wasn't counting as namespaces in the
way I was using.  But shame on me for using the word namespace without
more qualification.  I'll now need to invent a term like "lexical namespace"
to refer to what I really mean.  Only 1, 2, 5, and 6 from the above
count as namespace in the sense I was thinking.  3 is more of a parasite
on the lexical namespace; I've actually thought for a long time [I don't
think I made it up, I think I got it from someone but can't remember
whom--maybe Jonathan Rees] that the proper way to think of specials
is as data object references syntactically projected into the language
syntax as a kind of shorthand.   That is, that x normally means a lexical
variable access, but that in a sense, x could, by abuse of notation,
mean something else more like a refernce to a data structure.  In CL,
this can be expressed formally by something like:

  (symbol-macrolet ((x (binding-ref (load-time-value (special-binding 'x)))))
    ...)

so that when you see "x" you really see (binding-ref #<binding X>),
and so that specials could be added without cooperation of the language;
since I think this kind of namespace is primitive to the language, this shows
it's not a namespace like I intended.

Back to your list, 4 and 7 do not get closed over, so isn't what I 
was looking for.

Peter is right, though, that these are all namespaces in a more general
use of the term.  But to the extent that that's so, then Scheme certainly
has at least 2 and 7...  So if you adopted his meaning of namespace,
Lisp would be a Lisp7 but Scheme would be a Lisp2.  I'm sure they'd
find that very disquieting.

(Btw, I invented the terms "Lisp1" and "Lisp2" for a paper Gabriel and I
wrote trying to articulate the issues on this topic.  My attempts to say
what are and are not meant by these namespaces is indrectly an attempt
to clarify the original meanings I had meant for these terms when we wrote
the paper.  I'll try to get that paper online at some point.  It's in 
Vol 1, No. 1 of LASC (lisp and Symbolic Computation), though, if anyone
has that around and is curious.)
From: William Deakin
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <37A0082E.BFB8DE76@pindar.com>
Kent M Pitman wrote:

> So if you adopted his meaning of namespace, Lisp would be a Lisp7 but Scheme would be
> a Lisp2.  I'm sure they'd find that very disquieting.

IMHO Lisp7 and Lisp2 are more aesthetically pleasing. But I am not able to add anything
further.

> I'll try to get that paper online at some point.  It's in Vol 1, No. 1 of LASC (lisp
> and Symbolic Computation), though, if anyone has that around and is curious.

As I don't have easy access to LASC I would be interested in reading the article
online.

Best Regards,

-- will

This ones for me: 'Whereof one does not know thereof one should not speak' --- L.
Wittgenstein ;-)
From: Pekka P. Pirinen
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <ix6734k5a0.fsf@gaspode.cam.harlequin.co.uk>
William Deakin <·····@pindar.com> writes:
> In the section cunningly entitled 'The Seven Name Spaces', Norvig
> [1] states that in CL there are the following seven namespaces:
> 
> 1) functions and macros;
> 2) lexical variables;
> 3) special variables;
> 4) data types;
> 5) labels for go statements;
> 6) block names for return-from statments;
> 7) symbols inside quoted expression. eg. the tag name space used by
> catch throw.
>
> As to whether this is a complete list I am unable to say,

Having worked this out for the LispWorks dspec system, I can add a few
things.

There's a structure namespace separate from the type namespace (4).
DEFSTRUCT declares a name in both of them, unless the :TYPE option is
used, in which case no type name is declared.  The only place where
names in the structure namespace can be referred to is the :INCLUDE
option of DEFSTRUCT.

I think number 7 is a bit bogus.  While symbols do form namespaces in
a technical sense (each package a separate namespace, as Kent pointed
out in another message), they hold the priviledged position of being
the names (or at least the main constituent thereof) in all the other
namespaces.  (At least let's not claim catch tags are symbols -- they
can in fact be any Lisp objects, which allows for some interesting
programming tricks.)

setf methods (DEFINE-SETF-EXPANDER) and compiler macros have their own
namespaces: While it doesn't make much sense to have one, if there's
no function of the same name, they are technically independent.

Methods should be considered to be yet another space (while implying
the existence of the gf), named by the name of the gf plus the
signature.  And it's easy to forget method combinations.

Additionally, programmers often introduce new defining forms, with
associated namespaces.  Examples in common use include DEFSYSTEM and
CLIM:DEFINE-PRESENTATION-TYPE.  A vanilla LW (no CLIM) uses nine
non-standard namespaces at last count.

In summary:

 7) structures;
 8) setf methods;
 9) compiler macros;
 10) methods;
 11) method combinations;
 *) and any number of user-defined namespaces.

If you wish, add the package namespace and each package.
-- 
Pekka P. Pirinen
Adaptive Memory Management Team, (the new) Harlequin Limited
This article printed on 100% recycled electrons.
From: Vassil Nikolov
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <l03130300b3c5267520dc@195.138.129.105>
Kent M Pitman wrote:                [1999-07-28 16:06 +0000]

  [...]
  > I've actually thought for a long time [I don't
  > think I made it up, I think I got it from someone but can't remember
  > whom--maybe Jonathan Rees] that the proper way to think of specials
  > is as data object references syntactically projected into the language
  > syntax as a kind of shorthand.   That is, that x normally means a lexical
  > variable access, but that in a sense, x could, by abuse of notation,
  > mean something else more like a refernce to a data structure.  In CL,
  > this can be expressed formally by something like:
  > 
  >   (symbol-macrolet ((x (binding-ref (load-time-value (special-binding 'x)))))
  >     ...)
  > 
  > so that when you see "x" you really see (binding-ref #<binding X>),

Would

  (symbol-macrolet ((*x* (symbol-value '*x*)))
    ...)

also do?

  > and so that specials could be added without cooperation of the language;
  > since I think this kind of namespace is primitive to the language, this shows
  > it's not a namespace like I intended.
  [...]

Thanks for the explanations on namespace in these posts.



Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.
From: Kent M Pitman
Subject: Re: [newbie] lambda? The seven pillars of Lisp
Date: 
Message-ID: <sfwu2qogg7j.fsf@world.std.com>
Vassil Nikolov <········@poboxes.com> writes:

> Would
> 
>   (symbol-macrolet ((*x* (symbol-value '*x*)))
>     ...)
> 
> also do?

Yeah, it's just that symbols mean so many things that this would have been
presentationally confusing to say, only becuase *x* is a dynamic variable
already and I'm trying to describe a metacircular implementation.  I agree
this is truly not a violation of the metacircularity thing, but it would 
risk someone not following carefully not realizing what was going on.  So
I tried to make it look more different; for example, a way that it would
make sense in Scheme, which has no symbol-value.
From: Vassil Nikolov
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <l03130305b3c26ee5d32b@195.138.129.100>
Kent M Pitman wrote:                [1999-07-26 19:32 +0000]

  [...]
  > Lisps are partitioned, by definition, into families subscripted by the number
  > of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL
  > is often called a Lisp2 (since it has separated functions and values) but
  > is really some number higher than that (at least 4; I never made a thorough
  > check to see if there were any other namespaces; if someone knows others
  > besides blocks and go-tags, do mention them).
  [...]

(1) About Scheme which I don't know that well.  Does Scheme have block
names?  (I don't expect it to have go tags.)  Would the name of a named let
shadow a function with the same name?

(2) About namespaces.  Would type/class names count as another namespace?
Compiler macros?


Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.
From: Pierre R. Mai
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <87oggzgkom.fsf@orion.dent.isdn.cs.tu-berlin.de>
Vassil Nikolov <········@poboxes.com> writes:

> (1) About Scheme which I don't know that well.  Does Scheme have block
> names?  (I don't expect it to have go tags.)  Would the name of a named let
> shadow a function with the same name?

The name of a named let will shadow function and variable names, as
usual.

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
From: Kent M Pitman
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <sfwg12bnhzq.fsf@world.std.com>
Vassil Nikolov <········@poboxes.com> writes:

> Kent M Pitman wrote:                [1999-07-26 19:32 +0000]
> 
>   [...]
>   > Lisps are partitioned, by definition, into families subscripted by the number
>   > of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL
>   > is often called a Lisp2 (since it has separated functions and values) but
>   > is really some number higher than that (at least 4; I never made a thorough
>   > check to see if there were any other namespaces; if someone knows others
>   > besides blocks and go-tags, do mention them).
>   [...]
> 
> (1) About Scheme which I don't know that well.  Does Scheme have block
> names?  (I don't expect it to have go tags.)  Would the name of a named let
> shadow a function with the same name?

The right way for a CL programmer to understand it is to use the very old
Scheme of CATCH/THROW, wherein
 (CATCH FOO ...)
executes the "..." in a context where FOO is bound to a function which will
throw out of the catch.  So you might define
 (DEFINE (THROW TAG VALUE) (TAG VALUE)) ;Scheme-style
or
 (DEFUN THROW (TAG VALUE) (FUNCALL TAG VAGLUE)) ;CL-style
if you want the THROW part to be more apparent.  And you'd do
 (THROW FOO ...)
to do the throw, not (THROW 'FOO ...) since it would be a lexical binding.

In fact, Scheme casts THROW in the modern world as 
CALL-WITH-CURRENT-CONTINUATION so it looks more like
 (CALL-WITH-CURRENT-CONTINUATION 
  (LAMBDA (FOO) 
    ...))
but it just means the same as that CATCH I wrote above.

The Scheme community has eschewed macro syntax, for the most part, 
for reasons that seem to me miguided (albeit principled).
Nothing wrong with offering CALL-WITH-CURRENT-CONTINUATION as a
subprimitive, but the drive to not also include THROW is an excess
zeal for the ultra-tiny spec that I think impedes concise programs.
And there are many more programs than specs, so I wish they'd focus
more on short programs than on short specs.

All in all, for though it is longer than the Scheme spec, I think
the CL spec does a fairly good job of making concise and perspicuous
programs.  Often better than the equivalent in Scheme, whose generality
often hides its application/focus to specific situations.

> (2) About namespaces.  Would type/class names count as another namespace?
> Compiler macros?

No.  There is no way to "name" these things in a program without using quote.
They are just data keys.  That's different than (go foo), which names the
entity in a way that is both not quoted and adheres to lexically established
rules of lookup.
From: Christopher Browne
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <wc7n3.56919$AU3.1409523@news2.giganews.com>
On Mon, 26 Jul 1999 23:03:33 +0300, Vassil Nikolov
<········@poboxes.com> wrote: 
>Kent M Pitman wrote:                [1999-07-26 19:32 +0000]
>
>  [...]
>  > Lisps are partitioned, by definition, into families subscripted
>  > by the number of namespaces they use.  Scheme, because it has
>  > only one, is a Lisp1.  CL is often called a Lisp2 (since it has
>  > separated functions and values) but is really some number higher
>  > than that (at least 4; I never made a thorough check to see if
>  > there were any other namespaces; if someone knows others besides
>  > blocks and go-tags, do mention them). 
>  [...]
>
>(1) About Scheme which I don't know that well.  Does Scheme have block
>names?  (I don't expect it to have go tags.)

Named lets seem to be the nearest thing.  Nope, no go tags.

> Would the name of a named let shadow a function with the same name? 

Here's a little sample:

(define (showit x)
  (display x))

(define (nlet)
  (let 
      showit
    ((counter 1))
    (display counter)
    (if
     (> 10 counter)
     (showit (+ 1 counter)))))

showit is both a function as well as the name of a named let.

The output of running (nlet) is
12345678910
which clearly indicates that it does indeed shadow.

>(2) About namespaces.  Would type/class names count as another
>namespace?  Compiler macros?

Scheme macros are not something I've had opportunity to get real
familiar with, but I'd certainly expect them to shadow much as does
the "showit" in the named let.
-- 
"... psychologists sometimes refer to perception as controlled
 hallucination ..." -- B. K. P. Horn 6.866/6.801 Lecture
········@ntlug.org- <http://www.ntlug.org/~cbbrowne/langlisp.html>
From: Vassil Nikolov
Subject: namespaces (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <l03130300b3c3ceb5a465@195.138.129.101>
Kent M Pitman wrote:                [1999-07-26 22:50 +0000]

  [about CATCH/THROW in Scheme]

Thank you for the explanation.  It helps me to know the Scheme way
whether or not it is the Right Way.

  > > (2) About namespaces.  Would type/class names count as another namespace?
  > > Compiler macros?
  > 
  > No.  There is no way to "name" these things in a program without using quote.
  > They are just data keys.  That's different than (go foo), which names the
  > entity in a way that is both not quoted and adheres to lexically established
  > rules of lookup.

Is `lexically established rules of lookup' the critical distinguishing
feature of a namespace, in fact?  (Bearing in mind that type/class names
do not follow such rules.)

Besides, there _is_ a way to name those without using quote, e.g.
in a declaration.  So perhaps the actual point is that they can _also_
be named using a quote?

When thinking whether type/class names form a distinct namespace
in Common Lisp I also had in mind languages where the same identifier
cannot name a type and a variable at the same time.


Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.
From: Kent M Pitman
Subject: Re: namespaces (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <sfwwvvlo93i.fsf@world.std.com>
Vassil Nikolov <········@poboxes.com> writes:

>   > > (2) About namespaces.  Would type/class names count as 
>   > > another namespace? Compiler macros?
>   > 
>   > No.  There is no way to "name" these things in a program without
>   > using quote.  They are just data keys.  That's different than
>   > (go foo), which names the entity in a way that is both not
>   > quoted and adheres to lexically established rules of lookup.
> 
> Is `lexically established rules of lookup' the critical distinguishing
> feature of a namespace, in fact?  (Bearing in mind that type/class names
> do not follow such rules.)

I like to think so.  Essentially, the things that are "namespaces" are
the things the compiler is keeping track of and that would be "closed over"
in a closure.  So
  (block foo
    (flet ((frob (x) (return-from foo x)))
      (+ (block foo (frob 4)) 5)))
returns 4 and not 9 because block names are in a namespace and namespaces
are closed-over by lambda expressions.  This is a kind of "seat of the pants"
(i.e., practical experience) way of thinking about it.  I have no idea how
these things are thought of formally.  In case you can't tell, I've lived
my life in the company of people who are trained formally, but I'm not
specially schooled in formalese in many cases.  I never did formal semantics,
etc.  My definition of knowing the semantics is
"knowing how to never do something wrong".  There's probably a more rigorous
definition, but I'm not sure it will get you any farther...

In the case of classes, for example, even if there were a mechanism for
binding the class, the problem is that the class name is a symbol and so
it would necessarily work as a special binding--there can't be any lexical
binding of class names in a closure since there's no way to know that the
intended meaning of the symbol was as a class name and not as something
else entirely.   So
 #'(lambda () (find-class 'foo))
could never be affected by 
 (lexically-bind-class ((foo ...))
   ...)
because it contains only function calls and there is no dataflow to those
function calls communicating the lexical environment.  For example, I could
write (defun opaque-find-class (x) (find-class x))
and instead do
 #'(lambda () (opaque-find-class 'foo))
and then pass that closure into my supposed lexically-bind-class operator,
and it could never have any effect.  So we know that lexically binding a
class is meaningless because there is no path from the lexical data to the
place where it would be "used".  For every lexical "binder", there has to be
a corresponding lexical "user" or else you're just not in that space, I guess.
(Never really thought about that in that way, but that feels like the right
way to say the thing I always think.)

Hope you can make sense of this.  One virtue of being formal about things
is that they say it often briefer than I might.   I never find that very
helpful, but I suppose others might. :-)

> Besides, there _is_ a way to name those without using quote, e.g.
> in a declaration.  So perhaps the actual point is that they can _also_
> be named using a quote?

Ugh.  This isn't really quite so.  I think that if you poked at them, you'd
find that most systems seeing 
 (declare (type frobozz x))
and not recognizing frobozz as a primitive type instead compile something
that looks like a type-check for standard-class or some such thing 
(perhaps inquiring of the present system and hoping it's declared) but
again compile code that internally uses (ensure-something-or-other 'frobozz)
or (find-something-or-other 'frobozz) or something like that, with the quote
sneaking back in there.  I bet internally there is not a set of special
forms that are being used.  I don't think there would be any point.
I might be wrong, though.

> When thinking whether type/class names form a distinct namespace
> in Common Lisp I also had in mind languages where the same identifier
> cannot name a type and a variable at the same time.

In CL they certainly can, of course.  Other languages are other languages
and I didn't mean to speak about those.  Surely it's possible for types
to be a namespace.  But I don't think they are in CL.

Of course they are in the more general sense that packages are a
namespace.  They are a space of names.  All of my remarks above have
to do with the sense of the word namespace as used in the Lisp1/Lisp2
issue, which does not address the "partitioning of data" but "the
partitioning of program elements".  A package system certainly manages
namespaces of a kind, but it's of a different kind.  

If you want an analogy, it would be the sense in which I think SETQ is
not the same kind of destructive as SETF [except the special case of
SETF that is secretly a SETQ or the special case of SETQ that is
secretly a SETF; boy do I hate those two oddities when it comes to
explaining things].  It bugs me no end that Scheme uses SET! to set
variables, as if there was any "side-effect" going on.  To me, a
programmatic side-effect and a data side-effect are VERY
different--they happen at different reflective levels.  SETQ is not a
data mutator, which is why one ends up with the bug commonly known as
the "delete bug"; SETQ is not powerful enough by itself to affect the
value of the actual argument of a function when all it does is assign
the formal parameter...  Anyone who implements SETF immediately sees
that SETQ is not just a trivial case of other mutators, but a
completely different beast...
From: Martin Rodgers
Subject: Re: namespaces (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <MPG.1208c69a617e7771989f83@news.demon.co.uk>
In article <···············@world.std.com>, ······@world.std.com 
says...

>  It bugs me no end that Scheme uses SET! to set
> variables, as if there was any "side-effect" going on. 
 
Could the Scheme view be that SET! is mutating a closure? This is 
certainly implied by SICP introducing assignments in Chapter 3.
The use of SET! breaks referencial transparency. So does SETF in CL.

It seems to me that CL programmers are rather less sensitive about 
mutating state. It's not that it isn't significant, just less of a 
taboo. SML goes even further than Scheme, requiring the programmer to 
annotate all mutatable bindings.

> Anyone who implements SETF immediately sees that SETQ is not just
> a trivial case of other mutators, but a completely different beast...

Technically, yes. Culturally? I don't think Scheme has SETF, and I 
didn't know Scheme when I wrote my own SETF, about 10 years ago. While 
I was familiar with referencial transparency and state mutators, at 
that time I was heavily into the CL way of looking at things.

If any of this is confusing to a Lisp newbie (thinking of the 
subject), then reading SICP may help. See the FAQ for details.
-- 
Please note: my email address is munged; You can never browse enough
         "There are no limits." -- ad copy for Hellraiser
From: Kent M Pitman
Subject: Re: namespaces (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <sfw9080u64a.fsf@world.std.com>
···@wildcard.butterfly.demon.co.uk (Martin Rodgers) writes:

> In article <···············@world.std.com>, ······@world.std.com 
> says...
> 
> >  It bugs me no end that Scheme uses SET! to set
> > variables, as if there was any "side-effect" going on. 
>  
> Could the Scheme view be that SET! is mutating a closure? 

This is what I meant by it crosses reflective layers.

A closure is not a data structure at the reflective level of cons cells.
(Access to it is specifically opaque, except in dialects where you have
functions to read/write closure cells directly.)

(By reflective layer, for anyone who doesn't know the term, I mean 
there is always a program executing the current program, and a program
executing that program, and so on.  Conceptually, anyway.  Closures
are data of the program executing the program, not data of the current
level's program.)
From: Rudi Schlatte
Subject: Re: namespaces (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <87so67w0vm.fsf@semmel.berg>
Kent M Pitman <······@world.std.com> writes:

> SETQ is not a
> data mutator, which is why one ends up with the bug commonly known as
> the "delete bug"; SETQ is not powerful enough by itself to affect the
> value of the actual argument of a function when all it does is assign
> the formal parameter...  Anyone who implements SETF immediately sees
> that SETQ is not just a trivial case of other mutators, but a
> completely different beast...

What is the "delete bug"?  (This feels interesting.)

Rudi
From: Stig Hemmer
Subject: DELETE bug.
Date: 
Message-ID: <ekvso66p35d.fsf_-_@gnoll.pvv.ntnu.no>
Rudi Schlatte <····@sbox.tu-graz.ac.at> writes:
> What is the "delete bug"?  (This feels interesting.)

(delete element sequence)

The funtion DELETE returns its SEQUENCE argument with all copies of
ELEMENT removed.  It is allowed, but not required, to destroy the
original structure of SEQUENCE in the process.

The DELETE bug is to believe that if you have a variable MY-SEQUENCE,
then just doing

(delete 'foo my-sequence)

will remove FOOs from MY-SEQUENCE.  The correct way is 

(setq my-sequence (delete 'foo my-sequence))

In many cases, in most implementations, the short and buggy version
will work.  But this is by accident.  In particular, it will _not_
work if you are trying to delete the first element of a list.  And you
cannot trust it to work in other cases.

Stig Hemmer,
Jack of a Few Trades.

PS: I suppose you could write a DELETE that would "correctly" remove
   the first element of a list, but this would be a serious case of
   solving the wrong problem.
From: Bernhard Pfahringer
Subject: Re: DELETE bug.
Date: 
Message-ID: <7nst96$2qj8$1@www.univie.ac.at>
In article <··················@gnoll.pvv.ntnu.no>,
Stig Hemmer  <····@pvv.ntnu.no> wrote:
>
>PS: I suppose you could write a DELETE that would "correctly" remove
>   the first element of a list, but this would be a serious case of
>   solving the wrong problem.

Why? I'd be more happy with a definition of delete that guarantees destructive
behaviour and forces the result to be identical thereby avoiding the
SETQ-bug. One source of bugs less, and it is easy to do. But then I've
been accused of being a control freak before, so it might just be me.

Here's the concept, implementing correct behaviour of all keys
like :from-end, :test, :test-not, :start, :end, :count, :key is left as
an exercise :-) 

(defmethod true-delete ((x t)(l list))
  (loop with point = l
	while point
	do
	(if (eql x (first point))
	    (setf (first point) (second point)
		  (rest point) (cddr point))
	    (setq point (rest point))))
  l)

Bernhard
-- 
--------------------------------------------------------------------------
Bernhard Pfahringer
Austrian Research Institute for  http://www.ai.univie.ac.at/~bernhard/
Artificial Intelligence          ········@ai.univie.ac.at 
From: Bernhard Pfahringer
Subject: Re: DELETE bug.
Date: 
Message-ID: <7o585l$1ha2$1@www.univie.ac.at>
In article <·············@www.univie.ac.at>,
Bernhard Pfahringer <········@hummel.ai.univie.ac.at> wrote:
>In article <··················@gnoll.pvv.ntnu.no>,
>Stig Hemmer  <····@pvv.ntnu.no> wrote:
>>
>>PS: I suppose you could write a DELETE that would "correctly" remove
>>   the first element of a list, but this would be a serious case of
>>   solving the wrong problem.
>
>Why? I'd be more happy with a definition of delete that guarantees destructive
>behaviour and forces the result to be identical thereby avoiding the
>SETQ-bug. One source of bugs less, and it is easy to do. But then I've
>been accused of being a control freak before, so it might just be me.
>
>Here's the concept, implementing correct behaviour of all keys
>like :from-end, :test, :test-not, :start, :end, :count, :key is left as
>an exercise :-) 
>
>(defmethod true-delete ((x t)(l list))
>  (loop with point = l
>	while point
>	do
>	(if (eql x (first point))
>	    (setf (first point) (second point)
>		  (rest point) (cddr point))
>	    (setq point (rest point))))
>  l)
>

HOW EMBARRASSING!

As has be mentioned, NIL cannot be handled at the LISP level.

Even though I suppose some implementations could handle it
"behind the scenes" (maybe invisible forwarding pointers on
Lisp machines?), it would be too expensive runtime-wise to
require all implementations to handle such cases. So if one
wanted the above behaviour, one would need to implement some
kind of redirection, e.g. a proper container class.

Bernhard
-- 
--------------------------------------------------------------------------
Bernhard Pfahringer
Austrian Research Institute for  http://www.ai.univie.ac.at/~bernhard/
Artificial Intelligence          ········@ai.univie.ac.at 
From: Gareth Rees
Subject: Re: DELETE bug.
Date: 
Message-ID: <sihfmmlzc2.fsf@cre.canon.co.uk>
Stig Hemmer <····@pvv.ntnu.no> wrote:
> PS: I suppose you could write a DELETE that would "correctly" remove
>    the first element of a list

How would your DELETE work in the case where all elements of the list are
deleted?

-- 
Gareth Rees
From: Reini Urban
Subject: Re: DELETE bug.
Date: 
Message-ID: <37a2042b.124462127@judy.x-ray.local>
Stig Hemmer <····@pvv.ntnu.no> wrote:
>Rudi Schlatte <····@sbox.tu-graz.ac.at> writes:
>> What is the "delete bug"?  (This feels interesting.)
...
>(delete 'foo my-sequence)
>
>will remove [some] FOOs from MY-SEQUENCE.  The correct way is 
             inserted by myself. hey, editing foreign text is nice.
>(setq my-sequence (delete 'foo my-sequence))

but i didn't really understand what kent meant with "delete bug" in the
discussion about SETQ versus SETF. maybe he considered something else
though delete with a car is undoubtedly a problem, let's say a
documentation problem. 

but i see no difference in 
  (setq my-sequence (delete 'foo my-sequence)) vs. 
  (setf my-sequence (delete 'foo my-sequence)) and any possible setf
expansion.
and setq IS a data mutator here. it must be used as such, otherwise the
"delete bug" will hit you. this may be called a too vaguely promised
side-effect in delete.

I also read kent's chapter several times, and i believe kent just mixed
it up somehow. but it may be also just too hard to understand for me:
>If you want an analogy, it would be the sense in which I think SETQ is
>not the same kind of destructive as SETF [except the special case of
>SETF that is secretly a SETQ or the special case of SETQ that is
>secretly a SETF; boy do I hate those two oddities when it comes to
>explaining things].  It bugs me no end that Scheme uses SET! to set
>variables, as if there was any "side-effect" going on.  To me, a
>programmatic side-effect and a data side-effect are VERY
>different--they happen at different reflective levels.  SETQ is not a
>data mutator, which is why one ends up with the bug commonly known as
>the "delete bug"; SETQ is not powerful enough by itself to affect the
>value of the actual argument of a function when all it does is assign
>the formal parameter...  Anyone who implements SETF immediately sees
>that SETQ is not just a trivial case of other mutators, but a
>completely different beast...
--                                         
Reini
From: Rudi Schlatte
Subject: Re: DELETE bug.
Date: 
Message-ID: <87so63i88p.fsf@semmel.berg>
······@xarch.tu-graz.ac.at (Reini Urban) writes:

> Stig Hemmer <····@pvv.ntnu.no> wrote:
> ....
> >(delete 'foo my-sequence)
[...]
> >(setq my-sequence (delete 'foo my-sequence))
> 
> but i didn't really understand what kent meant with "delete bug" in the
> discussion about SETQ versus SETF. maybe he considered something else
> though delete with a car is undoubtedly a problem, let's say a
> documentation problem. 
> 

Ditto.  I was aware of the behavior Stig describes (and also Marco in
private email, thank y'both), but did not see where it applies in the
context of the discussion (and also did not know the term "delete
bug").

Now, in c.l.l there are always some threads that I really enjoy
reading because I encountered similar problems or can read about new
ways of expressing things, and then there are those that I cannot
follow because of lack of knowledge / practice on my part.  What drove
me to de-lurk was the sudden transformation from type 1 to type 2
(i.e. "I really should understand this!  What is happening?").

Prost,

Rudi
From: Vassil Nikolov
Subject: Re: DELETE bug.
Date: 
Message-ID: <l03130301b3c7c05074ae@195.138.129.84>
Reini Urban wrote:                [1999-07-30 20:09 +0000]

  [...]
  > I also read kent's chapter several times, and i believe kent just mixed
  > it up somehow. but it may be also just too hard to understand for me:
  > >If you want an analogy, it would be the sense in which I think SETQ is
  > >not the same kind of destructive as SETF [except the special case of
  > >SETF that is secretly a SETQ or the special case of SETQ that is
  > >secretly a SETF; boy do I hate those two oddities when it comes to
  > >explaining things].  It bugs me no end that Scheme uses SET! to set
  > >variables, as if there was any "side-effect" going on.  To me, a
! > >programmatic side-effect and a data side-effect are VERY
! > >different--they happen at different reflective levels.  SETQ is not a
  > >data mutator, which is why one ends up with the bug commonly known as
  > >the "delete bug"; SETQ is not powerful enough by itself to affect the
  > >value of the actual argument of a function when all it does is assign
  > >the formal parameter...  Anyone who implements SETF immediately sees
  > >that SETQ is not just a trivial case of other mutators, but a
  > >completely different beast...

Not that I may explain it on the author's behalf...  I understand the
above (`SETQ is not a data mutator') in the same sense as the rule
that a declaration is not about a variable but about an object (which
is the value of the variable).  And the note about reflective levels is
important, the notion itself being explained in another post in the
same thread; for convenience:

----- forwarded text follows -----

  Newsgroups: comp.lang.lisp
  From: Kent M Pitman <······@world.std.com>
  Subject: Re: namespaces (Ex: Re: [newbie] lambda?)
  Message-ID: <···············@world.std.com>
  Date: Wed, 28 Jul 1999 15:49:25 GMT
  
  ···@wildcard.butterfly.demon.co.uk (Martin Rodgers) writes:
  
  > In article <···············@world.std.com>, ······@world.std.com 
  > says...
  > 
  > >  It bugs me no end that Scheme uses SET! to set
  > > variables, as if there was any "side-effect" going on. 
  >  
  > Could the Scheme view be that SET! is mutating a closure? 
  
  This is what I meant by it crosses reflective layers.
  
  A closure is not a data structure at the reflective level of cons cells.
  (Access to it is specifically opaque, except in dialects where you have
  functions to read/write closure cells directly.)
  
  (By reflective layer, for anyone who doesn't know the term, I mean 
  there is always a program executing the current program, and a program
  executing that program, and so on.  Conceptually, anyway.  Closures
  are data of the program executing the program, not data of the current
  level's program.)
  
  
----- end of forwarded text -----





Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.
From: Johan Kullstam
Subject: Re: DELETE bug.
Date: 
Message-ID: <m2n1wbf5im.fsf@sophia.axel.nom>
Stig Hemmer <····@pvv.ntnu.no> writes:

> Rudi Schlatte <····@sbox.tu-graz.ac.at> writes:
> > What is the "delete bug"?  (This feels interesting.)
> 
> (delete element sequence)
> 
> The funtion DELETE returns its SEQUENCE argument with all copies of
> ELEMENT removed.  It is allowed, but not required, to destroy the
> original structure of SEQUENCE in the process.
> 
> The DELETE bug is to believe that if you have a variable MY-SEQUENCE,
> then just doing
> 
> (delete 'foo my-sequence)
> 
> will remove FOOs from MY-SEQUENCE.  The correct way is 
> 
> (setq my-sequence (delete 'foo my-sequence))
> 
> In many cases, in most implementations, the short and buggy version
> will work.  But this is by accident.  In particular, it will _not_
> work if you are trying to delete the first element of a list.  And you
> cannot trust it to work in other cases.
> 
> Stig Hemmer,
> Jack of a Few Trades.
> 
> PS: I suppose you could write a DELETE that would "correctly" remove
>    the first element of a list, but this would be a serious case of
>    solving the wrong problem.

this sounds like a job for ASETF.  i have polished it up a bit.  it
contains a fair amount of borrowing from paul graham.  the GROUP and
_F are his.  the ASETF macro itself has been crufted together out of
graham's ABBREV and ABBREVS.

the idea is for things which intenionally modify themselves you can
use ASETF.  IT is a pronoun which refers to the variable which is
being set.  therefore you can now write

  (ASETF MY-SEQUENCE (DELETE 'FOO IT))

instead of

  (SETQ MY-SEQUENCE (DELETE 'FOO MY-SEQUENCE))

multiple setting can be used as in

  (ASETF FOO (BAZ IT)
         BAR (ZOR IT))

where FOO gets set to (BAZ FOO) and BAR gets set to (ZOR BAR).  aside
from the advertised effect, ASETF is side-effect safe (like INCF and
friends).

where appropriate (using an imperitive form and going overly
side-effect happy is generally considered bad style and ASETF i admit
facilitates this), i like ASETF since it is more flexible than INCF
and less cluttery than defining a whole slew of DELETEF, REVERSEF &c
operations.  ASETF is a meta-INCF.

some useful examples

(ASETF FOO (+ IT Z)) is equivalent to (INCF FOO Z)

it often expands to exactly the same thing.

(ASETF FOO (* 1.2 IT)) grows FOO by a factor of 1.2.  there is no
MULTF as far as i know.

btw, when speaking of destructive functions, there seem to be two
flavors.  one is incidentally destructive in that it may (or might
not!) trash args passed to it, e.g., NREVERSE.  the other is where the
destruction is guarenteed and is itself the desired effect, e.g.,
INCF.  in lieu of anything better, i shall dub them type 1 and type 2
desctructive.  is there some phrase or description to distinguish
these cases of destruction?

the `problem' with DELETE seems to be that DELETE is spec'd as a
type 1 destructive while a naive user expects type 2.  perhaps this
distinction in destruction is worthwhile in that newbies (myself
included) can easily be confused.  in any event, a let me know if
there's a standard way of describing the two.

anyhow, here's the code.  as far as i go, feel free to use it in any
way if it helps you.  i suspect paul graham's license for _on lisp_
code (whatever that may be) probably governs it since so much is
borrowed from there.

;; grouping function
(eval-when (:compile-toplevel :load-toplevel)
  (defun group (source n)
    (if (zerop n) (error "zero length"))
    (labels ((rec (source acc)
	       (let ((rest (nthcdr n source)))
		 (if (consp rest)
		     (rec rest (cons (subseq source 0 n) acc))
                   (nreverse (cons source acc))))))
      (if source (rec source nil) nil))))

;; setf helper
(defmacro _f (op place &rest args)
  (multiple-value-bind (vars forms var set access) 
                       (get-setf-expansion place)
    `(let* (,@(mapcar #'list vars forms)
            (,(car var) (,op ,access ,@args)))
       ,set)))

;; anaphoric setf
(defmacro asetf (&rest implicit-pairs)
  ;; unroll for multiple pairs
  `(progn
     ,@(mapcar (lambda (pair) 
		 `(_f (lambda (it) 
			(declare (ignorable it))
			,(cadr pair))
		      ,(car pair)))
	       (group implicit-pairs 2))))

-- 
J o h a n  K u l l s t a m
[········@ne.mediaone.net]
Don't Fear the Penguin!
From: Vassil Nikolov
Subject: Re: DELETE bug.
Date: 
Message-ID: <l03130302b3cb097fe025@195.138.129.101>
Johan Kullstam wrote:                [1999-08-01 19:25 -0400]

  [...]
  > the idea is for things which intenionally modify themselves you can
  > use ASETF.  IT is a pronoun which refers to the variable which is
  > being set.

You mean, of course, `refers to the _place_ which is being set.'

  [...]
  > where appropriate (using an imperitive form and going overly
  > side-effect happy is generally considered bad style and ASETF i admit
  > facilitates this), i like ASETF since it is more flexible than INCF
  > and less cluttery than defining a whole slew of DELETEF, REVERSEF &c
  > operations.  ASETF is a meta-INCF.

ASETF is a means to overcome DEFINE-MODIFY-MACRO's limitation of
having the place always come first in the lambda-list of the modify
macro being defined.

(Personally, the name ASETF confuses me as I relate it to ASSOC,
ACONS and also AREF.  Besides, a better choice of the reserved
variable name would be IMHO something like &IT, rather than
something which looks like an ordinary variable.)

  [...]
  > btw, when speaking of destructive functions, there seem to be two
  > flavors.  one is incidentally destructive in that it may (or might
  > not!) trash args passed to it, e.g., NREVERSE.  the other is where the
  > destruction is guarenteed and is itself the desired effect, e.g.,
  > INCF.  in lieu of anything better, i shall dub them type 1 and type 2
  > desctructive.  is there some phrase or description to distinguish
  > these cases of destruction?
  > 
  > the `problem' with DELETE seems to be that DELETE is spec'd as a
  > type 1 destructive while a naive user expects type 2.  perhaps this
  > distinction in destruction is worthwhile in that newbies (myself
  > included) can easily be confused.  in any event, a let me know if
  > there's a standard way of describing the two.
  [...]

NREVERSE, DELETE, etc. are called _destructive_; each of them has
a non-destructive counterpart.  INCF, DECF, etc. are _modify macros_.

Destructive functions are called so not simply because they
trash their args, but because they trash _shared structure_.
(In the absence of shared structure, DELETE and REMOVE are
equivalent (in effect; they still might not be equivalent in
performance).)

Modify macros, on the other hand, are data mutators, something
quite different.

Look at it in this way too.  REMOVE/DELETE take one data structure
and produce another from it (the difference between the two being
that if (any part of) this data structure is shared, then one has an
effect on the sharer and the other does not).  Modify macros take
a component of a data structure (via its accessor) and change
whatever is there (except in the case of a simple variable as
a SETF place where there is no data structure at all, but this is
a special case and anyway it is not the raison d'etre for modify
macros).



Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.





 Sent via Deja.com http://www.deja.com/
 Share what you know. Learn what you don't.
From: Amon Seagull
Subject: Re: DELETE bug.
Date: 
Message-ID: <7o4f2f$6al$1@femto.cs.rochester.edu>
:   [...]
:   > btw, when speaking of destructive functions, there seem to be two
:   > flavors.  one is incidentally destructive in that it may (or might
:   > not!) trash args passed to it, e.g., NREVERSE.  the other is where the
:   > destruction is guarenteed and is itself the desired effect, e.g.,
:   > INCF.  in lieu of anything better, i shall dub them type 1 and type 2
:   > desctructive.  is there some phrase or description to distinguish
:   > these cases of destruction?
:   > 
:   > the `problem' with DELETE seems to be that DELETE is spec'd as a
:   > type 1 destructive while a naive user expects type 2.  perhaps this
:   > distinction in destruction is worthwhile in that newbies (myself
:   > included) can easily be confused.  in any event, a let me know if
:   > there's a standard way of describing the two.
:   [...]

: NREVERSE, DELETE, etc. are called _destructive_; each of them has
: a non-destructive counterpart.  INCF, DECF, etc. are _modify macros_.

: Destructive functions are called so not simply because they
: trash their args, but because they trash _shared structure_.
: (In the absence of shared structure, DELETE and REMOVE are
: equivalent (in effect; they still might not be equivalent in
: performance).)

: Modify macros, on the other hand, are data mutators, something
: quite different.

In my head, these "modify macros" are thought as cases of side-effect
programming.  INCF differs from DELETE in that it has a non-functional
component, when you think about the semantics of your program.  (I
guess I just like to call then "side-effect" instructions because I
can then attach it to something I already understand.  I don't
fundamentally object to the term "modify macros".)
amon
From: Vassil Nikolov
Subject: Re: DELETE bug.
Date: 
Message-ID: <l03130300b3ccf4236c44@195.138.129.99>
Gareth Rees wrote:                [1999-08-03 16:06 +0000]

  [...]
  > DELETE is a data mutator
  [...]

What is the one and only true meaning of `data mutator'?

To me, a data mutator is a function such as RPLACA which
does not change the layout of the structure it deals with
but just one of its components (fields).  DELETE, on the
other hand, produces one data structure from another; the
fact that this takes place in a destructive fashion is to me
something quite different from the essence of data mutators.

If DELETE is a data mutator, isn't REMOVE a data mutator
too?  And---from another perspective---SORT would also get
to be a data mutator, wouldn't it?

I am not saying my understanding of `data mutator' is the
Right One, but I do insist there is an essential difference
between e.g. RPLACA and NSUBST, on one hand, and DELETE
and SORT, on the other hand.  Also, I wonder how other people
would use `data mutator.'


Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.





 Sent via Deja.com http://www.deja.com/
 Share what you know. Learn what you don't.
From: Kent M Pitman
Subject: Re: DELETE bug.
Date: 
Message-ID: <sfwaes8nqew.fsf@world.std.com>
Vassil Nikolov <········@poboxes.com> writes:

> What is the one and only true meaning of `data mutator'?
> 
> To me, a data mutator is a function such as RPLACA which
> does not change the layout of the structure it deals with
> but just one of its components (fields).

It probably doesn't surprise you that I don't know if there really is
a one and only one true meaning of much of anything.  This definition
you have is useful to have a name for, but is not the thing that I 
was grumbling about when this thread got kind of kicked off.

My point about SETQ was that SETQ does not have an effect which you can
feel on the other side of a function call.  That is,

 ((lambda (x) ...inside... (setq x ...inside...) ...inside...)
  ...outside...)

is such that the lambda expression does not have a persistent effect on
"...outside..." UNLESS there is a side-effect done elsewhere in the 
"...inside...".  That is, SETQ on its own is not powerful enough.

That's the practical import of the DELETE bug.  There is nothing to 
side-effect.  In a call-by-reference language, you might do a SETQ
and expect the side-effect to propagate back to the caller, but lisp
has no such side-effect.

Incidentally, as an aside, the Lisp Machine has a LOCF operator such
that (LOCF place) yields a value (specifically, a locative) such that
(LOCATION-CONTENTS locative) will yield the contents of place.  The
delete bug can be headed off by doing a variant of DELETE that expects
a locative.  That way, you can use (LOCF X) in a caller and pass a 
pointer to X's location, effectively implementing call-by-reference by
making the locative pointer be a value type.

> If DELETE is a data mutator, isn't REMOVE a data mutator
> too?  And---from another perspective---SORT would also get
> to be a data mutator, wouldn't it?

I can see SORT.  I missed the part about REMOVE.
 
> I am not saying my understanding of `data mutator' is the
> Right One, but I do insist there is an essential difference
> between e.g. RPLACA and NSUBST, on one hand, and DELETE
> and SORT, on the other hand.  Also, I wonder how other people
> would use `data mutator.'

This is a useful distinction to draw, but I would prefer a new word be
made rather than attaching semantics to an existing/deployed word.
e.g., an "in-place data mutator" vs a "rearranging data mutator".  If
I understand the sense of your terms.

The thing I'm grumbling about with SETQ, though, is about the fact that
the "data" that is altered by SETQ is not  first class data accessible to
the program in some other means; it's hidden state known only to the
implementation.  So the programmer can tell some state change is occurring
but cannot manipulate the changed object in a first-class way.
From: Vassil Nikolov
Subject: Re: DELETE bug.
Date: 
Message-ID: <l03130305b3cd980b61ec@195.138.129.99>
Kent M Pitman wrote:                [1999-08-04 04:03 +0000]

  [...]
  > > If DELETE is a data mutator, isn't REMOVE a data mutator
  > > too?  And---from another perspective---SORT would also get
  > > to be a data mutator, wouldn't it?
  > 
  > I can see SORT.  I missed the part about REMOVE.

I was too brief.  What I meant was this:

(A) I expect people to not be willing to call REMOVE a data mutator
    (well, I might be wrong).

(B) On the other hand, if we call DELETE a data mutator, then we
    ought to call REMOVE a data mutator too, because they do the
    same _with regards to_ the changes to the data structure they
    perform:
    * they differ in speed, amount of consing, etc. but that
      is irrelevant to being data mutators or not;
    * they also differ in their effect on shared structure.  I
      would argue, however, that that, too, does not make one
      a data mutator and the other not: the exact effect of
      DELETE on shared structure is unpredictable, so one cannot
      use it to purposefully change shared structure.

And this is all driving to the point that I wouldn't want to
call any of DELETE, REMOVE, or SORT a data mutator (see below).

  > > I am not saying my understanding of `data mutator' is the
  > > Right One, but I do insist there is an essential difference
  > > between e.g. RPLACA and NSUBST, on one hand, and DELETE
  > > and SORT, on the other hand.  Also, I wonder how other people
  > > would use `data mutator.'
  > 
  > This is a useful distinction to draw, but I would prefer a new word be
  > made rather than attaching semantics to an existing/deployed word.
  > e.g., an "in-place data mutator" vs a "rearranging data mutator".  If
  > I understand the sense of your terms.

Yes, that is the sense.  I would suggest to use `data mutator' only
for `in-place data mutator'; I don't have a good suggestion for a word
for the other category, `rearranging data mutator' (and the latter
come in two flavours, destructive and non-destructive):
`data permutator,' perhaps?

But I would like to know what words others use; if already `data
mutator' is in popular use to mean both kinds of data operators,
then I won't insist on changing this, of course.

  > The thing I'm grumbling about with SETQ, though, is about the fact that
  > the "data" that is altered by SETQ is not  first class data accessible to
  > the program in some other means; it's hidden state known only to the
  > implementation.  So the programmer can tell some state change is occurring
  > but cannot manipulate the changed object in a first-class way.

Yes, I in fact started talking about something different from this issue
about SETQ.


Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.





 Sent via Deja.com http://www.deja.com/
 Share what you know. Learn what you don't.
From: Gareth Rees
Subject: Re: DELETE bug.
Date: 
Message-ID: <sid7x44zo1.fsf@cre.canon.co.uk>
Stig Hemmer <····@pvv.ntnu.no> wrote:
> I suppose you could write a DELETE that would "correctly" remove the
> first element of a list, but this would be a serious case of solving
> the wrong problem.

I think a better approach would be to recognize that DELETE is a data
mutator, and write something like

    (define-modify-macro deletef (item &rest keywords)
      (lambda (seq item &rest keywords)
	(apply #'delete item seq keywords)))

A proper implementaton of DELETEF would take its arguments in the same
order as DELETE, but wouldn't be quite so terse.

-- 
Gareth Rees
From: Johan Kullstam
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <uemhrjgwq.fsf@res.raytheon.com>
Vassil Nikolov <········@poboxes.com> writes:

> Kent M Pitman wrote:                [1999-07-26 19:32 +0000]
> 
>   [...]
>   > Lisps are partitioned, by definition, into families subscripted by the number
>   > of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL
>   > is often called a Lisp2 (since it has separated functions and values) but
>   > is really some number higher than that (at least 4; I never made a thorough
>   > check to see if there were any other namespaces; if someone knows others
>   > besides blocks and go-tags, do mention them).
>   [...]
> 
> (1) About Scheme which I don't know that well.  Does Scheme have block
> names?  (I don't expect it to have go tags.)  Would the name of a named let
> shadow a function with the same name?
> 
> (2) About namespaces.  Would type/class names count as another namespace?
> Compiler macros?

as far as i can make out, a namespace in common-lisp corresponds to a
slot on a symbol.  common-lisp therefore has at least three
name-spaces: value, function and property-list.  (there may be more but
i cannot recall offhand...)

-- 
johan kullstam
From: Duane Rettig
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <4u2qnvydm.fsf@beta.franz.com>
Johan Kullstam <········@ne.mediaone.net> writes:

> as far as i can make out, a namespace in common-lisp corresponds to a
> slot on a symbol.  common-lisp therefore has at least three
> name-spaces: value, function and property-list.  (there may be more but
> i cannot recall offhand...)

I think you are the first to have mentioned the property list on this
thread.  In fact, the property list is the most important namespace,
because it is itself a namespace-implementor.  In fact, the CL Spec itself
says that the representations of the namespaces ("attributes" are
implementation-dependent, so in theory you could create a symbol with
exactly one slot: a property-list.  The spec also gives a minimum
attribute set for a symbol: Name, Package, (Property-list), Value, and
Function; these other 4 could be implemented as name, package, value,
and function properties of the symbol.  I remember seeing some older
lisps that implemented the function definiton of the symbol in just
this way.

Of course, the reason no CL (that I know of) implements this way is for
the dual reason of space and speed, which, since every symbol needs these
attributes anyway, they may as well be fast-access one-word slots.  However,
the  reason I point this out is to broaden the scope of the thinking here;
I think that property-lists give all lisps an open-ended namespace space.
Many of the namespaces that are discussed in this thread are in fact
implemented using properties.  What separates Lisp1 and Lisp2 is
specifically how the Value and Function namespaces are handled (i.e.
in Lisp1 they are one and the same and in Lisp2 they are separate
and distinguishable).


Of course, there are even more bizarre representations of symbols possible;
You could have symbols one-word-apart, with each "adjacent" slot in the
symbol separated by a fixed distance; this could allow you to place all of
the symbol-names into a compact read-only space... I've never seen an
implementation of such an idea, but who knows?...

-- 
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: Rainer Joswig
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <joswig-3007990244280001@194.163.195.67>
In article <·············@beta.franz.com>, Duane Rettig <·····@franz.com> wrote:

> Of course, there are even more bizarre representations of symbols possible;
> You could have symbols one-word-apart, with each "adjacent" slot in the
> symbol separated by a fixed distance; this could allow you to place all of
> the symbol-names into a compact read-only space... I've never seen an
> implementation of such an idea, but who knows?...

How about making symbols CLOS objects?
From: Kent M Pitman
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <sfw7lni7qv6.fsf@world.std.com>
······@lavielle.com (Rainer Joswig) writes:

> In article <·············@beta.franz.com>, Duane Rettig <·····@franz.com> wrote:
> 
> > Of course, there are even more bizarre representations of symbols possible;
> > You could have symbols one-word-apart, with each "adjacent" slot in the
> > symbol separated by a fixed distance; this could allow you to place all of
> > the symbol-names into a compact read-only space... I've never seen an
> > implementation of such an idea, but who knows?...
> 
> How about making symbols CLOS objects?

They are.

Hint:  Clos has metaclasses and one of them is built-in-class.

You could also implement symbols as an index offset from each of 
several different locations.  So that page 1 had only the value
cells of symbols and page 2 had only the function cells and page 3
had only the plists, and so that when you had a pointer N it meant
"get the value from valuespacebase+symboladdress, get the function
value from functionspacebase+symboladdress, et.".  There are a variety
of such techniques possible, and extensive discussions were had in
the writing of the spec to make sure none of the wording suggested
you couldn't do these.  but practically speaking, I think most 
implementors have just found that a more standard-class-ish implementation
works better.

My personal wish is to see KEYWORDs redone in the following way: they
should just be strings (like  I guess Java's canonical strings) and
then (symbol-name some-packaged-symbol) => keyword.  that is, all
symbols with the same name would share the same "keyword" as their name,
and that name would be both a keyword and a not-to-be-modified string.
That would cut down a lot on my fear of storage clutter in having
 (foo :initarg :foo ...) 
in defstructs.  I always feel guilty about having 2*N symbols.
Some days I do
 (foo :initarg foo ...)
just to make a symbolic stab at fixing it.  But it would be simpler to
do another way.  In the long distant past, we had talked about how
keywords were not supposed to be symbols; we just kind of "parked"
them in the symbol space for a while for want of something better
to do with them.  And then they got stuck.
From: Rainer Joswig
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <joswig-3007990557580001@194.163.195.67>
In article <···············@world.std.com>, Kent M Pitman <······@world.std.com> wrote:

> ······@lavielle.com (Rainer Joswig) writes:
> 
> > In article <·············@beta.franz.com>, Duane Rettig <·····@franz.com> wrote:
> > 
> > > Of course, there are even more bizarre representations of symbols possible;
> > > You could have symbols one-word-apart, with each "adjacent" slot in the
> > > symbol separated by a fixed distance; this could allow you to place all of
> > > the symbol-names into a compact read-only space... I've never seen an
> > > implementation of such an idea, but who knows?...
> > 
> > How about making symbols CLOS objects?
> 
> They are.
> 
> Hint:  Clos has metaclasses and one of them is built-in-class.

I was thinking of the metaclass standard-class. ;-)


> My personal wish is to see KEYWORDs redone in the following way: they
> should just be strings (like  I guess Java's canonical strings) and
> then (symbol-name some-packaged-symbol) => keyword.  that is, all
> symbols with the same name would share the same "keyword" as their name,
> and that name would be both a keyword and a not-to-be-modified string.
> That would cut down a lot on my fear of storage clutter in having
>  (foo :initarg :foo ...) 
> in defstructs.  I always feel guilty about having 2*N symbols.
> Some days I do
>  (foo :initarg foo ...)

Yes, that's a problem. I'm also not too happy about:

(defclass person ()
  ((name :initarg :name :accessor person-name)))

(defun foo (&key name)
  (make-instance 'person :name name))

(person-name (foo :name "bar"))


"name" is a slot-name, name for an initarg,
then it is a symbol for a keyword argument and
being used as keyword when calling the function.
Additionally you get accessors with "-name".

------------------- 

Sometimes I would like instead

(defun foo (&key name age gender)
  (make-instance 'person :name name :age age :gender gender))

or

(defun foo (&rest initargs &key name age gender)
  (declare (dynamic-extent initargs)
           (ignore name age gender))
  (apply #'make-instance 'person initargs))


a shorter

(defun foo (&key name age gender)
  (make-my-instance 'person name age gender))
From: Kent M Pitman
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <sfwlnby4u0y.fsf@world.std.com>
······@lavielle.com (Rainer Joswig) writes:

> > > How about making symbols CLOS objects?
> > 
> > They are.
> > 
> > Hint:  Clos has metaclasses and one of them is built-in-class.
> 
> I was thinking of the metaclass standard-class. ;-)

Yes, I know, and I was sure you knew.  But it's just a common
confusion a lot of people make--to assume CLOS is separate from CL,
rather than totally permeating it.  I like to make a practice of
watching for this exact separation that your words appeared to make
and using it as a way of emphasizing that CLOS is a way of explaining
even the built-in classes.

 
> Yes, that's a problem. I'm also not too happy about:
> [...discussion of :accessor person-name vs :accessor name removed.]

I'm mixed on this, too.  I'm glad CL doesn't force me to decide one way
or the other.
From: Vassil Nikolov
Subject: keywords (Ex: Re: [newbie] lambda?)
Date: 
Message-ID: <l03130304b3c7c2b70506@195.138.129.84>
Kent M Pitman wrote:                [1999-07-30 03:34 +0000]

  [...]
  > 
  > My personal wish is to see KEYWORDs redone in the following way: they
  > should just be strings
  [...]

There was a discussion about that in comp.lang.lisp a few months ago
and the conclusion I drew for myself was that everybody agrees that
this is what should happen to keywords (i.e. they are no more expensive
than interned strings, with no storage wasted on value cell, function
cell, etc.) but that there are numerous more important things to do
with Lisp so this change might not get its turn before RSN.




Vassil Nikolov
Permanent forwarding e-mail: ········@poboxes.com
For more: http://www.poboxes.com/vnikolov
  Abaci lignei --- programmatici ferrei.
From: Kent M Pitman
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <sfwhfmn7zpx.fsf@world.std.com>
Johan Kullstam <········@ne.mediaone.net> writes:

> as far as i can make out, a namespace in common-lisp corresponds to a
> slot on a symbol. 

no.  this is entirely an unfortunate coincidence in some prominent cases.
There is, however, no symbol-go-tag slot, nor a symbol-block-tag.
From: Howard R. Stearns
Subject: Namespace-N (Re: [newbie] lambda?)
Date: 
Message-ID: <37A866E1.EDFDA24D@elwood.com>
I think if we want to go through the exercise of actually enumerating
the namespaces in Common Lisp, we should define exactly what we mean by
namespaces.

I don't have the formal background to give these the right names, but as
a practical matter, I find it convenient to distinguish between:

 1. "Syntactical" namespaces that MUST be recognized by eval/compile,
where the name is unquoted.  These certainly include value, function,
block, go-tag. 

 2. "Symbolic/runtime" namespaces usually refering to first class
objects, where the name is quoted.  These can include value and
function, but also properties, classes, types, packages, properties,
conditions, restarts, method-combinations, documentation,
presentation-types, resources, systems, and anything an application
cares to set up.  (In fact, I have a defintern macro that I use all the
time that creates a new "interned object" namespace.)  I consider
catch-tags in this category, even though the exit they refer to is not a
first class object in Common Lisp.

Note that:

+ we can enumerate all of either category that appear in the spec, but
we can't enumerate all the potential namespaces of the second kind that
may appear in an application.  They're user extendable.

+ Scheme consistently uses one syntactic namespace not just for value
and function, but also for control-flow (continuations).  Even so, all
three refer to first class objects.

+ The "names" of symbolic namespaces can involve tupples of more than
just a single symbol.  For example, one can view properties as being
named by a tupple of the symbol name and the property name.  This view
makes it hard to think about the namespace of namespaces.

+ There are often syntactic forms (macros) which allow runtime
namespaces to be used unquoted, and even to be optimized by the
compiler.  Examples are types in typecase, conditions and restarts in
their xxx-case forms, etc. This obscures that that the namespace is, in
principle, a runtime namespace.

+ There are holes in the spec where the relationship between some of
these runtime namespaces is not fully defined.  For example, using
deftype, defstruct, defclass and define-condition with the same name, or
defining setf defuns and setf-expanders with the same name.  (The latter
also running into the name-tupple vs namespace issue.)

+ One could even argue that numbers, pathnames, etc. are examples of
runtime namespaces (that sometimes can be compiler optimized or left
unquoted). Realizing the "potential uselessness" of thinking about
namespaces this way is what leads me to give special attention to
syntactical namespaces, and to not try to enumerate all the
symbolic/runtime namespaces.

The point is that there are different ways of carving up "metaspaces",
and that trying to enumerate them depends on how you define that
partitioning.

Johan Kullstam wrote:
> 
> Vassil Nikolov <········@poboxes.com> writes:
> 
> > Kent M Pitman wrote:                [1999-07-26 19:32 +0000]
> >
> >   [...]
> >   > Lisps are partitioned, by definition, into families subscripted by the number
> >   > of namespaces they use.  Scheme, because it has only one, is a Lisp1.  CL
> >   > is often called a Lisp2 (since it has separated functions and values) but
> >   > is really some number higher than that (at least 4; I never made a thorough
> >   > check to see if there were any other namespaces; if someone knows others
> >   > besides blocks and go-tags, do mention them).
> >   [...]
> >
> > (1) About Scheme which I don't know that well.  Does Scheme have block
> > names?  (I don't expect it to have go tags.)  Would the name of a named let
> > shadow a function with the same name?
> >
> > (2) About namespaces.  Would type/class names count as another namespace?
> > Compiler macros?
> 
> as far as i can make out, a namespace in common-lisp corresponds to a
> slot on a symbol.  common-lisp therefore has at least three
> name-spaces: value, function and property-list.  (there may be more but
> i cannot recall offhand...)
> 
> --
> johan kullstam
From: Tim Bradshaw
Subject: Re: [newbie] lambda?
Date: 
Message-ID: <nkjoggzcpr2.fsf@tfeb.org>
Fernando Mato Mira <········@iname.com> writes:

> 
> The expression in the CAR of an application is not evaluated, but
> searched in operator space,
> so the same happens elsewhere:
> 
> Scheme: ((lambda (x) x) 1)
> 

This is legal CL, but it's a special case.

--tim