[comp.lang.lisp.x] A few questions from a hacker.

L.Parkes@comp.vuw.ac.nz (Lloyd Parkes) (08/27/90)

I am currently working on an OO database engine for a MUD. I have
decided to use xlisp for this (I need OO more than database stuff).

I have a couple of questions though.

	1) Why does xset() call setvalue(), while xsetq() calls
	   xlsetvalue() to do it's work? As things stand at the
	   moment, set will only set the global value of a symbol.

	2) Why doesn't xlobget/setvalue search the ivars of the object
	   being sent the message, when looking for local bindings of
	   symbols? Why should it? I wanted to hack things for my OO
	   system. The way I have done it is to check the ivars of the
	   recieving object after the other ivars & cvars have been
	   checked. This means I may scope out a global symbol from a
	   method if a child class has an ivar with the same name, but
	   at least I won't scope out an ivar or cvar that used to be
	   in scope.

					Lloyd

p.s. I know #2 isn't all that wonderfull, but it does let you hack
things, particularly with #1.
p.p.s I am an xlisp neophyte, but I am very good at C.
--
------------------------------------------------------------------------
Lloyd Parkes		|
lloyd@comp.vuw.ac.nz	|
------------------------------------------------------------------------

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (08/28/90)

In article <1990Aug27.001721.9563@comp.vuw.ac.nz> L.Parkes@comp.vuw.ac.nz (Lloyd Parkes) writes:
>	2) Why doesn't xlobget/setvalue search the ivars of the object
>	   being sent the message, when looking for local bindings of
>	   symbols?

It does...

Through the miracle of gnuemacs tags (M-.) , I traced out the following
sequence of calls in xlisp 2.1:

(eval...)-->xleval()-->xlgetvalue()-->xlxgetvalue()-->xlobgetvalue():

[from xlsym.c]

|/* xlxgetvalue - get the value of a symbol */
|LVAL xlxgetvalue(sym)
|  LVAL sym;
|{
|    register LVAL fp,ep;
|    LVAL val;
|
|    /* check the environment list */
|    for (fp = xlenv; fp; fp = cdr(fp))
|
|	/* check for an instance variable */
+	if ((ep = car(fp)) && objectp(car(ep))) {
+	    if (xlobgetvalue(ep,sym,&val))
+		return (val);
|	}
|
|	/* check an environment stack frame */
|	else {
|	    for (; ep; ep = cdr(ep))
|		if (sym == car(car(ep)))
|		    return (cdr(car(ep)));
|	}
|
|    /* return the global value */
|    return (getvalue(sym));
|}

[from xlobj.c]

|/* xlobgetvalue - get the value of an instance variable */
|int xlobgetvalue(pair,sym,pval)
|  LVAL pair,sym,*pval;
|{
|    LVAL cls,names;
|    int ivtotal,n;
|
|    /* find the instance or class variable */
|    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {
|
|	/* check the instance variables */
|	names = getivar(cls,IVARS);
|	ivtotal = getivcnt(cls,IVARTOTAL);
|	for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
|	    if (car(names) == sym) {
|		*pval = getivar(car(pair),n);
|		return (TRUE);
|	    }
|	    names = cdr(names);
|	}
|
|	/* check the class variables */
|	names = getivar(cls,CVARS);
|	for (n = 0; consp(names); ++n) {
|	    if (car(names) == sym) {
|		*pval = getelement(getivar(cls,CVALS),n);
|		return (TRUE);
|	    }
|	    names = cdr(names);
|	}
|    }
|
|    /* variable not found */
|    return (FALSE);
|}

Note the lines above marked with '+'.

>	   Why should it?

Because otherwise, what's the point of having instance variables, or OOP,
for that matter.

As to your other questions, hopefully somebody else will answer, as I am
very busy.

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *

L.Parkes@comp.vuw.ac.nz (Lloyd Parkes) (08/30/90)

In article <5854@hplabsz.HPL.HP.COM> mayer@hplabsz.HPL.HP.COM (Niels Mayer) writes:

   In article <1990Aug27.001721.9563@comp.vuw.ac.nz> L.Parkes@comp.vuw.ac.nz (Lloyd Parkes) writes:
   >	2) Why doesn't xlobget/setvalue search the ivars of the object
   >	   being sent the message, when looking for local bindings of
   >	   symbols?

   It does...

