is CLOS reall OO?

861 views
Skip to first unread message

Kevin Haddock

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

Hi, I'm somewhat new to lisp but upon looking into CLOS it would appear
that the primary way to set slot values is with setf. Now I know that
setf is a generic function (which means it could do different things
with different objects given as arguments), but isn't it fundamentally
wrong for one object to be tinkering around with another's private data?

I have tried creating specific methods for accessing the private data of
objects, but that does not seem very elegant either. You have to match
the number of arguments wether you are storing or retreiving, or you
have to do specific tests to see if the second argument (the one to
store) is there. Is there something I am missing here or is that just
the nature of the beast? What happens, say, if I create a class and all
throughout my code I set one of it's slots with setf, then later in the
development I decide that that slot will not be an actual slot, but
derived from several other slots and now just merely a method. Do I
have to go all throughout my program and change the setf's into method
calls?

Thanks in advance for your feedback,


-Kevin
khad...@ecst.csuchico.edu

Lyman S. Taylor

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

In article <354DEDA4...@ecst.csuchico.edu>,
Kevin Haddock <khad...@ecst.csuchico.edu> wrote:
....

>wrong for one object to be tinkering around with another's private data?

For namespace privacy use packages. The CLOS doesn't manage
namespace control. The fact that "privacy" isn't syntactically
co-located with class declaration doesn't render CLOS non-OO, IMHO.
It may not be as an convenient notation... but that's a syntax argument.


If you have objects and methods you don't want the "user" of you
object library to use, place them in a package and only EXPORT those
methods and class names that the user is suppose to use.

[ Can the "user" of your library sneak in and subvert your package
"privacy"? Sure. However, most other OO languages have "back doors"
too. Perhaps with higher level of difficultly to implement...but
the truely dedicated can subvert them none the less. ]


>I have tried creating specific methods for accessing the private data of
>objects, but that does not seem very elegant either. You have to match
>the number of arguments wether you are storing or retreiving, or you
>have to do specific tests to see if the second argument (the one to
>store) is there.

seperate slot getter/setter methods.... that's basically what you have to
do in Smalltalk... I don't think there are very many who doubt it is OO.

(shape-height aShape ) ==> value

(shape-height-setter aShape new-value ) ==> new-value

That shouldn't collapse into one method with an optional arg.


>the nature of the beast? What happens, say, if I create a class and all
>throughout my code I set one of it's slots with setf, then later in the
>development I decide that that slot will not be an actual slot, but
>derived from several other slots and now just merely a method. Do I
>have to go all throughout my program and change the setf's into method
>calls?

I don't think so. I think you could just define a DEFSETF that
invokes the whatever you come up with for a setter method... that's
all DEFCLASS (or one if its minions ) does for you automagically anyway
(if I remember correctly).

In this particular case, I think you may have a OO Design problem in that
what does setting a "virtual" slot mean. If its values are derived from
several other slots.... How does a new slot value backpropagate
into its numerous sources? You would need a unique mapping from
a single value back to a set of values.

f( a, b, c ) ==> virtual value

inverse-f( virtual-value ) ==> ( a, b, c )

Perhaps it should have been the case that the orignal slot should have
been only "read only" in the first place. Therefore you wouldn't have
setf scattered about.... and switching to a virtual implementation
would be totally transparent.

--

Lyman S. Taylor "Twinkie Cream; food of the Gods"
(ly...@cc.gatech.edu) Jarod, "The Pretender"


Kent M Pitman

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

Kevin Haddock <khad...@ecst.csuchico.edu> writes:

I think your subject line implies some things you don't realize it
does. The term OO has existed a long time and its original meaning
has been co-opted by more modern systems that, while they supply
some interesting functionality (like "encapsulation") do not supply
other features classically associated with OO (like "dynamic typing
for all objects"). The question of "What is OO?" is at this point
inevitably a political one and one that all concerned would do best
to avoid. You're better off to pick the specific features of an OO
system that matter to you and ask about those individually rather
than blundering in thinking it's meaningful to ask whether CLOS is
"real" OO or not. For further remarks on this topic, see my
"Parenthetically Speaking" articles "What's in a Name?" at
http://world.std.com/~pitman/PS/Name.html
and "Lambda: The Ultimate Political Party" at
http://world.std.com/~pitman/PS/Lambda.html

> I know that setf is a generic function (which means it could do
> different things with different objects given as arguments

No, SETF is a macro. It makes its decision about what to do based
on static information. One of the things it might do is to call a
generic function if no static information is known about how to do
the assignment. But in the case of SETF of SLOT-VALUE, that's really
not what happens.

) but isn't it fundamentally


> wrong for one object to be tinkering around with another's private data?

As discussed recently in another thread (search for "private" in this
group within the last month at
http://www.dejanews.com/home_ps.shtml
to find the thread), Common Lisp objects really have no private data.
That fact may be lamentable to some (and not to others) but trying to
begin from a model of privacy and trying to find it in CL won't lead you
anywhere.

> I have tried creating specific methods for accessing the private data of
> objects, but that does not seem very elegant either.
> You have to match
> the number of arguments wether you are storing or retreiving, or you
> have to do specific tests to see if the second argument (the one to

> store) is there. Is there something I am missing here or is that just

> the nature of the beast?

That's what :reader and :accessor are for in slot descriptions, for
example. To help you write these tedious little methods.

Rainer Joswig

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

Kevin Haddock wrote in message <354DEDA4...@ecst.csuchico.edu>...

Ask five OO-experts for their definition of OO-ness. You will get atleast
six answers. Most people know only about a message-passing version.

>Hi, I'm somewhat new to lisp but upon looking into CLOS it would appear
>that the primary way to set slot values is with setf.

There are two ways.

First you can use setting the slot with (setf slot-value):

(defclass ship ()
(pos-x
pos-y
captain))

(setf titanic (make-instance 'ship))

(setf (slot-value titanic 'pos-x) 10
(slot-value titanic 'pos-y) 20)


CL-USER 15 > (describe titanic)

#<SHIP 235A4C04> is a SHIP
POS-X 10
POS-Y 20
CAPTAIN #<unbound slot>

Or you can use the slot-writer method:

(defclass ship ()
(pos-x
pos-y
(captain :accessor ship-captain)))

CL-USER 16 > (setf nautilus (make-instance 'ship))
#<SHIP 203A7AC4>

CL-USER 17 > (setf (ship-captain nautilus) 'nemo)
NEMO

> Now I know that


>setf is a generic function (which means it could do different things

>with different objects given as arguments),

Not setf is the generic function, but the writer method you can use via
setf.

> but isn't it fundamentally
>wrong for one object to be tinkering around with another's private data?


Keep in mind that generic functions are not connected to classes like
in languages like C++/Eiffel/Smalltalk, etc.

Methods are not part of a class definition. They are standing alone and are
defined
outside of classes. There are no inside methods. This takes
some time to understand when coming from a different model
(message passing between objects, where functionality
is part of the object). CLOS deals with classes and objects.
Generic functions are functions (input parameters and return values),
whose selected implementation depends on the arguments provided.
CLOS also enables the generation of an effective method depending
on one or more arguments. Most other OO-languages are
dispatching on one argument (the message receiver).

>What happens, say, if I create a class and all
>throughout my code I set one of it's slots with setf, then later in the
>development I decide that that slot will not be an actual slot, but
>derived from several other slots and now just merely a method. Do I
>have to go all throughout my program and change the setf's into method
>calls?

The idea of setf is that you don't have to remember how to actually
change a certain data structures (the content of an array at a index,
the value for a key in a hashtable, the slot of an object, whatever).
This is all hidden behind the setf mechanism. Knowledge about
a reader is enough.

You actually can write setf methods for writer/accessor functions:

Here SHIP-CAPTAIN is an existing accessor (see the class definition above).

(defmethod (setf ship-captain) :after (new-value (the-ship ship))
(print "Just changed a slot."))

CL-USER 18 > (setf (ship-captain nautilus) 'hornblower)

"Just changed a slot."
HORNBLOWER

Writing a primary setf method:

We define a setf method for SHIP-POS. The argument will
be a list of the x- and y-position. We then set the
pos-x and pos-y slot.

(defmethod (setf ship-pos) (new-position (the-ship ship))
(when (listp new-position)
(setf (slot-value the-ship 'pos-x) (first new-position)
(slot-value the-ship 'pos-y) (second new-position)))
new-position)

CL-USER 19 > (setf (ship-pos titanic) (list 50 60))
(50 60)

CL-USER 20 > (describe titanic)

#<SHIP 23C41A44> is a SHIP
POS-X 50
POS-Y 60
CAPTAIN #<unbound slot>


Greetings,

Rainer Joswig


Barry Margolin

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

In article <6il6rv$2...@desire.lavielle.com>,

Rainer Joswig <jos...@lavielle.com> wrote:
>Ask five OO-experts for their definition of OO-ness. You will get atleast
>six answers. Most people know only about a message-passing version.

Sometime around 1991 or so, I think there was an article in SIGPLAN Notices
or LISP Pointers that evaluated CLOS with respect to a well-known set of
criteria for OO language features (I think they were from OO bigwig like
Booch). Except for the information hiding features (which the article
admitted could be done somewhat with packages), it scored reasonably well.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.

Erik Naggum

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

* Kevin Haddock

| Hi, I'm somewhat new to lisp but upon looking into CLOS it would appear
| that the primary way to set slot values is with setf.

not necessarily. let's consider the two typical cases:

(defclass class-with-setter-getter ()
(some-slot :reader get-some-slot
:writer set-some-slot
:initform 42))

(defvar *setter-getter-instance* (make-instance 'class-with-setter-getter))

(get-some-slot *setter-getter-instance*) => 42
(set-some-slot 41 *setter-getter-instance*) => 41
(get-some-slot *setter-getter-instance*) => 41

(defclass class-with-accessor ()
(some-slot :accessor some-slot
:initform 42))

(defvar *accessor-instance* (make-instance 'class-with-accessor))

(some-slot *accessor-instance*) => 42
(setf (some-slot *accessor-instance*) 41) => 41
(some-slot *accessor-instance*) => 41

BTW: note the order of arguments in SET-SOME-SLOT.

| Now I know that setf is a generic function

no, it isn't. SETF is a macro.

| ... isn't it fundamentally wrong for one object to be tinkering around


| with another's private data?

well, objects don't do any tinkering to begin with, they just are, so
let's presume you meant that some _code_ somewhere "tinkers" with some
object's "private" data.

however, if you think it is "wrong" to do something, then you just don't
do that. if you want the compiler to smack you in the face if you do it
anyway, I'd say you have an attitude problem that needs readjustment
before you resume writing code.

some purportedly object-oriented languages are designed specifically for
people who love to be smacked in the face when they lie to the compiler.
bondage and discipline go hand in hand with very strict rules of privacy
and all that weird deviant stuff. CLOS isn't like that.

CLOS communicates the _intent_ of hiding differently, but if you look for
the ways to express yourself in CLOS, it would very hard indeed _not_ to
see that CLOS code is just as concerned with proper etiquette and access
rights as the anal-retentive languages. if a slot has no :WRITER option,
that's a fairly good sign you should not be writing to this slot. ditto
for :READER or :ACCESSOR. in essence, if you use the function SLOT-VALUE
in your code, you either have the right to do so, or you're trespassing.
_how_ to determine whether you have that right or is trespassing is a
question of policy that you find paralleled in communities everywhere:
whether to use armed guards with Rotweilers to whom you have to declare
people to be your friends, whether to fence yourself in but just lock the
gates, whether to have open access and everybody just keeps an eye on it
all, or whether to let giant open areas be accessible to the public as
long as they behave well. obviously, by using words like "tinkering
about with other's private data", you imply a strong sense of privacy and
an attitude towards heavy policing and ID cards for the children of your
friends and such. you might actually feel _unsafe_ in a CLOS world where
people are just expected to show good taste, unless you feel you can
trust them. it's a matter of what kind programmers you live amongst, I
guess. if you live among thieves and bums who steal and rob you, by all
means go for the compiler who smacks them in the face. if you live among
nice people who you would _want_ to worry about a red-hot plate they can
see inside a kitchen window or a broken window they need to look inside
your house before reporting as a crime (serious bug), you wouldn't want
the kind of armor-plating that you might want in the 'hood. that doesn't
mean the _need_ for privacy is any different. it's just that in C++ and
the like, you don't trust _anybody_, and in CLOS you basically trust
everybody. the practical result is that thieves and bums use C++ and
nice people use CLOS. :)

| What happens, say, if I create a class and all throughout my code I set
| one of it's slots with setf, then later in the development I decide that
| that slot will not be an actual slot, but derived from several other
| slots and now just merely a method.

I infer from this that you would use SLOT-VALUE. the :READER and :WRITER
and :ACCESSOR options in DEFCLASS automatically create methods for you,
so you don't have use SLOT-VALUE (although those methods will effectively
do just that). there is no difference between such a method and any
other method.

| Do I have to go all throughout my program and change the setf's into
| method calls?

presuming you don't use SLOT-VALUE directly: no, you define a SETF method
for the accessor method that does the right thing, and recompile the
callers.

#:Erik
--
Support organized crime: use Microsoft products!

Aaron Gross

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Erik Naggum <cle...@naggum.no> writes:

I think you're giving C++ a bum rap here. The class definitions are
conventionally put in .h files which the user has access to. Thus a
user can easily change private data to public. Stroustrup emphasized
in _The C++ Language_ that the "private" keyword is meant to protect
against *unintentional* trespassing, and that it doesn't do anything
to stop a programmer from knowingly modifying private data. So the
correct analogy would be a fence around the house with a gate that was
closed, but not locked.

Regarding your claim that CLOS's policy of trust is OK, it seems the
most obvious and convincing argument for a new CLOS programmer would
be empirical: "In my experience developing and maintaining x amount of
CLOS code, I've never seen a problem caused by this policy."

Erik Naggum

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

* Aaron Gross

| I think you're giving C++ a bum rap here. The class definitions are
| conventionally put in .h files which the user has access to. Thus a user
| can easily change private data to public.

well, yeah, at the cost of a system recompile, and you have be _very_
careful not to change the order of the members as C++ is so ill-designed
as to require memory layout to follow specification order. technically,
you can use the access specifier in front of every individual member, but
people tend to sort the members based on access rights. in particular, I
have never seen code in any textbook on C++ where the access specifier is
repeated or applied specifically to an individual member -- they are
always used only once, as sort of "headers", and the message is clear
from other sources, as well: don't _do_ that. so I'd say that a whole
culture is speaking against your "just change it" policy.

| Stroustrup emphasized in _The C++ Language_ that the "private" keyword is
| meant to protect against *unintentional* trespassing, and that it doesn't
| do anything to stop a programmer from knowingly modifying private data.

I don't think this can be true. I would, however, have believed it if
access violations were specified to be warnings, not the errors they are.

I have helped salvage a project where people "knew" the layout of C++
classes and were afraid to change the .h files because that would mean
many a lost day due to recompiling, so "knowingly modify private data"
through the wonders of pointer arithmetic and casting is such as horribly
bad "solution" to the problem that I would consider asking the police to
put a detail on programmers who do it -- they're likely to break the law
through blatant disregard in real life, too.

| So the correct analogy would be a fence around the house with a gate that
| was closed, but not locked.

really? this sounds more like you're on Bjarne's defense team than an
honest argument. how do you open the gate and get at something inside?
your analogy strongly implies that there is a mechanism to open gates,
but what you actually have to do is go away elsewhere and declare the
object to outside your gate, then rebuild the world so it is. when your
gate doesn't have an "open" method, who cares whether it's locked or not
as long as you have to tear the whole fence down to pass through it?

| Regarding your claim that CLOS's policy of trust is OK, it seems the most
| obvious and convincing argument for a new CLOS programmer would be
| empirical: "In my experience developing and maintaining x amount of CLOS
| code, I've never seen a problem caused by this policy."

this is a good point. I must have designed and implemented 20 times as
many classes in CLOS as I have in C++, but I have always had some sort of
problems with the access rights in C++ as uses and designs change over
time, and I have _never_ had any desire to control access in CLOS. now,
I don't claim to be typical. for more than a year after first exposed to
C++ in a six-month project, I was actively considering another career
because C++ was becoming the required language and I couldn't stomach the
monumental waste of human resources that this language requires of its
users and projects. the problem is not just one of pragmatics, however.

C++ is philosophically and cognitively unsound as it forces a violation
of all known epistemological processes on the programmer. as a language,
it requires you to specify in great detail what you do not know in order
to obtain the experience necessary to learn it. C++ has taken premature
optimization to the level of divine edict since it _cannot_ be vague in
the way the state of the system necessarily is. (I'm not talking about
totally vague, but about the kind of vague details that programmers are
supposed to figure out even after a good design has been drawn up.) in
other words, a C++ programmer is _required_ by language design to express
certainty where there _cannot_ be any. a C++ programmer who cares about
correctness is a contradiction in terms: correctness is a function of
acquired certainty, not random guesswork. I'm discounting the ability to
experiment with something through educated guesses, because the number of
issues that must be experimented with in this fashion is gargantuan in
any non-trivial piece of code. C++ is a language strongly optimized for
liars and people who go by guesswork and ignorance. I cannot live with
this. I especially cannot live with it when I cannot even ask for help
in maintaining the uncertainty I have. e.g., if I do not have enough
foreknowledge to know _exactly_ which type I need for a variable (and
there is no type hierarchy, so I cannot be vague), I must _guess_, which
is bad enough, but I have to _repeat_ the guess all over! I cannot say
"this thing here has the _same_ type as that thing over there, and I'd
rather you go look there because I just want to put down my guesses once"
-- there is no `typeof' operator and it certainlycannot be used in those
anal-retentive declarations to afford a limited form of type propagation.

I actually think C++ is ideal only for programmers without any ethics.
you must lie, you are encouraged to declare your private stuff and keep
the cards very closely to your breast, but if you need access, you just
go ahead and change other people's class definitions. the "improved"
strong typing is designed to cause errors if you make simple mistakes,
forcing you to use a lot more of your brain on remembering silly stuff,
but then you get to templates and all hell breaks loose because suddenly
you have _no_control_at_all_ over where things fly. when I wrote that
C++ and CLOS is a question of what kind of people you wish to live with
in your community, I was not _just_ making an analogy. one can only
imagine what having to lie to your compiler _every_ day and to make
unwarranted guesses that your colleagues will depend on the same way they
depend on your hard-earned knowledge _does_ to a human brain -- I know I
couldn't handle even the prospect of it.

and, no, the solution is _not_ to design everything on paper first, then
implement, although this is the way that C++ would actually have worked
out well -- if it were _possible_ to design like that in our world. all
experience has taught us that solving a complex problem uncovers hidden
assumptions and ever more knowledge, trade-offs that we didn't anticipate
but which can make the difference between meeting a deadline and going
into research mode for a year, etc. if C++ were used only to solve
_known_ problems with _known_ solutions, it would be a perfectly OK
language. smart people would design classes "once and for all" and sell
them like nuts and bolts, companies could pre-fabricate parts that fit
together because of industry consensus on standards and specifications,
and this age-old "dream" of some software engineers. I believe this is a
completely insane view of programming, but C++ cannot have any other --
it is _designed_ to be an "ex post facto language" -- most bad languages
are, because the desire to make things solid and predictable, especially
if they can never be, is so deeply ingrained in people they have to work
hard with the concept of dynamism. so people are now arguing in terms of
"patterns", _new_ code that conforms to "general design principles", and
which consequently doesn't fit with the other parts unless specially
designed to. more and more, people see that solving _any_ problem is a
question of acquiring knowledge and having respect for the cognitive and
epistemological processes involved in the human brain: use what you know,
learn what you can, and if you have to guess, be _aware_ that you do so
you can go back and update your guesses when you (hopefully) learn more.

do I give C++ a bum rap? I may well do, but I hope I can illuminate what
choice of language does to the human cognitive process: people who come
from the C++ camp are positively obsessed with protecting their data --
even to the point of being scared when they can't. are they paranoid? I
think have _become_ paranoid because C++ makes you go nuts if you don't
-- it's a natural, psychological defense mechanism against criminally bad
language design: the flip side of having to feign certainty about your
guesses is that you lose confidence in your real certainty, too. when
anything you decided in the past can be overturned without warning just
because some other random guesswork somewhere turnes out to be false, you
learn to be defensive. C++ _needs_ encapsulation and all this privacy
stuff because the whole language is _systematically_ and _fundamentally_
sloppy, and thus attract programmers (and managers) who don't care one
way or the other about it. but, hey, the very _existence_ of Microsoft
would have been _impossible_ without systematic and pervasive sloppiness,
carelessness and outright lies, so it's kinda hard to argue against those
vices with people who _only_ want a quick buck (which is a vice on its
own, if you ask me).

perhaps I care too much, but I found that I needed to get out of the C++
world _permanently_, and I only turn back to look and study to know mine
enemy. in order to think about difficult and interesting problems, I had
to find languages (and write tools) that allowed me _not_ to think about
all the idiotic problems that C++ forces on everybody, _swamping_ their
cognitive processes and creativity with meaningless minutiae that they
have to lie about to boot. I have succeeded because I knew _exactly_
what I needed to get away from, but that knowledge didn't come for free:
for a few years I was sustaining myself mostly as a writer instead of a
programmer simply because I couldn't do anything worthwhile until I had
figured out why C++ is so rotten, and just _how_ (initially unfathomably)
rotten it really is: C++ turns otherwise good people into paranoid,
insecure prostitutes, and it comes from creating such horrible living
environments for themselves and compounded by trying to explain to
themselves that "it's OK, really". (of course, if you don't think about
such things and never need to explain anything to yourself, if you are of
the kind who "just follow orders", C++ is probably OK for you, which
leads to another label for C++: assembly-line object-oriented language.)

end of rant. happy Lisp hacking!

David Hanley

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Erik Naggum <cle...@naggum.no> wrote:
> well, objects don't do any tinkering to begin with, they just are, so
> let's presume you meant that some _code_ somewhere "tinkers" with some
> object's "private" data.

> however, if you think it is "wrong" to do something, then you just don't
> do that. if you want the compiler to smack you in the face if you do it
> anyway, I'd say you have an attitude problem that needs readjustment
> before you resume writing code.

I agree with you as far as writing small programs for oneself goes,
but there's more to it than that. A lot of progrgramming is done either
in large groups, or by one programmer after another on the same project.
In these cases, it's nice to be able to say "don't mess with this, you'll
hurt yourself." In our project, we pass out object that others, if they
were to mess with, would make our module behave badly. So we don't
give them write access, we preserve our elegant design, and everyone's
happy.

> some purportedly object-oriented languages are designed specifically for
> people who love to be smacked in the face when they lie to the compiler.

You could also look at it as "they smack those who break the rules
established by the objects (invariances) so those who use them correctly
and those who have to debug them don't suffer." In a group project you
might be happy for such discipline.

> question of policy that you find paralleled in communities everywhere:
> whether to use armed guards with Rotweilers to whom you have to declare
> people to be your friends, whether to fence yourself in but just lock the
> gates, whether to have open access and everybody just keeps an eye on it
> all, or whether to let giant open areas be accessible to the public as
> long as they behave well.

You could look at it that way. I prefer the road analogy. By
driving on the correct side of the road, stopping at stoplights, and
driving correctly, we all get to where we're going faster, because we
don't have to drive 10MPH and stop at every intersection to avoid an
accident. Yes, if the roads were empty, I could get there faster by blowing
every light, driving the wrong side of the road, but that's not reality.

dave

Francis Leboutte

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Barry Margolin <bar...@bbnplanet.com> wrote:

>In article <6il6rv$2...@desire.lavielle.com>,
>Rainer Joswig <jos...@lavielle.com> wrote:
>>Ask five OO-experts for their definition of OO-ness. You will get atleast
>>six answers. Most people know only about a message-passing version.
>
>Sometime around 1991 or so, I think there was an article in SIGPLAN Notices
>or LISP Pointers that evaluated CLOS with respect to a well-known set of
>criteria for OO language features (I think they were from OO bigwig like
>Booch). Except for the information hiding features (which the article
>admitted could be done somewhat with packages), it scored reasonably well.

Some people at Gartner Group surely will agree with you. According to one
of their research notes (Dec. 6, 1993), CLOS is the only language that
meets all must-have and should-have criteria for object-oriented languages.
--
Francis Leboutte
f.leb...@skynet.be lebo...@acm.org http://users.skynet.be/algo
Marre du courrier non sollicité (spam)? Visitez http://www.cauce.org

Barry Margolin

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

In article <31033186...@naggum.no>, Erik Naggum <cle...@naggum.no> wrote:
> well, objects don't do any tinkering to begin with, they just are, so
> let's presume you meant that some _code_ somewhere "tinkers" with some
> object's "private" data.

Of course, this is one of the primary reasons why many people don't think
CLOS is OO. Most of Object-Oriented programming is based on the idea of
active objects, which tinker with their own innards and interact with other
objects solely by sending messages, so that those objects can then tinker
with their own innards and send messages, and so on.

CLOS doesn't implement this OO paradigm. We chose to focus on the aspects
of OO programming related to class hierarchies, and CLOS's features in that
area are virtually unsurpassed. Method combination is one of the most
powerful features of CLOS, yet it's practically unique in the OO universe
(although I can't think of any reason why the built-in method combinations
couldn't easily be included in most other OO languages, even C++, rather
than always requiring overriding methods to call the superclass method
explicitly).

Perhaps we should have stopped referring to CLOS as Object-Oriented when we
switched from method passing and active objects to generic functions and
multimethods. A better term for CLOS might be Class-Oriented or
Class-Based.

Vassil Nikolov

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

On Mon, 4 May 1998 22:15:43 -0700,
Aaron Gross <aa...@morannon.bfr.co.il> wrote in comp.lang.lisp:

>I think you're giving C++ a bum rap here. The class definitions are
>conventionally put in .h files which the user has access to. Thus a

>user can easily change private data to public. (...)

Even if you only have access to the compiled code?
And if you just make public what was private, can you
be sure that nothing will be broken, with C++'s
complicated rules regarding private/public and inheritance?

* * *

I think that the really good thing about Common Lisp (including
CLOS) is that it gives you _full_choice_; you can:

(A) leave everything accessible (the door is open), or
(B) set things up so that there are just warnings on access, or
(C) set things up so that access is denied (the door is locked).

Yes, (B) and (C) require some effort (see note below), but
then nothing is free. While C++ offers you (A) and (C),
I don't think it offers you (B).

As to tresspassing and protection against it, I don't
care about other programmers tresspassing. If they
use my code, and tresspass, it's their responsibility.
What I want is the _option_ to be notified (not necessarily
smacked in the face, to borrow Erik Naggum's phrase)
if I tresspass myself, which option I would turn on
when I am absent-minded or whatever.

Note: to show that (B) and (C) are achievable (if that is
not already evident), consider, as just one possible
approach, defining a before method for SLOT-VALUE which
signals a warning (for (B)) or an error (for (C)) if
a slot is accessed without invoking the appropriate
accessor. The accessor can notify the SLOT-VALUE
method by setting a variable, which may be shared by
the two in a lexical closure (thus inaccessible to
anybody else).


Best regards,
Vassil.


Vassil Nikolov

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Rainer Joswig

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

In article <1998050516474...@nym.alias.net>, "Vassil Nikolov"
<vnik...@math.acad.bg> wrote:

> Note: to show that (B) and (C) are achievable (if that is
> not already evident), consider, as just one possible
> approach, defining a before method for SLOT-VALUE which
> signals a warning (for (B)) or an error (for (C)) if
> a slot is accessed without invoking the appropriate
> accessor. The accessor can notify the SLOT-VALUE
> method by setting a variable, which may be shared by
> the two in a lexical closure (thus inaccessible to
> anybody else).

How do you do that? Isn't SLOT-VALUE an ordinary function
(not a generic function)?

--
http://www.lavielle.com/~joswig/


Mike McDonald

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

In article <6in7tp$erh$1...@eve.enteract.com>,

David Hanley <ma...@enteract.com> writes:
> Erik Naggum <cle...@naggum.no> wrote:
>> well, objects don't do any tinkering to begin with, they just are, so
>> let's presume you meant that some _code_ somewhere "tinkers" with some
>> object's "private" data.
>
>> however, if you think it is "wrong" to do something, then you just don't
>> do that. if you want the compiler to smack you in the face if you do it
>> anyway, I'd say you have an attitude problem that needs readjustment
>> before you resume writing code.
>
> I agree with you as far as writing small programs for oneself goes,
> but there's more to it than that. A lot of progrgramming is done either
> in large groups, or by one programmer after another on the same project.
> In these cases, it's nice to be able to say "don't mess with this, you'll
> hurt yourself." In our project, we pass out object that others, if they
> were to mess with, would make our module behave badly. So we don't
> give them write access, we preserve our elegant design, and everyone's
> happy.

The basic assumption with "protection" is that the
user is too stupid to be trusted with not breaking
the object. If this assumption is true (and there's
plenty of evidence to support that in general) then
the solution is not "protection", it taking the
keyboards away from the idiots and let your skilled
employees lose. Don't cripple the skilled individuals
in the name of hordes of idiots.

Mike McDonald
mik...@mikemac.com


Mike McDonald

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

In article <31033568...@naggum.no>,

Erik Naggum <cle...@naggum.no> writes:
> * Aaron Gross
>| I think you're giving C++ a bum rap here. The class definitions are
>| conventionally put in .h files which the user has access to. Thus a user
>| can easily change private data to public.
>
> well, yeah, at the cost of a system recompile, and you have be _very_
> careful not to change the order of the members as C++ is so ill-designed
> as to require memory layout to follow specification order.

In my experience using C++, if you didn't do a
complete recompile every couple of hours, you were
asking for trouble. Trying to figure out what the
heck is going wrong when some class definition got
changed but some code that uses that class didn't get
recompiled is a nightmare. I also think you should
recompile your C++ code with different compilers as
often as you can. That helps you avoid introducing
wierd compiler dependancies.


>| So the correct analogy would be a fence around the house with a gate that
>| was closed, but not locked.
>
> really? this sounds more like you're on Bjarne's defense team than an
> honest argument. how do you open the gate and get at something inside?
> your analogy strongly implies that there is a mechanism to open gates,
> but what you actually have to do is go away elsewhere and declare the
> object to outside your gate, then rebuild the world so it is. when your
> gate doesn't have an "open" method, who cares whether it's locked or not
> as long as you have to tear the whole fence down to pass through it?

And why are your "privates" hanging out for the
whole world to see anyway? (Philosophical question, I
know the technical reason.)

>| Regarding your claim that CLOS's policy of trust is OK, it seems the most
>| obvious and convincing argument for a new CLOS programmer would be
>| empirical: "In my experience developing and maintaining x amount of CLOS
>| code, I've never seen a problem caused by this policy."
>
> this is a good point. I must have designed and implemented 20 times as
> many classes in CLOS as I have in C++, but I have always had some sort of
> problems with the access rights in C++ as uses and designs change over
> time, and I have _never_ had any desire to control access in CLOS. now,
> I don't claim to be typical. for more than a year after first exposed to
> C++ in a six-month project, I was actively considering another career
> because C++ was becoming the required language and I couldn't stomach the
> monumental waste of human resources that this language requires of its
> users and projects. the problem is not just one of pragmatics, however.

From your writing, I think you probably are an
atypical programmer, definitely an atypical C++
programmer. For one thing, you care! In my
experience, most programmers don't care. It's just a
job to them. It sounded better than flipping burgers
but that's all. I too have been giving serious
consideration to finding another career. Dealing with
a world designed for idiots has me worn down.

> and, no, the solution is _not_ to design everything on paper first, then
> implement, although this is the way that C++ would actually have worked
> out well -- if it were _possible_ to design like that in our world. all
> experience has taught us that solving a complex problem uncovers hidden
> assumptions and ever more knowledge, trade-offs that we didn't anticipate
> but which can make the difference between meeting a deadline and going
> into research mode for a year, etc. if C++ were used only to solve
> _known_ problems with _known_ solutions, it would be a perfectly OK
> language.

Oh how I wish you could talk to my boss! He's
suppose to be a relatively enlightened guy. He got
his degree from MIT and all. (He didn't know that
Lisp had arrays though! How can I explain something
like CLOS to a guy like this?) Inorder to keep things
under control, our company (and group) have a
developement process. We write a spec, have marketing
approve it. Then we write the design doc and have
marketing approve that. Then we spend 8 weeks
implementing it and have marketing approve it. The it
goes to our beta customers for 6 months so we can
kludge it up to do what they really wanted in the
first place! Oh and we have our choice of three
languages to use for the implementation, C++, Perl,
or TCL. I'm currently stuck on the "design" portion
of the spec. I'm totally bummed since I know it's BS.
The whole project would take a couple of weeks in
CLOS and then we could get right to finding out what
the customers really wanted. But no, gotta follow the
process!


> perhaps I care too much, but I found that I needed to get out of the C++
> world _permanently_, and I only turn back to look and study to know mine
> enemy.

Caring is definitely a no no in this "profession".

>
> end of rant. happy Lisp hacking!
>
> #:Erik

If only it were so! Back to kludging C++/TCL for
me.

Mike McDonald
mik...@mikemac.com


Dan Higdon

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Mike McDonald wrote in message ...

> The basic assumption with "protection" is that the
>user is too stupid to be trusted with not breaking
>the object. If this assumption is true (and there's
>plenty of evidence to support that in general) then
>the solution is not "protection", it taking the
>keyboards away from the idiots and let your skilled
>employees lose. Don't cripple the skilled individuals
>in the name of hordes of idiots.


Of course, you could look at it this way: protection
allows you to declare what you do and don't want to
be able to do with a design. This spec allows the
compiler to catch your errors (logic errors in either
the original design or your code) much like a strongly
typed language catches value errors. Of course, I
don't expect Lisp programmers to really dig this sort
of thing, given the general hostility to strong type
checking one usually sees around here. :-)

As far as "hordes of idiots", I suppose you've never
made a semantic typo? (Accidentally used the wrong
variable/function.) I know I've had a number of bugs
pointed out to me by my compiler (better under SML
and such than C++, to be sure). Most humans make
mistakes, and it's occasionally nice to have the compiler
point them out to you.

Still, I have to agree with you that programmers who
don't care about their jobs shouldn't be allowed to
drag down those of us who do care, and want to
use appropriate tools for the tasks at hand.

----------------------------------------
hd...@charybdis.com
"Throwing fire at the sun"

Gavin E. Gleason

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

> Of course, you could look at it this way: protection
> allows you to declare what you do and don't want to
> be able to do with a design. This spec allows the

I don't think I've been able to bend my mind around this
problem. Why is it that :: is a problem but *dyn-var*
isn't? I mean with a group of people who are not complete
morons it seem like you could get your co-workers to ask
you why you didn't export a symbol befor they went and
used it.

Scott L. Burson

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Mike McDonald wrote:
> Oh how I wish you could talk to my boss! He's
> suppose to be a relatively enlightened guy. He got
> his degree from MIT and all. (He didn't know that
> Lisp had arrays though! How can I explain something
> like CLOS to a guy like this?)

Harrumph. *When* did he get his degree from MIT? If it was after 1978
or so, he has no excuse for his ignorance.

> In order to keep things


> under control, our company (and group) have a

> development process. We write a spec, have marketing


> approve it. Then we write the design doc and have
> marketing approve that. Then we spend 8 weeks
> implementing it and have marketing approve it.

Oh boy, the waterfall model!

> Then it


> goes to our beta customers for 6 months so we can
> kludge it up to do what they really wanted in the
> first place! Oh and we have our choice of three
> languages to use for the implementation, C++, Perl,
> or TCL.

Oh dear, you *are* in Hell.

See if you can talk your boss into letting you use Java. This shouldn't
be too hard -- it's very trendy. And it will be a much better language
to work in than any of the above.

> I'm currently stuck on the "design" portion
> of the spec. I'm totally bummed since I know it's BS.
> The whole project would take a couple of weeks in
> CLOS and then we could get right to finding out what
> the customers really wanted.

I suggest you at least try to explain to your boss that you should be
doing in-depth interviews with the customers *before* writing the
design. This shouldn't be too hard to justify on the basis that it will
likely shorten the beta period.

Even the waterfall model needs some water (information) coming in at the
top.

-- Scott (MIT 1980)

* * * * *

To use the email address, remove all occurrences of the letter "q".

Sunil Mishra

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Yes, it is. The AMOP has slot-value call slot-value-using-class, which is a
generic function.

But even if it were generic, I still don't see how the above proposal would
work. The function slot-value has to operate for any number of classes (and
subclasses) of any given class. If you want a private slot in the sense of
C++, then the slot should not be shared with children of the class. So, if
a child redefines the slot to have an accessor, then the new accessor will
no longer share the lexical closure, and I believe in this situation you
will lose.

Sunil

Kevin Haddock

unread,
May 5, 1998, 3:00:00 AM5/5/98
to

Erik Naggum wrote:
>
> * Kevin Haddock
*snip*

(my comment about tinkering with private data)

> however, if you think it is "wrong" to do something, then you just don't
> do that. if you want the compiler to smack you in the face if you do it
> anyway, I'd say you have an attitude problem that needs readjustment
> before you resume writing code.

Well, I'm not saying that it should be impossible. I mean sometimes one
might *have* to do it for performance reasons. But perhaps it should be
somewhat difficult (e.g. prepending an underscore or something)

(Eric's comments about compiler rigor)

> that doesn't
> mean the _need_ for privacy is any different. it's just that in C++ and
> the like, you don't trust _anybody_, and in CLOS you basically trust
> everybody. the practical result is that thieves and bums use C++ and
> nice people use CLOS. :)

Yes, I can see that. And I greatly appreciate all the responses I got
to my question!

(And BTW, I pretty much hail from the Forth community. C++ makes me
wretch)

-Kevin

Espen Vestre

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

Barry Margolin <bar...@bbnplanet.com> writes:

> CLOS doesn't implement this OO paradigm. We chose to focus on the aspects
> of OO programming related to class hierarchies, and CLOS's features in that
> area are virtually unsurpassed.

Surpassed only by those CLOS implementations which implement the
MOP :-)

--

(espen vestre)

Espen Vestre

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

smi...@piedmont.cc.gatech.edu (Sunil Mishra) writes:

> Yes, it is. The AMOP has slot-value call slot-value-using-class, which is a
> generic function.
>
> But even if it were generic, I still don't see how the above proposal would
> work. The function slot-value has to operate for any number of classes (and
> subclasses) of any given class.

So you need to use the MOP and implement a meta-class, along these
lines:

(defclass my-meta (standard-class)
())

(defmethod slot-value-using-class :before ((class my-meta) instance slot-name)
(when (hidden-in-class class slot-name)
(error "Attempt to access hidden slot")))

(I guess the most elegant way to implement "hidden-in-class" would be
to subclass the slot-definition metaclass....?)
--

(espen)

Tim Bradshaw

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

* Vassil Nikolov wrote:

> Note: to show that (B) and (C) are achievable (if that is
> not already evident), consider, as just one possible
> approach, defining a before method for SLOT-VALUE which
> signals a warning (for (B)) or an error (for (C)) if
> a slot is accessed without invoking the appropriate
> accessor. The accessor can notify the SLOT-VALUE
> method by setting a variable, which may be shared by
> the two in a lexical closure (thus inaccessible to
> anybody else).

I think this is a bad approach actually, because any implementation
worth its salt is going to optimise SLOT-VALUE into the ground, so
defining methods on it (or on SLOT-VALUE-USING-CLASS) is kind of a bad
thing to do.

Although I can't remember the details, it did seem to me that AMOP
really requires SLOT-VALUE to call SLOT-VALUE-USING-CLASS, which
strikes me as a ludicrous limitation on implementations which one
shouldn't assume they actually adhere to.

--tim

Kjetil Valstadsve

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

Espen Vestre <e...@nextel.no> writes:

> So you need to use the MOP and implement a meta-class, along these
> lines:
>
> (defclass my-meta (standard-class)
> ())
>
> (defmethod slot-value-using-class :before ((class my-meta) instance
> slot-name)
> (when (hidden-in-class class slot-name)
> (error "Attempt to access hidden slot")))
>
> (I guess the most elegant way to implement "hidden-in-class" would be
> to subclass the slot-definition metaclass....?)

Sounds like a MOP thing, definitely. How would you put it to use?
Ie. what's the most practical way to make certain slots of a my-meta
class hidden?

I've studied the MOP spec here now, and found that I can override
DIRECT-SLOT-DEFINITION-CLASS (which returns the slot-definition class
for a given slot) for my-meta classes and look for keywords in the
&rest'ed arguments (representing, it seems, keywords in the
slot-definition form within the defclass form). Then, I can specify
that extra keyword (for instance, :hidden) in the defclass form and
get away with it, something like this: (I use the keyword :my-slot,
below, not :hidden)

(defclass my-meta (standard-class) ())

(defclass my-slot-definition (standard-direct-slot-definition) ())

(defmethod clos:direct-slot-definition-class ((class my-meta) &rest initargs)
(print "yikes!")
(if (member :my-slot initargs)
(progn
(print "hubba!")
(class-of (make-instance 'my-slot-definition))) ;; <- *blush*
;; I momentarily forgot how to specify classes
;; directly, and mr. Naggum was asleep at the time.
(call-next-method)))

Usage:

[4c] USER(26): (defclass my-class ()
((my-slot :my-slot))
(:metaclass my-meta))
"yikes!"
"hubba!"
Error: Recursive loop in finalize-inheritance
#<STANDARD-CLASS MY-SLOT-DEFINITION>

... oops, with some hitches, admittedly, but would this be a good way
to go about it, given some time to iron out the glitches? I'm a CLOS
newbie, so be gentle.

--
We are looking for people who sincerely want to rule the universe. Have
you got what it takes to be an evil galactic tyrant? Please tick one [X]
[ ] I am slightly naughty [ ] I am actually quite evil
[ ] I am very naughty indeed [ ] I am so evil that I am going to quote
your entire post after my own gibberish

Joao Cachopo

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

>>>>> "Vassil" == Vassil Nikolov <vnik...@math.acad.bg> writes:

Vassil> Note: to show that (B) and (C) are achievable (if that is not
Vassil> already evident), consider, as just one possible approach,
Vassil> defining a before method for SLOT-VALUE which signals a
Vassil> warning (for (B)) or an error (for (C)) if a slot is accessed
Vassil> without invoking the appropriate accessor. The accessor can
Vassil> notify the SLOT-VALUE method by setting a variable, which may
Vassil> be shared by the two in a lexical closure (thus inaccessible
Vassil> to anybody else).

Others have pointed out the problems with these approaches.

However, I feel there is something I do not fully understand, and that
is related to a message I sent a few days ago but that nobody
followed-up.

It seems that some people are deeply worried with private slots and
the way that they are accessed in CLOS. But I can't see what's the
use for private slots that nobody can manipulate, since in CLOS
OO-paradigm there are no "class-owned methods". Therefore, I assume
that the problem is in the use of the slot-value function (or
with-slots).

Indeed, I think that writing code relying in slot-names (through the
use of slot-names or with-slots) is not a "good thing", and that
accessors should be used instead.

This leads me to my question: why use slot names at all?

I know that the use of slot names allow you to do things like:

1. Inherit several (distinct) initargs for the same slot.
2. Inherit several (distinct) accessors for the same slot.
3. Constrain further the type of an inherited slot.
4. Specify an initform for an inherited slot.
5. [ Possibly many other things... ]

But, is it worth it?
I mean, are these things really useful?
I ask this because I do not have much experience with CLOS programming
in the large...

As I see it (maybe naively), those who do not like access to a slot
unless through its accessors (which I agree is the right way to do it,
because you can add methods to the corresponding generic functions),
should not use slot names at all.

Slot names are not optional in slot definitions, of course, but using
gensyms you get pretty much the same effect, isn't it?

Either

(defclass a ()
((#.(gensym) :accessor property1)))

or

(defclass a ()
((#:property1 :accessor property1)))

Should do.

Am I right?

--
Joao Cachopo * Homepage: http://www.gia.ist.utl.pt/~jcachopo

*** Murphy was an optimist ***

Sunil Mishra

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <w63eend...@gromit.nextel.no> Espen Vestre <e...@nextel.no> writes:

So you need to use the MOP and implement a meta-class, along these
lines:

(defclass my-meta (standard-class)
())

(defmethod slot-value-using-class :before ((class my-meta) instance slot-name)
(when (hidden-in-class class slot-name)
(error "Attempt to access hidden slot")))

(I guess the most elegant way to implement "hidden-in-class" would be
to subclass the slot-definition metaclass....?)

--

(espen)

If you are going to use the MOP to implement slot access control, I believe
AMOP has a good example of that too. And I think they do subcalss the slot
definition class, as you have suggested.

Sunil

Antonio Leitao

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

>>>>> "Joao" == Joao Cachopo <jcac...@gia.ist.utl.pt> writes:

[...]

Joao> It seems that some people are deeply worried with private
Joao> slots and the way that they are accessed in CLOS. But I
Joao> can't see what's the use for private slots that nobody can
Joao> manipulate, since in CLOS OO-paradigm there are no
Joao> "class-owned methods". Therefore, I assume that the problem
Joao> is in the use of the slot-value function (or with-slots).

Joao> Indeed, I think that writing code relying in slot-names
Joao> (through the use of slot-names or with-slots) is not a "good
Joao> thing", and that accessors should be used instead.

That is definitely true, but for a large number of people that made
the transition from other Object-Oriented languages to CLOS,
multi-dispatch methods is something that they use rarely. Mostly, they
will map the idea of methods defined in a class into a CLOS method
specialized in just one argument. Then, they will want to access the
"instance variables" of the class as if the method was part of the
class. Then, they will discover that they must precede the method body
by a with-slots form specifying all the slots they need, meanwhile
complaining about such strange obligation. Finally, they will
understand that there is nothing special about a with-slots form (or
slot-value) and that everybody can use it from any place, so they
complain that there is no privacy in CLOS. All of this results, of
course, from the belief that a method in CLOS is like a method in
other languages, and should have privileged rights. I bet that as
soon as they start using multi-dispatch methods all these
misconceptions disappear.

Now, I would like to add a related topic, namely the use of structures
(a la defstruct). When we use a defstruct, we get automatically
defined accessors and we simply use those accessors to manipulate the
structure. We know that an "instance" of a defstruct is just a vector,
so we can access the slots using aref. What surprises me is that no
one complains that there is no privacy in a defstruct. Besides, when
we think that we can use (single) inheritance in structures, then I
don't see much difference between accessing the "instance" of a
defstruct using aref or accessing the "instance" of a defclass using
slot-value.

As a result, I would suggest that slot-value is to defclass the
same as aref is to defstruct. Of course, the fact that slot-value uses
a symbol while aref uses a number makes a big difference, and it
entitles people to think that slot-value is more legitimate than
aref. But from the point of view of a system that must evolve as time
goes by, using a slot-value is almost as dangerous as using an aref
because we might have to decide that a specific value that was kept in
a slot will instead have to be computed and then it is too late because
all the code is using slot-value and not the proper accessor.

Joao> This leads me to my question: why use slot names at all?

Joao> I know that the use of slot names allow you to do things
Joao> like:

Joao> 1. Inherit several (distinct) initargs for the same slot.
Joao> 2. Inherit several (distinct) accessors for the same slot.
Joao> 3. Constrain further the type of an inherited slot.
Joao> 4. Specify an initform for an inherited slot. 5. [ Possibly
Joao> many other things... ]

Joao> But, is it worth it? I mean, are these things really
Joao> useful? I ask this because I do not have much experience
Joao> with CLOS programming in the large...

In my opinion, they are very useful. I would paraphrase your
question in a different way: why use slot-value at all?

Why not just resort exclusively to accessors, maybe allowing for some
kind of optimization where they are inlined as slot-value? Then you
would have an accessor that behaved like a slot-value without the
overhead of going through a generic function. I don't remember whether
this is not already possible in CLOS. Maybe it is.

The idea is to convince the programmer that using slot-value will not
give him anything that a proper optimization couldn't give. Just like it
happens with defstruct. We don't use aref because we know that it can't
be faster than the accessor when it is compiled with proper optimization.
And for people who like to look at slots as "instance variables", then
we already have the powerful with-accessors. The only problem is
that, contrary to what happens with defstruct, there is no automatic
creation of accessors. By default, no accessors are created. We should
change this.

Joao> As I see it (maybe naively), those who do not like access to
Joao> a slot unless through its accessors (which I agree is the
Joao> right way to do it, because you can add methods to the
Joao> corresponding generic functions), should not use slot names
Joao> at all.

Even if you don't want to add methods to the corresponding generic
function, you shouldn't use slot-value. You might want to change that
slot and then you must check all the code. A function is much more
"stable" than a slot.

Joao> Slot names are not optional in slot definitions, of course,
Joao> but using gensyms you get pretty much the same effect, isn't
Joao> it?

Joao> Either

Joao> (defclass a () ((#.(gensym) :accessor property1)))

Joao> or

Joao> (defclass a () ((#:property1 :accessor property1)))

Joao> Should do.

Joao> Am I right?

I think so, but it looks ugly. I don't we just use automatic defined
accessors, a la defstruct, with some automatic optimizations
included?

António Menezes Leitão.


Vassil Nikolov

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

On Tue, 5 May 1998 14:07:08 -0700,
Sunil Mishra <smi...@piedmont.cc.gatech.edu> wrote in comp.lang.lisp:


> In article <1998050516474...@nym.alias.net>, "Vassil Nikolov"
> <vnik...@math.acad.bg> wrote:
>

> > Note: to show that (B) and (C) are achievable (if that is

> > not already evident), consider, as just one possible
> > approach, defining a before method for SLOT-VALUE which
> > signals a warning (for (B)) or an error (for (C)) if
> > a slot is accessed without invoking the appropriate
> > accessor. The accessor can notify the SLOT-VALUE
> > method by setting a variable, which may be shared by
> > the two in a lexical closure (thus inaccessible to
> > anybody else).
(...)
>But (...) I still don't see how the above proposal would


>work. The function slot-value has to operate for any number of classes (and

>subclasses) of any given class. If you want a private slot in the sense of

^^^^^^^^^^^^^^^^^^^^^^^^^^ ... see note 1


>C++, then the slot should not be shared with children of the class. So, if
>a child redefines the slot to have an accessor, then the new accessor will

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ see note 2


>no longer share the lexical closure, and I believe in this situation you
>will lose.

With any particular approach there are conditions under which
one loses. Perhaps I should have made it explicit that I wasn't
offering a general solution, just an approach which may or may
not be useful in the particular situation that the programmer
has at hand.

(note 1) Besides, I don't want a private slot in the sense of C++.
I just want a means whereby I could have CLOS notify me if an accessor
was bypassed and SLOT-VALUE was used directly, which may or may
not be with good reason. (Hence `notify,' not `block.')

(note 2) If the definition of a subclass redefines accessors for a slot,
it it the responsibility of the maker of that definition
whether or not to extend the scope of the notification mentioned
above. Certainly I don't want to impose undue restrictions on
those that want to subclass my classes; they are supposed to
know what they are doing!

Finally, there are other possibilities: CLOS doesn't give you
_the_ direction to follow, but a number of them (yes, that
makes life difficult: decisions must be taken...). Espen
Vestre already mentioned one could use MOP (that's what it
is for, after all). One could also `privatise' slots by
using uninterned symbols for the slot names (I think that
Graham gives such an example, but I know it from hearsay,
haven't seen the book myself), if one really must have it.
And anyway, slots not being private isn't usually the
real problem.

Best regards,
Vassil.


Barry Margolin

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <1998050516474...@nym.alias.net>,
Vassil Nikolov <vnik...@math.acad.bg> wrote:
>On Mon, 4 May 1998 22:15:43 -0700,
>Aaron Gross <aa...@morannon.bfr.co.il> wrote in comp.lang.lisp:
>
>>I think you're giving C++ a bum rap here. The class definitions are
>>conventionally put in .h files which the user has access to. Thus a
>>user can easily change private data to public. (...)
>
>Even if you only have access to the compiled code?
>And if you just make public what was private, can you
>be sure that nothing will be broken, with C++'s
>complicated rules regarding private/public and inheritance?

Actually, C++ got that right. Name resolution takes place independently of
public/private designation. After it resolves the name, it then determines
whether the visibility rules allow the reference. Although this tends to
confuse newbies (and probably even some oldies), it means that making a
member public cannot change the behavior of existing code.

Barry Margolin

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

In article <354F6DA6...@zeta-sqoft.com>,

Scott L. Burson <Gy...@zeta-sqoft.com> wrote:
>See if you can talk your boss into letting you use Java. This shouldn't
>be too hard -- it's very trendy. And it will be a much better language
>to work in than any of the above.

I was speaking to someone last night who's looking to hire someone to
rewrite a Java application in C++, because Java isn't up to snuff yet.

David Hanley

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

Barry Margolin <bar...@bbnplanet.com> wrote:
> In article <354F6DA6...@zeta-sqoft.com>,
> Scott L. Burson <Gy...@zeta-sqoft.com> wrote:
> >See if you can talk your boss into letting you use Java. This shouldn't
> >be too hard -- it's very trendy. And it will be a much better language
> >to work in than any of the above.

> I was speaking to someone last night who's looking to hire someone to
> rewrite a Java application in C++, because Java isn't up to snuff yet.

Maybe they should look into translating it to smalltalk?
I would think that would be less work. For one thing, the java code might
depend a lot on the GC and dynamism.

dave

Scott L. Burson

unread,
May 6, 1998, 3:00:00 AM5/6/98
to

Barry Margolin wrote:
> In article <354F6DA6...@zeta-sqoft.com>,
> Scott L. Burson <Gy...@zeta-sqoft.com> wrote:
> >See if you can talk your boss into letting you use Java. This shouldn't
> >be too hard -- it's very trendy. And it will be a much better language
> >to work in than any of the above.
>
> I was speaking to someone last night who's looking to hire someone to
> rewrite a Java application in C++, because Java isn't up to snuff yet.

Yeah, Mike responded to me privately with similar concerns.

I clearly need to take another look at the Java environment situation --
it's been about 10 months since I did so. I had assumed that we'd be
seeing pretty good environments by now, but I guess we're not. I know
it's a lot of work to build a good environment, but it doesn't seem like
anyone in the Unix world is investing all that much in it, even Sun.

-- Scott

Rainer Joswig

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In article <wog1inw...@antartida.gia.ist.utl.pt>, Antonio Leitao
<a...@antartida.gia.ist.utl.pt> wrote:

> Now, I would like to add a related topic, namely the use of structures
> (a la defstruct). When we use a defstruct, we get automatically
> defined accessors and we simply use those accessors to manipulate the
> structure. We know that an "instance" of a defstruct is just a vector,
> so we can access the slots using aref.

This does work only in your particular implementation of CL
and is not part of ANSI CL.


Welcome to Macintosh Common Lisp Version 4.2!
? (defstruct foo bar)
FOO
? (make-foo :bar 'baz)
#S(FOO :BAR BAZ)
? (aref * 0)
> Error: value #S(FOO :BAR BAZ) is not of the expected type ARRAY.
> While executing: CCL::%AREF1
> Type Command-. to abort.
See the Restarts... menu item for further choices.

--
http://www.lavielle.com/~joswig/


Marco Antoniotti

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

I think there are advantages in both models of "fencing".

What I think makes things a little murky in C++ (CL is murky as well
for totally different reasons) is that the two concepts of "package"
(plug in your favorite synonym) and class (plug in your favorite
synonym) are collapsed. (I am not familiar enough with C++
namespaces, nor do I know how much they are implemented in various
compilers).

Java does it "more" right, by (re)introducing the notion of package.
Ada95 also has some interesting featurs.

Cheers

--
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it

Espen Vestre

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

Marco Antoniotti <mar...@galvani.parades.rm.cnr.it> writes:

> for totally different reasons) is that the two concepts of "package"
> (plug in your favorite synonym) and class (plug in your favorite
> synonym) are collapsed.

In Perl, OO is in fact a hack built upon the package system...

--

(espen)

Erik Naggum

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

* Antonio Leitao

| Now, I would like to add a related topic, namely the use of structures (a
| la defstruct). When we use a defstruct, we get automatically defined
| accessors and we simply use those accessors to manipulate the structure.
| We know that an "instance" of a defstruct is just a vector, so we can
| access the slots using aref.

* Rainer Joswig


| This does work only in your particular implementation of CL
| and is not part of ANSI CL.

well... you can tell DEFSTRUCT you want a vector representation.

#:Erik
--
Support organized crime: use Microsoft products!

Tim Bradshaw

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

* Antonio Leitao wrote:

> Why not just resort exclusively to accessors, maybe allowing for some
> kind of optimization where they are inlined as slot-value? Then you
> would have an accessor that behaved like a slot-value without the
> overhead of going through a generic function. I don't remember whether
> this is not already possible in CLOS. Maybe it is.

At least some implementations optimise the automatically-defined
accessors into something like SLOT-VALUE with a constant slot name,
and then optimise that into something very quick indeed (close to
DEFSTRUCT performance). You may lose if you define auxiliary methods
on the accessors.

It would be interesting to know which implementations optimise this
kind of thing, and how much.

> The idea is to convince the programmer that using slot-value will not
> give him anything that a proper optimization couldn't give. Just like it
> happens with defstruct. We don't use aref because we know that it can't
> be faster than the accessor when it is compiled with proper optimization.
> And for people who like to look at slots as "instance variables", then
> we already have the powerful with-accessors. The only problem is
> that, contrary to what happens with defstruct, there is no automatic
> creation of accessors. By default, no accessors are created. We should
> change this.

It would be easy to write a wrapper around DEFCLASS which looked quite
like DEFSTRUCT and defined the accessors for you (and obfuscated the
slot names if you wanted).

--tim

Bob Hutchison

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

Barry Margolin <bar...@bbnplanet.com> wrote:

>In article <354F6DA6...@zeta-sqoft.com>,
>Scott L. Burson <Gy...@zeta-sqoft.com> wrote:
>>See if you can talk your boss into letting you use Java. This shouldn't
>>be too hard -- it's very trendy. And it will be a much better language
>>to work in than any of the above.
>
>I was speaking to someone last night who's looking to hire someone to
>rewrite a Java application in C++, because Java isn't up to snuff yet.

Any particular problem with Java? More to the point, what's the problem
with Java that C++ is supposed to fix?
---
Bob Hutchison, hu...@RedRock.com, (416) 760-0565
RedRock, Toronto, Canada

Vassil Nikolov

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

On Wed, 6 May 1998 12:50:05 -0700,
Barry Margolin <bar...@bbnplanet.com> wrote in comp.lang.lisp:

>In article <1998050516474...@nym.alias.net>,
>Vassil Nikolov <vnik...@math.acad.bg> wrote:
>>On Mon, 4 May 1998 22:15:43 -0700,
>>Aaron Gross <aa...@morannon.bfr.co.il> wrote in comp.lang.lisp:
>>

>>>(...) a user can easily change private data to public. (...)
>>
(...)


>>And if you just make public what was private, can you
>>be sure that nothing will be broken, with C++'s
>>complicated rules regarding private/public and inheritance?
>
>Actually, C++ got that right. Name resolution takes place independently of
>public/private designation. After it resolves the name, it then determines
>whether the visibility rules allow the reference. Although this tends to
>confuse newbies (and probably even some oldies), it means that making a
>member public cannot change the behavior of existing code.

Thank you for correcting me and for the clarification.
Since you know what you are talking about, I take my
question back. (There are still some things I'd like
to know about C++ in this respect, so I guess I might
RTFM... one day.)

When I think about it, I probably got mixed up with Java's
rules about what gets inherited. I am so lucky I can
afford (at least so far) to have only an academic interest
in these languages.

Best regards, Vassil.


Vassil Nikolov

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

On Wed, 6 May 1998 03:25:07 -0700,
Tim Bradshaw <t...@aiai.ed.ac.uk> wrote in comp.lang.lisp:

(...)


>Although I can't remember the details, it did seem to me that AMOP
>really requires SLOT-VALUE to call SLOT-VALUE-USING-CLASS, which
>strikes me as a ludicrous limitation on implementations which one
>shouldn't assume they actually adhere to.

Here's the speed vs. flexibility trade-off again. X needs the
former, Y needs the latter. Usually one can't have both,
but the good news is that rarely one wants both equally strongly.

By the way, both CLtL2 and the standard (using CLHS as the source)
_recommend_ that the implementation uses SLOT-VALUE-USING-CLASS,
although this is not a requirement for conformance to the standard.

Would it be nice to be able to declare that SLOT-VALUE doesn't
use SLOT-VALUE-USING-CLASS on a particular occasion?
In other words, to give the programmer choice whether to insist
on flexibility or on speed. (Such a declaration would follow
the spirit of the DYNAMIC-EXTENT declaration, I guess.)

Best regards, Vassil.


Lyman S. Taylor

unread,
May 7, 1998, 3:00:00 AM5/7/98
to

In article <3557cdff....@enews.newsguy.com>,
Bob Hutchison <hu...@RedRock.com> wrote:
>Barry Margolin <bar...@bbnplanet.com> wrote:
...

>>rewrite a Java application in C++, because Java isn't up to snuff yet.
>
>Any particular problem with Java? More to the point, what's the problem
>with Java that C++ is supposed to fix?

It is likely not Java, the "Language", that isn't up to snuff. It is the
implementation(s) thereof and the high state of flux of the libraries.

Does the Language C++, do things better than Java? IMHO, For most things,
No. Do the implementations of C++ do many things better than Java? In many
circumstances, yes. Especially, if we're outside the venue of web
browser applets.

For instance, Sun's "super duper" Java optimizer isn't ready for prime
time yet. Most C++ implementaton's optimizers have many more man-years of
work in them.

--

Lyman S. Taylor "Twinkie Cream; food of the Gods"
(ly...@cc.gatech.edu) Jarod, "The Pretender"


Georg Bauer

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

In article <6in7tp$erh$1...@eve.enteract.com>, David Hanley
<ma...@enteract.com> wrote:

> In a group project you
>might be happy for such discipline.

Actually I would be much happier in a group project if everybody
_understood_ what to touch and what not. It's not that it isn't there -
you can always write a comment into the source. It is awkward to build
restrictions into the compiler just because some other people might not be
able to understand what it is all about. I don't like the idea to
transport "behaviour" in the source - it should be in the peoples minds,
already.

The better way would be to throw out the people tinkering with parts of
the objects that they shouldn't tinker with and hire some people instead
that have a clue.

BTW: people that would tinker with foreign objects in an open environment
will do things like that in a closed environment, too. Ok, they won't play
with your private parts (pun intended), but they will allways find
"creative" ways to abuse your modules. So it would be better not to have
to work with those people in the first place.

A anal-retentive (I like this one, Erik :-) ) language doesn't help there.
It just hinders those that have clue about what they are doing. _Any_
language can be abused by bad programmers. So a language should
concentrate on helping the cluefull programmer and not worry with bashing
clueless ones.

bye, Georg

--
#!/usr/bin/perl -0777pi
s/TS:.*?\0/$_=$&;y,a-z, ,;s, $,true,gm;s, 512,2048,;$_/es

Asle Olufsen

unread,
May 8, 1998, 3:00:00 AM5/8/98
to

Barry Margolin <bar...@bbnplanet.com> writes:

>
> Of course, this is one of the primary