From: Michael Burschik
Subject: Q: differences between structures and objects
Date: 
Message-ID: <16CAA9ED4S85.UPP201@ibm.rhrz.uni-bonn.de>
 
This may be a silly question, but what are the main differences between
structures and objects? They look pretty similar to me.
 
Cheers,
        Mike.
 
 
 
 
 
 
 
 
 
 

From: Simon Leinen
Subject: Re: Q: differences between structures and objects
Date: 
Message-ID: <SIMON.93Dec20125243@liasg3.epfl.ch>
Michael> This may be a silly question, but what are the main
Michael> differences between structures and objects? They look pretty
Michael> similar to me.
 
If you define a class using DEFCLASS with no :METACLASS option, the
class will be of type STANDARD-CLASS.  Probably you are thinking of
instances of such classes when you say "objects".  In order to
distinguish them from other objects, I will call them "standard
objects" because they are all of type STANDARD-OBJECT.

Structures are instances of classes of type STRUCTURE-CLASS.  The
common supertype of all structure types is STRUCTURE-OBJECT, so I will
say "structure objects" when talking about instances of structure
classes.

For the programmer, standard-classes offer more flexibility than
structure-classes:

* A standard-class can inherit from more than one superclass, while a
  structure-class can only inherit from one superclass (specified by
  the :INCLUDE option to DEFSTRUCT).

* Standard-classes can be redefined on the fly.  Outstanding instances
  of a redefined class (including indirect instances, i.e. instances
  of subclasses) will adapt to the new class definition.  This
  adaptation can be controlled by the meta-object protocol.  If you
  redefine a structure class, existing instances of the type will
  generally become incompatible with the new type definition.  In many
  implementations, you also need to recompile code that accesses these
  structures, at least if you change the slot layout.

* Standard-instances can have their class changed by CHANGE-CLASS.
  Again, there is an adaptation protocol which can be customized
  through the MOP.

* The instance creation protocol offered by MAKE-INSTANCE is richer
  than the protocol offered by defstruct constructors.

This added flexibility means that standard-objects are not as easy to
implement than structure-objects.  A structure-object can be
implemented as a vector that contains places for each slots, plus an
entry for the structure type (this could be the struct name, or - more
elegantly - a pointer to the structure class itself).  Struct
accessors can be implemented as indirect pointer accesses with a fixed
offset for each slot.  This corresponds to one or two machine-level
instructions when no type checking is done.

Standard instances and their accessors cannot be implemented in this
straighforward way, because a slot accessor must still work when a
class definition is changed (changing the slot's offset) or when the
object itself changes its class.  I don't know how exactly
standard-objects are represented in existing CLOS implementation, but
I assume that there is no way to avoid at least one additional
indirection and probably a cache lookup per slot access.

So, if you don't need multiple inheritance, dynamic class redefinition
or dynamic class change, then using defstruct instead of defclass is
probably a performance win.  In my experience, this is especially true
if you create a lot of objects, because structures are constructed
faster than standard instances (they also take up less space).  Hint:
If you use structures, boa constructors will be significantly faster
than the default keyword-based constructors created by DEFSTRUCT.

You can specialize methods on structures just as you can specialize
them on standard classes (except if you use a very old version of
PCL).  It is possible that generic function dispatch on structures is
slower than on standard objects - I haven't tried that out.

Regards,
-- 
Simon Leinen.
Laboratoire d'Intelligence Artificielle
Ecole Polytechnique Federale de Lausanne
From: Harley Davis
Subject: Re: Q: differences between structures and objects
Date: 
Message-ID: <DAVIS.93Dec21091008@passy.ilog.fr>
In article <···················@liasg3.epfl.ch> ·····@lia.di.epfl.ch (Simon Leinen) writes:

   You can specialize methods on structures just as you can specialize
   them on standard classes (except if you use a very old version of
   PCL).  It is possible that generic function dispatch on structures is
   slower than on standard objects - I haven't tried that out.

This seems unlikely to me.  Why do you think this?

-- Harley Davis
--

------------------------------------------------------------------------------
nom: Harley Davis			ILOG S.A.
net: ·····@ilog.fr			2 Avenue Gallie'ni, BP 85
tel: (33 1) 46 63 66 66			94253 Gentilly Cedex, France
From: Barry Margolin
Subject: Re: Q: differences between structures and objects
Date: 
Message-ID: <9312201825.AA23297@telecaster.think.com>
In article <···················@ibm.rhrz.uni-bonn.de> you write:
>This may be a silly question, but what are the main differences between
>structures and objects? They look pretty similar to me.

Objects are more powerful and flexible than structures, which are generally
implemented simply as vectors.  Objects are more appropriate for
object-oriented programming, although CLOS allows methods to be specialized
on most types (including structures).  Objects support multiple
inheritance, can be created using MAKE-INSTANCE (making it easier if you
must determine the class at runtime), and support a more complex
initialization mechanism (the :DEFAULT-INITARGS option and specialization
of initialization methods).  They allow slot access with SLOT-VALUE,
SLOT-MAKUNBOUND, and SLOT-BOUNDP.
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar
From: Michael Burschik
Subject: Re: Q: differences between structures and objects
Date: 
Message-ID: <16CABCA56S85.UPP201@ibm.rhrz.uni-bonn.de>
In article <···················@ibm.rhrz.uni-bonn.de>
······@ibm.rhrz.uni-bonn.de (Michael Burschik) writes:
 
>
>This may be a silly question, but what are the main differences between
>structures and objects? They look pretty similar to me.
>
>Cheers,
>        Mike.
>
>
>
>
>
>
>
>
>
>
>
>This may be a silly question, but what are the main differences between
>structures and objects? They look pretty similar to me.
>
>Cheers,
>        Mike.
Ok, it was a silly question. Mostly because it was phrased so vaguely.
What I really wanted to know was how structures with methods stored in
some of their slots differ from single inheritance classes from an
implementation point of view. Simon Leinen told me just that in his
helpful reply. Now, I have a related question, which I will try to put
more clearly than the last one. In Common Lisp, it is possible to
implement a simple kind of object/class as a closure. This does not
seem to be possible in Emacs Lisp, at least not in an obvious way.
Is this due to differences in scoping or something else?Can the problem
be circumnavigated?
 
Cheers,
Mike.
From: Daniel LaLiberte
Subject: Emacs Lisp closures (was Re: Q: differences between structures and objects)
Date: 
Message-ID: <LIBERTE.93Dec21094335@ebony.cs.uiuc.edu>
   From: ······@ibm.rhrz.uni-bonn.de (Michael Burschik)
   ...
   In Common Lisp, it is possible to
   implement a simple kind of object/class as a closure. This does not
   seem to be possible in Emacs Lisp, at least not in an obvious way.
   Is this due to differences in scoping or something else?  Can the problem
   be circumnavigated?

Emacs Lisp does not have lexical scoping, which would help in creating
closures which are also absent.  

Lexical scoping can be partially faked in Emacs Lisp.  Unique names
(which can be generated automatically, as in lexical-let in cl.el)
almost make lexical scoping a non-issue because names outside a local
scope will never be shadowed by the local scope and outside code can
never refer to the new names.  But references to these fake lexical
vars still cannot be returned in closures.  Consider what the
following should do with the local-var:

  (let ((local-var some-data))
     (function (lambda () (do-something-with local-var)
                          (setq local-var new-data))))

The local-var in the lambda will not refer to the binding in the let
no matter what it is named.  It will refer to the dynamically scoped
local-var that exists, if at all, at the time the function is called.
However, there is a way to fake this too, called "cons insertion" I
believe.  The trick is to replace the value in every local variable
binding with another object that references the value indirectly.  A
cons cell or vector of length one will do.  Every variable reference
is replaced by the indirect access to the value through this object,
and every change of the variable value is replaced by a side effect on
this object.  So the above code would be changed to:

  (let ((local-var (vector some-data)))
     (function (lambda () (do-something-with (aref local-var 0))
                          (aset local-var 0 new-data)))))