[ lots of imported code deleted ]

The code in 2.1 only searches the instance variables of the class for
which the method is defined, not the object that is being sent the
message. This only crops up when you are playing around with super
classes and inheritance of methods. What I was doing was trying to
write a generic `set an instance variable' method for an entire class
heirarchy. After I had `fixed' xlisp, wasn't very difficult, just
yucky :-)

   As to your other questions, hopefully somebody else will answer, as I am
   very busy.

Aren't we all :-(

						Lloyd
--
------------------------------------------------------------------------
Lloyd Parkes		|	But like, what is the point man? I mean
lloyd@comp.vuw.ac.nz	|	what is the point?
------------------------------------------------------------------------

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (08/31/90)

In article <LLOYD.90Aug30111545@embassy.comp.vuw.ac.nz> L.Parkes@comp.vuw.ac.nz (Lloyd Parkes) writes:
>The code in 2.1 only searches the instance variables of the class for
>which the method is defined, not the object that is being sent the
>message. This only crops up when you are playing around with super
>classes and inheritance of methods. What I was doing was trying to
>write a generic `set an instance variable' method for an entire class
>heirarchy. After I had `fixed' xlisp, wasn't very difficult, just
>yucky :-)

I guess I misunderstood what you meant in your prev posting. In Xlisp,
Instance variables are part of an object instance; methods can access
instance variables of their class, and their superclasses; you send
messages to objects, and methods defined on the class or superclasses
"answer" the message...

If you are expecting methods on superclasses to be able to access instance
variables defined on subclasses, then you are not using the Xlisp object
system "correctly"...  maybe you need to be using a more complex object
system (e.g. CLOS) for the kind of things you are doing.

The following code works in the version of XLISP I'm using in Winterp-1.01
(which uses a modified XLISP 2.1):

| (setq class-0
|       (send Class :new
| 	    '(ivar-0)			;new instance vars
| 	    ))
| 
| (setq class-1
|       (send Class :new
| 	    '(ivar-1)			;new instance vars
| 	    '()				;no class vars
| 	    class-0))			;superclass
| 
| (setq class-2
|       (send Class :new
| 	    '(ivar-2)			;new instance vars
| 	    '()				;no class vars
| 	    class-1))			;superclass
| 
| (setq class-3
|       (send Class :new
| 	    '(ivar-3)			;new instance vars
| 	    '()				;no class vars
| 	    class-2))			;superclass
| 
| (send class-3 :answer :printout '()
|       '(
| 	(format T " ivar-0=~A\n ivar-1=~A\n ivar-2=~A\n ivar-3=~A\n"
| 		ivar-0 ivar-1 ivar-2 ivar-3)
| 	))
| 
| (send class-3 :answer :isnew '(v0 v1 v2 v3)
|       '(
| 	(setq ivar-0 v0)
| 	(setq ivar-1 v1)
| 	(setq ivar-2 v2)
| 	(setq ivar-3 v3)
| 	))
| 
| (setq inst0
|       (send class-3 :new 'just 'say 'no "to bugs")
|       )
| (setq inst1
|       (send class-3 :new 'means 'fight 'a "war on bugs")
|       )
| (setq inst2
|       (send class-3 :new 'if 'panama 'was "a police action")
|       )
| (setq inst3
|       (send class-3 :new 'why 'do 'they "call it a war on drugs?")
|       )
| 
| (send inst0 :printout)
| (send inst1 :printout)
| (send inst2 :printout)
| (send inst3 :printout)

The four :printout message-sends at the end give the following results...

: Xlisp-Eval-Result:  ivar-0=JUST
:  ivar-1=SAY
:  ivar-2=NO
:  ivar-3=to bugs
: Xlisp-Eval-Result:  ivar-0=MEANS
:  ivar-1=FIGHT
:  ivar-2=A
:  ivar-3=war on bugs
: Xlisp-Eval-Result:  ivar-0=IF
:  ivar-1=PANAMA
:  ivar-2=WAS
:  ivar-3=a police action
: Xlisp-Eval-Result:  ivar-0=WHY
:  ivar-1=DO
:  ivar-2=THEY
:  ivar-3=call it a war on drugs?

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *