What are the characteristics dynamic redefinition?
Is it a better/worse/equal to C++ dynamic binding?
My first object-oriented language was C++, so I am not used the term
"meta class".
In java all classes inherits from the class "Object", is that a meta
class?
When do one need to write meta classes?
/Mattias Högström
> I am new to quite new to object-orientation in lisp
Welcome :-)
> Is dynamic redefinition of classes something like C++'s dynamic binding?
I don't know what C++'s concept of dynamic binding is, but I'm quite sure
they will turn out to be very different.
> What are the characteristics dynamic redefinition?
> Is it a better/worse/equal to C++ dynamic binding?
Your program can define or change a class definition in runtime. As for the
comparison with C++, you will have to decide on your own.
> My first object-oriented language was C++, so I am not used the term
> "meta class".
This is a fairly complex story. First get used to CLOS, otherwise
explaining the use of metaclasses will be quite difficult.
> In java all classes inherits from the class "Object", is that a meta
> class?
Well, no. Metaclass is the class of which all other classes are
*instances*, rather than subclasses.
> When do one need to write meta classes?
When you want CLOS to behave differently than it does. Almost never.
Sunil
um, it is less of a new thing than it might appear to be. it is easier
to think of Common Lisp as object-oriented from the start than to think
of the object-oriented features as somehow "different" or "additional".
| Is dynamic redefinition of classes something like C++'s dynamic binding?
no. you execute the code that defines a class at run-time in CL, and you
can execute a different piece of code that defines a class that already
exists, and this is handled well by the system, which remembers of which
"version" of a class an instance is an instance.
| My first object-oriented language was C++, so I am not used the term
| "meta class".
it might also help to stop regarding C++ as an object-oriented language
and especially stop comparing anything to it. it take some effort to
avoid it, but do not let your first experiences color your next
experience.
| In java all classes inherits from the class "Object", is that a meta
| class?
the meta-class in Java is Class. <class>.class is an instance of Class,
and you can call its newInstance method, for instance. the reflection
protocol allows you to talk about the instances of Class. you can not
create new meta-classes (or sub-classes of Class).
| When do one need to write meta classes?
when it is harder to what you need to do without it. knowing that you
can will save you a lot of work, but you won't get there for a while.
#:Erik
--
The Microsoft Dating Program -- where do you want to crash tonight?
* Erik Naggum wrote:
* "Mattias Högström" <pt9...@student.hk-r.se>
> | Is dynamic redefinition of classes something like C++'s dynamic binding?
> no. you execute the code that defines a class at run-time in CL, and you
> can execute a different piece of code that defines a class that already
> exists, and this is handled well by the system, which remembers of which
> "version" of a class an instance is an instance.
I think this is confusing (though I'm sure Erik understands the
issue!).
In CL you can define a class and then make some instances of it. You
can then *redefine* the class -- say adding some slots or something.
All the instances of the class will be updated automagically to be
instances of the updated class. This update happens at some point
before you next refer to the instances.
More powerful still, you can define methods that get called during the
update -- say you delete a slot from a class, and somehow you need to
merge information formerly held in that slot into other slots, then
you can define methods that do just that.
You can also change the class of an object, and of course you can
define methods that get called when an object's class changes.
(The reason that I think Erik's answer was confusing is that it could
have meant that there could be several versions of a class in
existence, and instances could belong to each of them. CL isn't like
that, but I think Oaklisp was for instance).
--tim
> * "Mattias Högström" <pt9...@student.hk-r.se>
> | I am new to quite new to object-orientation in lisp
>
> um, it is less of a new thing than it might appear to be. it is easier
> to think of Common Lisp as object-oriented from the start than to think
> of the object-oriented features as somehow "different" or "additional".
Well CLOS has a different approach to object-oriented programming than the
languages I know of. It has really weird stuff not found in Java/C++.
> | Is dynamic redefinition of classes something like C++'s dynamic binding?
>
> no. you execute the code that defines a class at run-time in CL, and you
> can execute a different piece of code that defines a class that already
> exists, and this is handled well by the system, which remembers of which
> "version" of a class an instance is an instance.
When do you want to change a class' behaviour run-time?
Why not instanciate a subclass to change the behaviour?
What is the alternative to redefinition of classes, how does C++/Java cope
without it?
Do they use patterns to solve the same problem?
> | My first object-oriented language was C++, so I am not used the term
> | "meta class".
>
> it might also help to stop regarding C++ as an object-oriented language
It isn't?
I know that Simula and Smalltalk are better, but C++ has object-oriented
capabilities.
But if you have any interesting links concerning the opposite it would very
appreciated.
> and especially stop comparing anything to it. it take some effort to
> avoid it, but do not let your first experiences color your next
> experience.
Hehe
It is the only object-oriented language except from Java I have experience of.
How is it possible to avoid comparing to other languages I know?
> | In java all classes inherits from the class "Object", is that a meta
> | class?
>
> the meta-class in Java is Class. <class>.class is an instance of Class,
> and you can call its newInstance method, for instance. the reflection
> protocol allows you to talk about the instances of Class. you can not
> create new meta-classes (or sub-classes of Class).
This "meta" thing was harder than I thought...
Learning object-orientation with C++ was huge a mistake(damn my school)
Now it's harder than ever to understand true object-oriented languages.
> | When do one need to write meta classes?
>
> when it is harder to what you need to do without it. knowing that you
> can will save you a lot of work, but you won't get there for a while.
Hey stop dissin' me! ;)
I will probably not need it either, I was just interested in when you need it,
since it doesn't exist in C++. How does C++ cope without it?
Now I am really interested what meta classes really are.
> #:Erik
> --
> The Microsoft Dating Program -- where do you want to crash tonight?
/Mattias
Here is an example somebody posted on the net sometime back.
Assume you have a class called Empolyee which has subclasses
like manager, programmer etc. You have instances of one of these
classes to represent each of your employees in the organisation.
Assume that a person was a programmer before, and now been
assigned as a manager (may be a promotion, or may be a
punishment :-).
Now the old way to "deallocate" the old instance of
the programmer and allocate a new instance of the manager.
(And you need to store some contents of the old instance
to be put into the news instance)
In CLOS using MOP you can do things like "CHANGE-CLASS"
which takes an instance of one class and makes as an instance
of other class. This is not exactly the example for
class redifinition, but it does show some MOP (meto-object-protocol)
capabilities.
srini
-----
Srinivas Palthepu, Lucent Technlogies, Inc.
Email: psr...@lucent.com, phone: (630) 979-9154
So to get at one fragment of an issue: When does one need to write
metaclasses? Here's my favorite example: Suppose we need to know all the
instances of a class. Now there's no "central place" in CLOS where
pointers to all the instances are kept (which is why GC is necessary and
possible), so we can't even poll all instances and select those of the
appropriate class (which could be hideously costly, anyway). Of course
there are various ways of keeping track of which instances are in each
class, but a (conceptually) easy way is to let the class object itself
do it (note the important assumption that the class object is an
instance of some class, as are all instances in CLOS).
This means that we need a new kind (class) of class --i.e., a new
metaclass-- that's a subclass of the standard one. It must support the
entire protocol of the existing metaclass and in addition support a new
protocol element: "give me all your instances". Any new class built as a
subclass of this new instance-interning metaclass will be able to
respond to the "give me all your instances" message by returning its
instances.
I don't propose here that there are any advantages, etc. of this (I say
again: there are other ways to do it); I'm simply pointing it out as an
_example_ of something you'd need metaclasses to do, in order to
illuminate the concept. There are many other cases (not "hardly ever")
that require different kinds of classes _WHEN YOU'RE EXPANDING THE
ENVELOPE_ of what CLOS can do. I'm shouting because most of what CLOS
does it does reasonably well but it doesn't do everything, like
persistence, distribution, notification, maintenance, etc.
LRP
> When do you want to change a class' behaviour run-time?
Objects are changing over time. I think this a fundamental
observation. Most systems are totally static and
are not able to represent the changes. People
are reading books from Meyer and they believe that
objects and classes *need* to be static. The opposite
is true.
In some respect even CLOS is not dynamic enough. See:
Description Logics, Frame Languages, KL-One, Semantic
Networks, First-order Logic, ...
> Why not instanciate a subclass to change the behaviour?
Because it is an awful kludge?
> What is the alternative to redefinition of classes, how does C++/Java cope
> without it?
Restarting the program?
> Do they use patterns to solve the same problem?
They use all kinds of patterns to try to solve problems they
have introduced by accident. Read the paper by Peter Norvig
about patterns in dynamic languages. You can find
it on his web site (http://www.norvig.com/)
However, it turns out this feature is critical for a persistent
object system, since you really don't have the option to
redefine a class, recompile that application, and then
restart it as of 6 months ago and re-execute the 2-billion transactions
that occurred on the database during that 6 months (or 6 years.)
Nope, you've got to update the existing instances.
And furthermore, you might not have the option to stop
the application for 8 hours while it is updated.
Hmm, funny that sounds exactly like the situation with an
online commerce website...
-Kelly Murray k...@intellimarket.com
$500 reward offered for a CommonLisp JPEG encode/decoder utility
well, I have this application running at a client's that needs 100%
uptime from 04:00 through 20:00 every working day. when I make changes
to the system, I can load new function and class definitions into the
running system, and pre-existing instances of a class will update
themselves to the new class definition. we had 99.994% uptime until last
week, when a firewall got Alzheimer's and the backup routed croaked, so
now we're down to 99.96% uptime. without the ability to make run-time
changes to class definitions, we would have had to stop and restart the
system several times a day, usually in response to user requests that
would probably not have been possible to satisfy at all without this
feature.
| Why not instanciate a subclass to change the behaviour?
you're thinking static applications, here. don't. think living systems
that don't believe in reincarnation (reboot).
| How is it possible to avoid comparing to other languages I know?
just don't do it. consciously avoid comparing when you feel it coming
on. force yourself to start with a clean slate and separate old from new
like you separate two natural languages you need to learn. (you never
learn to speak another language if you keep translating between the two
or continue to think in one and use grammar and vocabular from another --
I'm sure you already know this. :)
| Learning object-orientation with C++ was huge a mistake(damn my school)
| Now it's harder than ever to understand true object-oriented languages.
not really. the human mind has a demonstrably great capacity to repress
painful experiences. it's a basic defense mechanism in any intelligent
animal with memory. you don't even need to learn to use it, just do it.
(and don't think I'm being facetious.)
| I will probably not need it either, I was just interested in when you
| need it, since it doesn't exist in C++. How does C++ cope without it?
C++ doesn't cope without it. therefore, if you think in C++ terms, you
will need it as much as the average fish will invent hanggliding gear.
invention is the mother of need.
a typical example of when you need a meta-class is when you want some
behavior to apply to all instances of all classes of the meta-class, like
persistent objects that are going to be stored on disk. you would code
the disk-storing properties in one place, only, and use the classes just
like normal classes. everything relating to persistency would be taken
care of automatically. in a language without this ability to centralize,
you would need to code the persistence in a lot of places, and perhaps
expose it via different calling conventions where it is being used.
| Now I am really interested what meta classes really are.
they define the behavior of classes as classes define the behavior of
their instances. it's really no big deal. instead of being taught "this
is what being a class means" and having to adapt to whatever the language
offers, you can now define it yourself if you need more than the language
designers had in mind at the time. this is the same argument you would
use to describe classes (or even structures or simple type definitions).
I agree that it could look like that. thanks for clearing it up.
In C++, you can use a combination of operator overloading and RTTI (run-time
type identification) to get some of the same results as you can with
metaclasses - and, more generally, a metaobject protocol. In particular,
RTTI can get you some of the introspective capabilities found in
metaclass-based object systems, while operator overloading (and especially
overloading the new, ->, and () operators) can get you some of the effects
of defining new metaclasses that implement alternative object allocation,
slot access, and method calling strategies. Lisp systems usually let you do
even more than C++, exposing, for instance, a protocol for modifying
inheritance or doing new types of method combination.
Here are two classic examples of where you might want to use a metaobject
protocol:
1. Object browsers. By storing classes and methods as objects, it is
possible to write a completely general object browser within the language
without resorting to code parsing.
2. Instances stored in databases. Here you want to allocate a row in an
RDBMS when an object is allocated and do a database query when you reference
an (uncached) slot value. To do this transparently (i.e. without defining
new operations on objects) you need to be able to redefine how the normal
operations for allocating objects and accessing slots work. A MOP gives you
this capability, as does the C++ operator overloading. Using a MOP, you
would define a new metaclass whose instances are classes whose instances are
stored in a database. You would define methods on the metaclass for generic
functions like allocate-instance and slot-value-using-class. When you
define a class whose instances would be stored in the DB, you specify the
metaclass. In C++, you would define a superclass (base class) which
implements operator new and operator->. Classes derived from this base
class would then have the desired capability.
IMO, the C++ way of doing things is, as usual, hairy and error-prone (and
not entirely transparent) while the typical Lisp object systems are more
elegant. C++ does in general have a performance advantage for low-level
hackery, but as I'm sure someone else will be sure to say, Lisp has a
general productivity and abstraction advantage that can lead to reasonably
efficient overall systems.
BTW, Java provides the introspective capability of Lisp but has no support
for adding new functionality transparently via a MOP. In this respect, both
C++ and Lisp are superior to Java, although at a cost of considerable extra
complexity in the specification and implementation of the languages.
-- Harley
On the other hand, when you're first learning the new language, it's almost
impossible to do it any way else. Most people think about concepts using
the framework of language, so you start out by mentally translating.
Eventually you become fluent enough in the new language that you can
initiate thoughts there, but it's not reasonable to expect this off the
bat.
I've learned just about every programming language I know by recognizing
the similarities and differences between it and other languages I have
experience in. E.g. when I learned C, I could see that
for (<var> = <initial>; <condition>; <var> = <update>) ...
was analogous to Lisp's
(do ((<var> <initial> <update>))
((not <condition>))
...)
I could also see where they differed: Lisp's DO makes it easier to step
multiple variables (although this is possible in C using the comma
operator); C doesn't require the update expression to update the same
variable as the initialization expression.
I think learning by comparing and contrasting is the way to go, as it
allows you to build from a foundation rather than starting from scratch.
But you have to recognize when two paradigms are so different that you
can't really do this. The OO paradigm in CLOS is very different from just
about all its predecessors, particularly the emphasis on generic functions
rather than active objects (the original OO paradigm came out of research
on "actor" languages, where active objects passed messages to each other
and dispatched on these messages, and this is totally gone in CLOS). In
many ways C++ is closer to traditional OO, whose archetype is Smalltalk,
than CLOS is.
--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Don't bother cc'ing followups to me.
Because that wouldn't change the behavior of existing instances on the fly.
>What is the alternative to redefinition of classes, how does C++/Java cope
>without it?
>Do they use patterns to solve the same problem?
Most "conventional" languages are static, they don't provide ways to change
anything at runtime. If you modify the program, you have to restart the
application.
Lisp allows function redefinition on the fly: you can call EVAL, COMPILE,
or LOAD to redefine things. Consistent with this is allowing classes to be
redefined.
Allowing the class of instances to be changed on the fly was a more
controversial feature, but in the end it won out. However, it can be
difficult to use. I recall that Symbolics's initial implementation of
their Table facility, which had different representations for tables
depending on their size (e.g. an alist for small tables, a hash table for
large ones) tried to use CHANGE-CLASS, but there was a combinatorial
explosion of UPDATE-INSTANCE-FOR-REDEFINED-CLASS methods for all the
possible conversions. They later changed it so that there was a single
class for tables, and the representation was a slot in the instance. (This
is all from very vague memory and I may have some details wrong, but I
recall that there were a number of bugs in the initial table facility that
seemed to be due to problems with changing class on the fly -- maybe Kent
can clarify.)
> When do you want to change a class' behaviour run-time?
If you only know at run-time _how_ your class' behaviour should change.
> Why not instanciate a subclass to change the behaviour?
Before instantiating a subclass, that subclass has to be defined.
Since you don't know the details of the behaviour your subclass should
provide until run-time, you would have to dynamically define the
subclass at run-time. This is impossible in C++ (maybe Java's current
version helps here a bit), but of course no problem in CLOS.
OTOH why create a subclass dynamically, when you really want the old
class to change? And vice-versa, why change the old class, when you'd
really want a new subclass? CLOS provides you with all of these
abilities (and quite a few more[1]), so that you can implement the
behaviour and semantics you want to model as directly as possible.
> What is the alternative to redefinition of classes, how does C++/Java cope
> without it?
> Do they use patterns to solve the same problem?
Well yes, mostly C++/Java&Co try to resort to patterns when the
languages themselves are not expressive enough to implement the
desired behaviour directly. But in the case of class-(re)definition
at runtime, this would require some very complex kind of pattern,
i.e. in reality this involves lots of duplication of the languages
own machinery. Consider the complexity of CORBA or COM (the basic
part, without all additional features like directory services & co), or
of adding a scripting engine to the application in question (e.g. CINT,
a C++-interpreter used in the simulation framework ROOT of CERN, or the
use of python& co.).
> Hey stop dissin' me! ;)
> I will probably not need it either, I was just interested in when you need it,
> since it doesn't exist in C++. How does C++ cope without it?
> Now I am really interested what meta classes really are.
Consider getting hold of "The Art of the Metaobject Protocol" by
Gregor Kiczales, Jim des Rivières and Daniel G. Bobrow (MIT Press).
But a very good demonstration of the power and uses of MOPs is the
implementation of Design-By-Contract machinery for Common Lisp via the
MOP in ~ 400 Lines of Code, which Matthias Hölzl has posted here some
weeks ago[2]. Where a CLOS user can implement this functionality in
400 lines of code in the language itself, the "inventor" of
Design-By-Contract (Bertrand Meyer) created a whole new language
(Eiffel) just to support this design methodology.
If you wanted to add DBC support to C++ or Java, you would have to
change the language, and in effect[3] change the compiler.
Regs, Pierre.
Footnotes:
[1] e.g. you can change the class of an instance at run-time, which
is really very useful to model some kinds of (drastic) state
changes, that would otherwise entail checking a state-flag in
nearly every method. Consider a stream, whose total behaviour
varies drastically depending on whether the stream is open or
closed. More specifically most stream types behave alike, when
they're closed, but behave very differently when open.
[2] He wrote: "I keep the latest version of the sources at
<http://www.muc.de/~hoelzl/tools/dbc/dbc.lisp>
with a short (and mostly unfinished) intro to DBC at
<http://www.muc.de/~hoelzl/tools/dbc/dbc-intro.html>"
[3] You could of course write extra-lingual add-on tools (like
preprocessors) to support this, but this is in effect just another
form of changing the compiler when you don't have access to the
source code.
--
Pierre Mai <pm...@acm.org> http://home.pages.de/~trillian/
"One smaller motivation which, in part, stems from altruism is Microsoft-
bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]
PM> If you wanted to add DBC support to C++ or Java, you would have to
PM> change the language, and in effect[3] change the compiler.
Not to defend C++ very strongly, but some people might be interested
in OpenC++[1], which is a compile-time MOP for C++ (ie a
source-to-source translator). It can be used to create a specialized
runtime MOP, or to add extensions such as persistence or fault
tolerance mechanisms to C++ programs. There is also a Java version in
the works.
PARC maintain a list[2] of MOP implementations. Also see [3] for more
information on theoretical aspects.
[1] http://www.softlab.is.tsukuba.ac.jp/~chiba/openc++.html
[2] http://www.parc.xerox.com/spl/projects/mops/existing-mops.html
[3] @TechReport{Maes87,
author = "Pattie Maes",
title = "Computational Reflection",
institution = "Vrije Universiteit Br{\"u}ssel",
address = "Br{\"u}ssel",
type = "Technical Report",
number = "87-2",
keywords = "Meta-Knowledge, Object-Oriented Language, Programming
Language, Reflection, Refletive Architecture,
Self-Reference",
year = "1987",
}
--
Eric Marsden
emarsden @ mail.dotcom.fr
It's elephants all the way down
huh? if by "starting from scratch" you mean forgetting understanding, I
don't understand how it woulb e possible to forget understanding. it has
never happened to me. I forget details, particulars, individual rules,
but I don't forget anything in the web of understanding that forms how I
approach things both new and old.
e.g., the specific syntax and the concrete semantics of one language are
useless in the extreme when learning another and should be ignored, not
used a basis for comparison. the idea of expressability of the concepts
through various general means remains, however. when you first learned
to program, you needed to learn the concepts of flow control, variables,
evaluation order, operator precedence, types, etc. these _concepts_ have
different expression in each language, optimized differently according to
perceived frequency of need, and you can obviously not avoid employing
your _understanding_ of these concepts, but you ought to suppress your
memory of the particulars, and I think that is fundamentally necessary
when learning a new instance of something when you know an old instance.
it is really hard to discover subtle differences when you expect things
that appear the same to be the same, but aren't.
"it is better to know what it is, than to believe it is what it appears
to be". short motto-like statement has hung framed on my father's office
wall since I was kid, and it has shaped much of my thinking -- I find it
infuriatingly frustrating when people hold the reverse view.
incidentally, I think the idea of suppressing memory in order to learn is
general advice. remembering is a great time-saver when dealing with the
already-known world. abstraction and understanding is, however, what you
will need and capitalize on when dealing with the to-be-known world, and
if you remember at the wrong times, you will not recognize that something
is sufficiently different from what you were used to to become anything
but confused and frustrated by the differences when you stumble upon them.
I think the subtle differences between Scheme and Common Lisp despite the
many glaring similarities is a prime example of this, and we see students
who continue to write in Scheme despite talking to a Common Lisp system
all the time. I attribute this to the problem of learning similar things
through comparisons that yield false positives. by effectively assuming
the negative, I remove the danger of the false positives.
now, _after_ you have figured out how something works in two different
languages, you may compare them and reach valid and informed conclusions,
but as a means of learning something new? no way it will save you time
and effort. on the contrary -- the more you believe things to be the
same, the less likely you are to stop and reconsider that view.
| In many ways C++ is closer to traditional OO, whose archetype is
| Smalltalk, than CLOS is.
I guess it must be my education from the University of Oslo, but I heard
that SIMULA was the first language to earn the "object-oriented" merit
badge, as early as 1967. SIMULA started out as a language to express
simulation (complete with co-routines, absent in other object-oriented
languages), and grew into an object-performs-action-language, which is
the model employed in C++ (Bjarne was very influenced by SIMULA), and I
don't think this is even close to the message-passing model of Smalltalk
and Flavors. (I actually find the object-performs-action-paradigm
lacking in abstraction power, since I don't think that way to begin with.
both message-passing and generic functions work well with me, though.)
I'll chip in and say that Common Lisp has a significant performance
advantage over unsupported hacks (patterns) that mostly unskilled C++
programmers need to engage in to do advanced object-oriented stuff.
in my experience, C++ does not perform well when things get complex.
it's like a kid who can multiply two-digit numbers amazingly fast, but
doesn't have the math skills that, e.g., calculus requires, so either he
fails or he does it real slow, but still sells himself as a math wiz.
> * Barry Margolin <bar...@bbnplanet.com>
> | I think learning by comparing and contrasting is the way to go, as it
> | allows you to build from a foundation rather than starting from scratch.
>
> huh? if by "starting from scratch" you mean forgetting understanding, I
> don't understand how it woulb e possible to forget understanding. it has
> never happened to me. I forget details, particulars, individual rules,
> but I don't forget anything in the web of understanding that forms how I
> approach things both new and old.
A lot of us understand things in a way that makes essential use
of concrete examples. I don't mean we couldn't state the concepts
in terms that don't require the examples; but that the easiest
way for us to think about the concepts makes use of the examples.
It may be that this isn't the most effective way of thinking
(though I think I think this way to some extent, and it seems
to work well for me[1]), but for people who think that way it's
possible that "forget the concrete examples" isn't the most helpful
advice. (Whether it is helpful depends on how readily one can
reorganise one's whole way of thinking. If your way is better
and it's possible to change, your advice might still be good
even for those who don't presently think your way.)
If someone only knows one language well (a misfortune that affects
most people when they start programming, and some people for much
longer) and naturally thinks in this rather concrete way, it may
be best for them to approach a second language -- initially --
by mapping new constructs onto old and remembering what the
differences are. Once they know a few more languages, the
generalities are likely to be more readily available, and this
becomes less necessary.
[1] And if you are inclined to say "So obviously you can only
cope with the concrete, and are incapable of abstract thought",
you might like to note my signature...
--
Gareth McCaughan Dept. of Pure Mathematics & Mathematical Statistics,
gj...@dpmms.cam.ac.uk Cambridge University, England.
> My first object-oriented language was C++, so I am not used the term
> "meta class".
[...]
> When do one need to write meta classes?
Don't miss this excellent tutorial (Kiczales is one of the authors of the
CLOS Metaobject Protocol):
"Open Implementations and Metaobject Protocols"
Gregor Kiczales, Andreas Paepcke
(Xerox PARC - Open Implementation Group)
http://www.parc.xerox.com/spl/groups/eca/pubs/papers/Kiczales-TUT95/for-web.pdf
Also check the OI Group home page:
http://www.parc.xerox.com/spl/projects/oi/
Paolo
--
Paolo Amoroso <amo...@mclink.it>
ah, but here's an important distinction. it's pretty hard to _explain_,
say, the concept of assignment to variables without at some point having
=, :=, <-, SET!, or SETQ enter the explanation, and it is probably harder
to understand the concept from an explanation without such examples, but
what remains after you understand it is independent of the operator. so
you can forget the _particular_ operator, and the concept of "assignment"
remains, to be re-instantiated with a different operator or syntax of
your choice to no detriment to the concept. obviously, assignment
doesn't exist in a particular language without a particular operator, but
if it was tied to the operator, you would have a different concept in
another language. that is not a useful approach. (for completeness,
there are a few variations on the "assignment" theme, as well. e.g., in
languages that "declare" objects and initialize them with the same syntax
used for assignments, the concepts "binding" and "assignment", which are
cleanly separated in Lisp, get conflated and turn into a major source of
frustration and confusion in language like C++.)
when such concepts are well understood, the mistake of thinking that
since C's a + b + c is expressed (+ a b c) in Common Lisp, there "ought"
to be a direct translation of a = b = c into (setq a b c), would not be
possible. (I'm not making this up, as Dave Barry would say -- it is an
actual example of student confusion I had to laboriously undo.) such a
mistake is only possible if the _concepts_ are very unclear and there is
little or no understanding, only examples to be compared.
(I'm not saying Barry favors the "copy, don't understand" view of
teaching, but as long as people do copy without requiring understanding,
that _is_ a very likely outcome, and it won't save people time at all,
even though they might get something non-trivial "working" sooner.)
| [1] And if you are inclined to say "So obviously you can only
| cope with the concrete, and are incapable of abstract thought",
| you might like to note my signature...
no, but I _am_ inclined to question where you thought you had provided
evidence for the "only" part. :)
>Read the paper by Peter Norvig
>about patterns in dynamic languages. You can find
>it on his web site (http://www.norvig.com/)
Harumph. Why ppt? Why not PDF? Now I have to read it online or fetch all
the HTML and put them together.
bye, Georg
Get a free Powerpoint viewer from Microsoft. Even available for
your Mac.
>many ways C++ is closer to traditional OO, whose archetype is Smalltalk,
>than CLOS is.
Uhm - actually I think that is not true. The "archetype" of OO might be
Simula (as the oldest representative of this type of languages). And that
one is quite similar to the ideas of C++, granted. But it is very unlike
the ideas of Smalltalk. Smalltalk is much nearer to the "Lisp" way of OO.
Of course, if you think about it, both Smalltalk and Interlisp (at least
the -D variant) are built at Xerox Parc. And there was something like
Loops for Interlisp-D, so it could be possible that Smalltalk took much
from the earlier Lisp variant.
I think there are three main variations on the theme of OO (of course, as
with all schemes, there are several others that don't fit into this scheme
- for example Loop is something completely different, even if it
definitely is somehow connected to OO):
- the Simula way of OO. Most static variant, you can find this one in
things like C++, Object Pascal and even Eiffel.
- the Smalltalk way of OO. Much more dynamic than Simula. You have
something like a MOP, or at least several ways of dynamically interaction
with the object system. You find ideas of Smalltalk in Languages like Self
and Objective-C (although especially Self and Objective-C have serveral
differences to Smalltalk, so this whole second variand is only loosely
connected)
- the Lisp way of OO. Like it is done in CLOS and several of the Frame
systems from the AI world. Maximum of dynamic interaction with the object
system. And the broadest variations on the OO theme.
In a way the second (Smalltalk) variant seems to try to move the third
(Lisp) variant more towards the first one to gain efficiency and maybe to
ease the learning curve. Would be interesting where Dylan fits the picture
(I would put it into the second variant).
Oh, and of course, as with all schemas, this is completely ridiculous and
doesn't say anything, so don't blame me if it doesn't fit your view on the
world ;-)
I think this classification is very unhelpful. Smalltalk OO is much
closer to Simula67 than it is to Self. Smalltalk, Simula67, and Java,
and Common Lisp all use *class-based* inheritance, while Self and
JavaScript use *prototype-based* inheritance. Prototype-based
languages by definition use dynamic typing, but you can have dynamic
typing in a class-based langauge, such as Smalltalk.
--
--Per Bothner
Cygnus Solutions bot...@cygnus.com http://www.cygnus.com/~bothner
> it might also help to stop regarding C++ as an object-oriented language
> and especially stop comparing anything to it. it take some effort to
> avoid it, but do not let your first experiences color your next
> experience.
For those of you with access to the magazine 'SIGS Application
Development advisor', there's an article in the nov/dec-issue
(vol.2, no.2), which pretty much sums up, to me, as a C++-ignorant,
why I am, and have reasons to be, happy as a clam using CLOS
instead of C++ for my current project (I'm thinking of the article
"Effective C++: Data that Describes Itself" on p. 49).
OO without true dynamicity is Not Even Half The Fun (maybe Objective-C
is more fun than C++, then?)!
--
(regards
(espen vestre))
[I said:]
>| A lot of us understand things in a way that makes essential use of
>| concrete examples. I don't mean we couldn't state the concepts in terms
>| that don't require the examples; but that the easiest way for us to think
>| about the concepts makes use of the examples.
>
> ah, but here's an important distinction. it's pretty hard to _explain_,
> say, the concept of assignment to variables without at some point having
> =, :=, <-, SET!, or SETQ enter the explanation, and it is probably harder
> to understand the concept from an explanation without such examples, but
> what remains after you understand it is independent of the operator. so
> you can forget the _particular_ operator, and the concept of "assignment"
> remains, to be re-instantiated with a different operator or syntax of
> your choice to no detriment to the concept. obviously, assignment
> doesn't exist in a particular language without a particular operator, but
> if it was tied to the operator, you would have a different concept in
> another language. that is not a useful approach. (for completeness,
> there are a few variations on the "assignment" theme, as well. e.g., in
> languages that "declare" objects and initialize them with the same syntax
> used for assignments, the concepts "binding" and "assignment", which are
> cleanly separated in Lisp, get conflated and turn into a major source of
> frustration and confusion in language like C++.)
Yes, I agree with all this. But I'm suggesting that for many
people, particularly those who are relative beginners at
programming (meaning: familiar with only 1 language; not
familiar with only 0 languages), those concepts may not be
there in all their abstract glory; and that for such people,
it may be more helpful to start with the language-specific
understanding they have, rather than saying "throw away all
those language-specific knowledge".
If someone knows C and is learning Common Lisp, for instance,
they might well be helped by telling them "THROW and CATCH
are rather like longjmp and setjmp, but much cleaner", or
"DO is similar to for". Of course you then have to explain
the differences.
> when such concepts are well understood, the mistake of thinking that
> since C's a + b + c is expressed (+ a b c) in Common Lisp, there "ought"
> to be a direct translation of a = b = c into (setq a b c), would not be
> possible.
Sure. But if someone thinks this it's because the teaching
technique I'm defending has been misapplied. It isn't really
true that a+b+c [C] equals (+ a b c) [CL]; it's nearer to
(+ (+ a b) c), or possibly (+ a (+ b c)) -- I forget which.
This isn't just nit-picking; note that (1) with this way
of seeing it you don't get baffled by questions like "So
what is the CL equivalent of a+b-c+d-e?", and (2) you can
then say simply that a=b=c [C] equals (setq a (setq b c)) [CL],
which is much nearer the truth. (C's = is of course much
closer to SETF than to SETQ.)
> (I'm not making this up, as Dave Barry would say -- it is an
> actual example of student confusion I had to laboriously undo.) such a
> mistake is only possible if the _concepts_ are very unclear and there is
> little or no understanding, only examples to be compared.
Of course. Someone who has no understanding but only examples is
doomed. But many people have a partial understanding, with rather
narrow concepts -- in fact, we presumably all do to some extent --
and they may find expanding their concepts easier if the new
ideas are related explicitly to the old ones.
> (I'm not saying Barry favors the "copy, don't understand" view of
> teaching, but as long as people do copy without requiring understanding,
> that _is_ a very likely outcome, and it won't save people time at all,
> even though they might get something non-trivial "working" sooner.)
I didn't think anyone was advocating copying without understanding.
I'm certainly not. But I think getting something non-trivial "working"
sooner *is* an important goal. If I need to learn a new language,
I try to get coding in it quickly, even if my understanding is full
of bugs to begin with. (But, like you, I want a reference manual
available from the very beginning.)
>Get a free Powerpoint viewer from Microsoft. Even available for
>your Mac.
Sorry, I won't ever install that on the Mac. Nope, no chance. Hey, this is
my day to be irrational! ;-)
>I think this classification is very unhelpful. Smalltalk OO is much
>closer to Simula67 than it is to Self. Smalltalk, Simula67, and Java,
>and Common Lisp all use *class-based* inheritance, while Self and
>JavaScript use *prototype-based* inheritance. Prototype-based
>languages by definition use dynamic typing, but you can have dynamic
>typing in a class-based langauge, such as Smalltalk.
Sure, you can dived the languages via the inheritance-mechanism. I was
just referring to the level to which they support something like a MOP.
How much dynamicism is in the OO-part of the language. And there, Simula
is quite different from Smalltalk. Smalltalk _does_ have a MOP. Simula
doesn't.
Oh, and to say that CL uses a class-based inheritance is a bit of an
oversimplification, too, don't you think so? At least you should add an
"by default" to your statement ;-)