But if do-something-with is a macro that might change local-var, then
the above is wrong.  All macros need to be expanded before we can tell
what uses are being made of local variables.

Daniel LaLiberte
·······@cs.uiuc.edu
From: John S Cooper
Subject: Re: Emacs Lisp closures (was Re: Q: differences between structures and objects)
Date: 
Message-ID: <JSC.93Dec22183234@kontiki.Eng.Sun.COM>
Daniel LaLiberte writes:

> However, there is a way to fake this too, called "cons insertion" I
> believe.  The trick is to replace the value in every local variable
> binding with another object that references the value indirectly.  A
> cons cell or vector of length one will do.  Every variable reference
> is replaced by the indirect access to the value through this object,
> and every change of the variable value is replaced by a side effect on
> this object.  So the above code would be changed to:
> 
>   (let ((local-var (vector some-data)))
>      (function (lambda () (do-something-with (aref local-var 0))
>                           (aset local-var 0 new-data)))))

I don't see how this can work? The binding of `local-var' in the `let'
statement is not recorded in the function, unlike in Scheme, so trying
to access it via aref will surely fail?

The following code generates a "Symbol's value is variable is void: foo"
error:

(setq x (let ((foo (vector 'something)))
	  (function (lambda () (print (aref foo 0))))))
(funcall x)

Am I missing something here?
--

    --- John
From: Daniel LaLiberte
Subject: Re: Emacs Lisp closures (was Re: Q: differences between structures and objects)
Date: 
Message-ID: <LIBERTE.93Dec24155009@ebony.cs.uiuc.edu>
   From: ···@kontiki.Eng.Sun.COM (John S Cooper)

   Daniel LaLiberte writes:
   > So the above code would be changed to:
   > 
   >   (let ((local-var (vector some-data)))
   >      (function (lambda () (do-something-with (aref local-var 0))
   >                           (aset local-var 0 new-data)))))

   I don't see how this can work? The binding of `local-var' in the `let'
   statement is not recorded in the function, unlike in Scheme, so trying
   to access it via aref will surely fail?

Yeah, you're right.  You would have to do what lexical-let in cl.el 
does already.  It creates another global symbol with a unique name
to be used inside the lambda expression.

dan
From: Brent Benson
Subject: Re: Q: differences between structures and objects
Date: 
Message-ID: <BRENT.93Dec21125949@jade.ssd.csd.harris.com>
······@ibm.rhrz.uni-bonn.de (Michael Burschik) writes:
#
#                                  In Common Lisp, it is possible to
# implement a simple kind of object/class as a closure. This does not
# seem to be possible in Emacs Lisp, at least not in an obvious way.
# Is this due to differences in scoping or something else?Can the problem
# be circumnavigated?
#  

In my experience, people don't often roll their own object systems in
Common Lisp now that CLOS is here.  On the other hand, people often
use this closure-as-object approach in Scheme to provide a simple
object system.

Anyhow, closures are great for bottling up some state (like instance
variables and methods) in a function for a simple object system.  Even
though Emacs Lisp does not have closures (it is dynamically rather
than lexically scoped) you can still write an object system for it.
In fact, I have written a little object system for elisp with classes
and generic functions.  If people are interested, I can clean it up
and make it available.

--
Brent Benson                     
Harris Computer Systems