HDTenEightyP/NetNews huggingface dataset:
From: chyde@pecos.ads.com (Clinton Hyde)
Newsgroups: comp.lang.clos
Subject: undefmethod
Date: 19 Aug 92 23:31:28 GMT
Distribution: comp
Organization: Advanced Decision Systems, Mountain View, CA 94043, +1 (415)
	960-7300


last week I asked about how to remove a method. here's the solution I
came up with in the end:

(defun undefmethod (gen-fn-name qualifiers-list specializer-type-names-list)
  
  "This will remove a method from a generic function. Only names are required.
Qualifiers-list is a list of things like :after, :before, :around.
`specializer-type-names-list` is a list of either class names or lists like (EQL _X_)."
  
  (flet ((get-specializer (name)
	   (if (symbolp name)
	       ;;THEN, just get the class.
	       (find-class name)
	     ;;else, it's either an eql specializer or something illegal. i think.
	     (if (and (listp name)
		      (equal (car name) 'eql))
		 ;;then, we're on this.
		 name
	       ;;else, we got something bad.
	       (error "~s is neither a class-name (symbol) or an eql specializer." name)
	       ))))

    (let (meth
	  (gen-fn (and (fboundp gen-fn-name)
		       (symbol-function gen-fn-name))))
      (unless (typep gen-fn 'generic-function)
	(format t "There is no generic function named ~S" gen-fn-name)
	(return-from undefmethod))
      (setq meth (find-method gen-fn qualifiers-list 
			      (mapcar #'get-specializer specializer-type-names-list)
			      ()))
      (unless meth 
	(error "There is no method for ~S with Qualifiers ~S and specializers ~S"
	       gen-fn-name qualifiers-list specializer-type-names-list))
      (remove-method gen-fn meth)))
  )

they way you use it:

(undefmethod 	'some-method-name 
		'(:after | :before | :around | nothing-at-all)
		'(class-name | class-name | (EQL something) ...))

works nicely. much help supplied by Gregor Kizcales, thanks to all
those who pointed out that it was supposed to be class-objects, not
just names. I wanted to only be using names on this.

also thanks to Gregor for introducing me the EQL-specializers, which
I'd not heard of before (they're probably right there in the book and
I haven't read those paragraphs). 

this is only tested in Allegro CL 4.1, but I'd guess it would work
elsewhere--I didn't cheat and use anything vendor-specific.

 -- clint
--

Clint Hyde		"Give me a LispM or give me death!" -- anonymous

Advanced Decision Systems	Internet:  chyde@chesapeake.ads.com
2111 Wilson Blvd #800
Arlington, VA 22201		(703) 875-0327
Newsgroups: comp.lang.clos
From: lange@lanai.cs.ucla.edu (Trent Lange)
Subject: Re: Accessors specified in a defclass don't seem to use slot-value in 
Organization: UCLA Artificial Intelligence Laboratory
Date: Fri, 14 Aug 92 21:28:38 GMT

In article <28265.9208141401@subnode.aiai.ed.ac.uk> jeff@aiai.edinburgh.ac.uk (Jeff Dalton) writes:
>
>Ordinary accessors can be efficient by not going through
>slot-value-using-class, but what about the accessors that
>_do_ have to go through slot-value-using-class?  How big
>a price do you pay for actually using the MOP?
>
>-- jd

In the new versions of PCL, that depends entirely upon your
slot-value-using-class methods.  When creating the method-function
for accessors, PCL calls compute-applicable-methods on
slot-value-using-class or (setf slot-value-using-class) to tell
whether it is an ordinary accessor method.  If it is, then it uses
the optimized accessor method-function, which precomputes the slot-location
and its type (instance or class-allocated), and essentially looks like
this for standard instances/slots:

(let ((index <index-num>))
  #'(lambda (instance) (svref (std-instance-slots instance) index)))

In reality it also has a check for whether the slot value returned is
unbound, but as you can see, it's about optimal.

If the accessor is non-ordinary, PCL uses the actual slot-value-using-class
dispatch function on the given instance for its method-function.  It
precomputes the instance's class and the slot's effective-slot-definition.
The accessor's method-function then looks like this:

(let ((class <instance-class>)
      (slotd <instance-classes-slot-definition>)
      (svuc-dispatch-function <...>))
  #'(lambda (instance)
      (funcall svuc-dispatch-function class instance slotd)))

Because of this, non-ordinary accessors are actually faster than
directly calling slot-value-using-class, since the slot-definition
is stored and because accessor generic-functions only have to do
dispatch on one parameter (the instance), rather than the three
required parameters that s-v-u-c does.

Compared to optimized accessors, this can be relatively fast or slow,
depending on your s-v-u-c methods.  However, it will probably be slower
than the optimized accessor method-functions, since it would be difficult
to cache the slot locations in user-defined s-v-u-c methods like the
optimized accessors do.  (The standard s-v-u-c method is definitely
slower than optimized accessors, since it looks up the slot's location
with the slot-definition-location generic function.)

An optimization hint is that non-ordinary accessors will take only as
long as the defined s-v-u-c method function if the effective s-v-u-c
method completely overrides the standard method (e.g. as a primary
or :around method that does not call call-next-method).  There is some
extra overhead for the dispatch function to handle combined methods
otherwise.  So if you're really looking for the best possible
performance, you might want to make sure your defined s-v-u-c method
overrides the primary and includes a copy of the standard s-v-u-c code
(from PCL's slots.lisp file) as necessary.

- Trent Lange

Newsgroups: comp.lang.clos
From: jmg@inference.COM (Jeff Greif)
Subject: Accessors specified in a defclass don't seem to use slot-value in Lucid
Organization: Inference Corporation
Date: Wed, 12 Aug 1992 22:11:45 GMT

>>>>> gregor@parc.xerox.com (Gregor Kiczales) writes:

	-> In article <9208111754.AA06971@jupiter.risc.rockwell.com> kal@jupiter.risc.rockwell.com (Kevin Lovette) writes:

	->    From: kal@jupiter.risc.rockwell.com (Kevin Lovette)
	->    Date: 11 Aug 92 17:54:14 GMT

	->    I have some code that uses (setf slot-value-using-class) to trigger the update
	->    of windows on my display.  When I ported this code from Franz to Lucid it
	->    stopped working.  It turns out that accessors in Franz are implemented with
	->    slot-value, but in lucid accessors seem to directly access the slot without
	->    calling slot-value. 

	->    Is there a finalized CLOS MOP specification yet? If so, what does it specify? 

....

	-> As it turns out, the specification never comes right out and says that
	-> automatically generated accessor methods must call SLOT-VALUE-USING-CLASS
	-> and (SETF SLOT-VALUE-USING-CLASS).  But that is certainly what was
	-> intended.  Otherwise, code like your's becomes difficult (perhaps even
	-> impossible) to write.

The user can override the automatically-generated accessor methods, or
supply :around, :before or :after qualifiers to the accessor methods to carry
out the desired side-effect, without going through SLOT-VALUE-USING-CLASS.
This would solve Mr. Lovette's problem, but then somebody could call 
slot-value-using-class instead of the accessor method.
The real issue is that if there are two paths to change a slot value
you have to modify both.  

	-> The current version of PCL, unless something has changed I don't know
	-> about, supports this.  It is pretty easy to do without undue performance
	-> penalty.

In tests I did about a year ago on Lucid CLOS, reader methods on objects of
metaclass standard-class ran about 3x faster than slot-value.  There was
probably a good reason why Lucid bypassed slot-value-using-class in
implementing these -- perhaps JonL can weigh in with it.  My suspicion is that
since the method is specific to a single slot, various runtime decisions can
be moved to compile time -- the check for class-allocated slot under some
circumstances.  I can even imagine an architecture where the index into an
instance vector could be compiled in, and if a subclass inheriting the
method changed the allocation or index of the slot, new accessor methods
for that subclass could be automatically generated and compiled to
override the one from the superclass, without violating any protocol,
as long as we could tell that the superclass's accessor was automatically
generated and its functionality was thus circumscribed.
From: dcmartin@fascet.msi.com (David C. Martin)
Newsgroups: comp.lang.clos
Subject: Re: Beginner's question and method lookup
Date: 20 Aug 92 06:39:30 GMT
Article-I.D.: fascet.9208202039.AA29519
Organization: Molecular Simulations, Inc.

Jon L White writes:

    David, if it were possible to do  "complete determination
    i.e. static binding for the executable"  at compile time,
    then there would be no need for "virtual" functions in
    C++.   Do you understand the fundamental problem posed by
    having same-named methods on a class and and on a derived
    (sub) class?  the dispatch from a higher method cannot
    determine at compile time whether or not a sub-called
    method[*] is the one defined on the same statically
    determinable class or one of those defined on a derived
    (sub) class.  I talked about this topic at the CLOS versus
    C++ debate last week at the 1992 Lisp Users and Vendors
    conference.

Yes, I do understand that you can't do *complete* determination, but I meant
that you didn't always need to do table lookups for cases in which you would
not use "virtual" functions in C++.  I did not mean that you can always do
static determination for solutions in all know problem space.  I should have
been more specific.

dcm
Newsgroups: comp.lang.clos
From: rharris@rdrc.rpi.edu
Subject: Re: PCL structure methods
Organization: The Ohio State University Department of Computer and Information Science
Date: Tue, 18 Aug 1992 12:08:07 GMT

There is a problem with discrimination on pcl::structure-object that
appears in every version of PCL newer than March 92 PCL.
In these versions of PCL, typep is sometimes used for discrimination
(when use-dispatch-dfun-p returns t).

The problem is that the class pcl::structure-object is supposed to
be a superclass of every class having metaclass structure-class, and
this requires a change to the way defstruct works.
I can think of three ways to fix this problem:

 (1) Change defstruct to :include the structure named structure-object whenever
     an :include option is not provided and the name is not structure-object
     and :type is not specified.  Move the definition of structure-object
     from pcl/defs.lisp the place that defstruct is defined.  Then change PCL
     to import the symbol structure-object from whatever package defined it.

 (2) Change typep and subtypep to simulate the effect of (1).

 (3) Change the macro class-test (pcl/methods.lisp), to be the following:

(defmacro class-test (arg class)
  (cond ((eq class *the-class-t*)
	 't)
	((eq class *the-class-slot-object*)
	 `(not (eq *the-class-built-in-class* 
		(wrapper-class (std-instance-wrapper (class-of ,arg))))))
	((eq class *the-class-standard-object*)
	 `(or (std-instance-p ,arg)
              (fsc-instance-p ,arg)
              (typep ,arg 'standard-object)))
	((or (and (structure-class-p class)
		  (not (eq class *the-class-structure-object*)))
             (eq (class-of class) *the-class-built-in-class*))
	 `(typep ,arg ',(class-name class)))
	(t
	 `(memq ',class (class-precedence-list (class-of ,arg))))))


  Richard Harris
Newsgroups: comp.lang.clos
From: rharris@rdrc.rpi.edu
Subject: The class STANDARD-OBJECT
Organization: The Ohio State University Department of Computer and Information Science
Date: Tue, 18 Aug 1992 15:15:38 GMT

The implementation of CLOS in Lucid's Sun Common Lisp 4.0.1 disagrees with 
the MOP specified in chapters 5 and 6 of "The Art of the Metaobject Protocol" 
about a fundamental issue: the meaning of the classes STANDARD-OBJECT and
FUNCALLABLE-STANDARD-OBJECT.  This disagreement is likely to cause portability
problems for some programs.  

The classes STANDARD-OBJECT and FUNCALLABLE-STANDARD-OBJECT are meant to be
"maximal elements" of some set of classes.  The disagreement is over which
set.  There are really three sets of classes that are relevant:
  (1) The set of all subclasses of STANDARD-CLASS,
  (2) The set of all subclasses of FUNCALLABLE-STANDARD-CLASS, and
  (3) The union of (1) and (2).

In PCL, STANDARD-OBJECT is the maximal element for set (3), and
FUNCALLABLE-STANDARD-OBJECT is the maximal element for set (2), 
and there is no class corresponding to the maximal element for set (1).

In Lucid's Common Lisp, STANDARD-OBJECT is the maximal element for set (1), 
and FUNCALLABLE-STANDARD-OBJECT is the maximal element for set (2), 
and there is no class corresponding to the maximal element for set (3).

I believe that all three of these classes should exist, and I think that
the most important of them is the class for (3), because it is this class that
users are most likely to want to specialize on in order to operate on all
instances.  I think that it would be helpful for us to agree on names
for both the class for (1) and the class for (3).  

Also, it would be good to define a class whose direct subclasses are 
STANDARD-CLASS and FUNCALLABLE-STANDARD-CLASS (PCL has no such class;
in Lucid's CLOS this class is called CLOS::SLOTTED-CLASS).


This same issue applies to structure classes.  There two additional
interesting sets of classes:
  (4) The set of all subclasses of STRUCTURE-CLASS, and
  (5) The union of (1), (2), and (4).
Note: Versions of PCL earlier than March 92 PCL do not have the class
      STRUCTURE-CLASS.
In PCL, STRUCTURE-OBJECT is the maximal element for set (4), and
PCL::SLOT-OBJECT is the maximal element for set (5).  Also, the class
PCL::SLOT-CLASS corresponds to set (5).

In Lucid's Common Lisp, STRUCTURE-OBJECT is the maximal element for set (4),
and there is no class corresponding to the set (5).

--------------
Richard Harris
Newsgroups: comp.lang.clos
From: john@linus.mitre.org
Subject: Re: Beginner's question and method lookup
Organization: The Ohio State University Department of Computer and Information Science
Date: Thu, 20 Aug 1992 07:23:55 GMT

Eric Smith (eric@tfs.com) asks:

  But doesn't that make method dispatch very time consuming?  It
  seems like it would involve searching for the method in tables, and
  that the amount of time consumed would depend on how many methods
  were in those tables and how many class arguments each method had.

and David C. Martin (dcmartin@msi.com) replies:

  Yes, if you did things that way.  In fact, you can determine at
  compile time what the argument types are and then put in the
  appropriate call to the appropriate function.

I think this is often true, but not in general, even with extensive
declarations.  If you have a very rich class hierarchy, the compiler
may only be able to narrow the type to partway down the hierarchy, or
to a disjunction of types, not to a leaf.  A SSC may be able to make
use of this information, but I'm not sure many commercial CLOSes could.

In the most ridiculous case, an argument to a generic-function may be
computed via a call to READ; there's little the compiler can do then.

John Burger
john@mitre.org
Newsgroups: comp.lang.clos
From: jeff@aiai.edinburgh.ac.uk (Jeff Dalton)
Subject: Re: Accessors specified in a defclass don't seem to use slot-value in 
         Lucid
Organization: The Ohio State University Department of Computer and Information Science
Date: Fri, 14 Aug 1992 14:01:15 GMT

> With regard to the performance implications of doing it this way, Trent
> Lange has already pointed out that the newest PCL does this efficiently.
> It's too bad that earlier versions of PCL (one which some commercial
> implementations are based) had the bug where they didn't implement this
> aspect of the MOP properly.

Ordinary accessors can be efficient by not going through
slot-value-using-class, but what about the accessors that
_do_ have to go through slot-value-using-class?  How big
a price do you pay for actually using the MOP?

-- jd

Newsgroups: comp.lang.clos
From: kanderso@bbn.com
Subject: Re: Beginner's question and method lookup
Organization: The Ohio State University Department of Computer and Information Science
Date: Thu, 20 Aug 1992 08:53:25 GMT

  To: comp.lang.clos@cis.ohio-state.edu
  Date: Thu, 20 Aug 1992 07:23:55 GMT
  Organization: The Ohio State University Department of Computer and Information Science
  From: john@linus.mitre.org
  Sender: commonloops-request@cis.ohio-state.edu
  Subject: Re: Beginner's question and method lookup
  
  Eric Smith (eric@tfs.com) asks:
  
    But doesn't that make method dispatch very time consuming?  It
    seems like it would involve searching for the method in tables, and
    that the amount of time consumed would depend on how many methods
    were in those tables and how many class arguments each method had.
  
  and David C. Martin (dcmartin@msi.com) replies:
  
    Yes, if you did things that way.  In fact, you can determine at
    compile time what the argument types are and then put in the
    appropriate call to the appropriate function.
  
  I think this is often true, but not in general, even with extensive
  declarations.  If you have a very rich class hierarchy, the compiler
  may only be able to narrow the type to partway down the hierarchy, or
  to a disjunction of types, not to a leaf.  A SSC may be able to make
  use of this information, but I'm not sure many commercial CLOSes could.
  
  In the most ridiculous case, an argument to a generic-function may be
  computed via a call to READ; there's little the compiler can do then.
  
READ is not a ridiculous case, it is a ridiculously important one.  It is
typical of any interaction with the user that could return an arbitrary
object.  While C++ may be clever about using compile time type information,
one of its short coming is it does not support run time typing adequately
enough, READ being a good example.

If there were sufficiently smart compilers, there would be no programmers.

k
From: chyde@pecos.ads.com (Clinton Hyde)
Subject: Re: CLOS Stylistic Questions -- Program Structuring
Organization: Advanced Decision Systems, Mountain View, CA 94043, +1 (415)
	960-7300
	<DOUG.92Aug14161927@monet.ads.com>
Date: Wed, 19 Aug 1992 17:37:47 GMT


Hi Doug!

I personally prefer the DEFSYSTEM approach. i've been using it for 7+
years. if you are just a little careful about your code organization,
it's fairly easy to deal with. I have a simple guideline for what goes
where in the defsystem:

first module contains macros ONLY. this module must be compiled AND
loaded before continuing.

second module contains things like Classes ONLY. like compiled and
loaded. 

third module contains DEFVARs and SETQs of the defvars. if you just
use (DEFVAR *global-var*) or (DEFVAR *global-var* NIL "doc-string")
then a file of these things can precede module 1 or 2 if you want
macros or classes to use global symbols. otherwise, as module 3, the
defvars can be assigned make-instances of the classes.

fourth and subsequent modules can now use macros, classes, and
globals. I NEVER put macros, classes or DEFVARs anywhere except the
first three modules (generally, these are single files of the three
things). meta-. will find things for me with no trouble, so the could
get organized differently, but i've found this technique to be safest
for me over the years.

it keeps me out of trouble in case I forget the compile/load ordering
of the other modules.

 -- clint
--

Clint Hyde		"Give me a LispM or give me death!" -- anonymous

Advanced Decision Systems	Internet:  chyde@chesapeake.ads.com
2111 Wilson Blvd #800
Arlington, VA 22201		(703) 875-0327
Newsgroups: comp.lang.clos
From: wbm@freedom.stanford.edu (Wally Mann)
Subject: Re: CLOS Stylistic Questions -- Program Structuring
Organization: The Ohio State University Department of Computer and Information Science
Date: Tue, 18 Aug 1992 20:41:24 GMT

Ooops.
My apologies ... if anyone read my previous posting, it was
obviously not related to CLOS.
Wally
Newsgroups: comp.lang.clos
From: dcmartin@fascet.msi.com (David C. Martin)
Subject: Re: Beginner's question and method lookup
Organization: Molecular Simulations, Inc.
Date: Thu, 20 Aug 1992 01:48:16 GMT

john@linus.mitre.org writes:

and David C. Martin (dcmartin@msi.com) replies:

	Yes, if you did things that way.  In fact, you can determine at
	compile time what the argument types are and then put in the
	appropriate call to the appropriate function.

    I think this is often true, but not in general, even with extensive
    may only be able to narrow the type to partway down the hierarchy, or
    to a disjunction of types, not to a leaf.  A SSC may be able to make
    use of this information, but I'm not sure many commercial CLOSes could.

You might be surprised at the work that both Franz and Lucid have done with
their CLOS implementations.  I have talked about this issue with John
Foderero @ Franz and he has put hooks in so that if you wish to have
static class hierarchies you can do complete determination, i.e. static 
binding for the executable.

    In the most ridiculous case, an argument to a generic-function may be
    computed via a call to READ; there's little the compiler can do then.

    John Burger
    john@mitre.org

Ah, true.  So you can't do everything, but then again, you can't do static
binding in C++ for that case either.

dcm
Newsgroups: comp.lang.c++
From: pjl@sparc6.cs.uiuc.edu (Paul Lucas)
Subject: Re: Simple inheritance question
Organization: University of Illinois at Urbana-Champaign
Distribution: usa
Date: Tue, 18 Aug 1992 16:06:10 GMT

In <schnitzi.714141577@eola.cs.ucf.edu> schnitzi@cs.ucf.edu (Mark Schnitzius) writes:

>Is there any way to access the variable 'hold' in
>this example with only a pointer to the base class?

>class base {};

>class derived: public base {
>	int hold;
>};

>main ()
>{
>	derived d;
>	base *p;

>	p = &d;

>	cout << p->hold;  //DOESN'T WORK!
>}

*****>	cout << ((derived*)p)->hold;

	However, you had better be *sure* that 'p' really, really does
	point to a 'derived'.

	The reason it doesn't work is because 'base' objects don't have
	'hold' variables; hence, the required cast.
-- 
	- Paul J. Lucas				University of Illinois	
	  AT&T Bell Laboratories		at Urbana-Champaign
	  Naperville, IL			pjl@cs.uiuc.edu
Newsgroups: comp.lang.c++
From: ralph@Xenon.Stanford.EDU (Ralph Melton)
Subject: 'virtual' static members
Originator: ralph@Xenon.Stanford.EDU
Organization: Computer Science Department, Stanford University.
Date: Wed, 12 Aug 1992 20:10:04 GMT


I am trying to write a general enumeration class that can do output
of itself.  If I was doing it as a single class, part of it might
look like

class myEnum
{
  int value;
  static int names;
friend ostream& operator<< (ostream&, myEnum&);
//...
}

ostream& operator<< (ostream& os, myEnum& e);
{ return ( os << e.names[e.value] ); }


This is all well and good, but I would like to make this into an
abstract base class, so that for a specific type of MyEnum, you subclass
myEnum, and give the subclass its own static "names" array.
I would like to leave the operator<< function the same, if possible.

Ideally, I would like to be able to define a fully functional
subclass of myEnum in just one or two lines.

Can this be done?  If I don't declare the array in myEnum, this
operator<< function can't see it; if I do declare it, I can't
override it in subclasses.

I think I can see more or less skanky ways around this problem using
macros or specialized constructors; I am curious as to whether there
is any way to declare a static member that is different for every
subclass.


Ralph Melton
-- 
Ralph Melton			ralph@cs.stanford.edu
"Then ye shall know the truth, and the truth shall make you free."