From: Joachim De Beule
Subject: structur(e)(al) question
Date: 
Message-ID: <l33dis35uw.fsf@arti6.vub.ac.be>
Hello all,

Here is my simplified problem:

I want to define a structure with some slots dynamicaly depending on some
others.  

A simple example would be:

   (defstruct S
	(a 5)
	(f #'(lambda (x) (+ x a))))

the f-slot depends on the a-slot.

Now if I do a 

   (setf test (make-s))

this works fine:

   (funcall (s-f test) 5) => 10.

But now the troubles begin.

1) If I should do a 

      (setf (s-a test) 7)

   I want (funcall (s-f test) 5) to return 12 instead of 10, so f
   does not take the current value for a which is my first problem

2) If I should do a
   
      (setf (s-f test) #'(lambda (x) (* x a)))

   I want this new f to take the (s-a test) for a but it does not
   which is my second, related problem.

Now for the question:

How can this be done if at all ? Is there some variable *self* that
can be used within a structure and points to itself ? 
I know I could do 2) with a detour like

   (setf (s-f test) #'(lambda (x) (* x (s-a test))))

but I would rather make it go automatically.  In addition, this still does
not solve problem 1).

Thanks, Joachim.

From: Marco Antoniotti
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <y6cvgvobjeb.fsf@octagon.mrl.nyu.edu>
Joachim De Beule <·······@arti.vub.ac.be> writes:

> Hello all,
> 
> Here is my simplified problem:
> 
> I want to define a structure with some slots dynamicaly depending on some
> others.  
> 
> A simple example would be:
> 
>    (defstruct S
> 	(a 5)
> 	(f #'(lambda (x) (+ x a))))
> 
> the f-slot depends on the a-slot.
> 
> Now if I do a 
> 
>    (setf test (make-s))
> 
> this works fine:
> 
>    (funcall (s-f test) 5) => 10.
> 
> But now the troubles begin.
> 
> 1) If I should do a 
> 
>       (setf (s-a test) 7)
> 
>    I want (funcall (s-f test) 5) to return 12 instead of 10, so f
>    does not take the current value for a which is my first problem
> 
> 2) If I should do a
>    
>       (setf (s-f test) #'(lambda (x) (* x a)))
> 
>    I want this new f to take the (s-a test) for a but it does not
>    which is my second, related problem.
> 
> Now for the question:
> 
> How can this be done if at all ? Is there some variable *self* that
> can be used within a structure and points to itself ? 
> I know I could do 2) with a detour like
> 
>    (setf (s-f test) #'(lambda (x) (* x (s-a test))))
> 
> but I would rather make it go automatically.  In addition, this still does
> not solve problem 1).

I would define a generic function

(defstruct S (a 5))

(defgeneric s-f (the-s x)
  (:method ((the-s S) x) (* x (s-a the-s))))

Cheers

-- 
Marco Antoniotti =============================================================
NYU Bioinformatics Group			 tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                          fax  +1 - 212 - 995 4122
New York, NY 10003, USA				 http://galt.mrl.nyu.edu/valis
             Like DNA, such a language [Lisp] does not go out of style.
			      Paul Graham, ANSI Common Lisp
From: Rainer Joswig
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <joswig-0B78CA.16400022092000@news.is-europe.net>
In article <··············@arti6.vub.ac.be>, Joachim De Beule 
<·······@arti.vub.ac.be> wrote:

> A simple example would be:
> 
>    (defstruct S
> 	(a 5)
> 	(f #'(lambda (x) (+ x a))))
> 
> the f-slot depends on the a-slot.

Not really.

>    (setf test (make-s))

The A in your function is the keyword variable A of MAKE-S .

> How can this be done if at all ? Is there some variable *self* that
> can be used within a structure and points to itself ? 

Since a structure is just like a vector of named slots there
is nothing like *SELF*. Functions and Structures don't have
anything to do with each other. Structures don't
make a namespace for functions and functions are not defined
"inside" of structures.

I guess you would need to define a DEFSTRUCT* ;-),
which does what you want.

-- 
Rainer Joswig, Hamburg, Germany
Email: ·············@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/
From: Joachim De Beule
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <l31yyc31r0.fsf@arti6.vub.ac.be>
Ok, here is something that more or less does what I want but it is
very messy I think which is like a sign to me that I am not on the
right track.  So I still would like to know if and why I am on the wrong
track, if lisp has some ways to do this automaticaly.

 (defun make-S (&key (a 3) 
                     (f #'(lambda (x p) (+ p x))))
   (let ((ia a)
	 (if f))
     #'(lambda (dispatch &optional arg)
	 (case dispatch
	   ('get-a ia)
	   ('get-f #'(lambda (x) (funcall if x ia)))
	   ('set-a (setf ia arg))
	   ('set-f (setf if arg))))))

 (defun S-a (S) (funcall S 'get-a))
 (defun S-f (S) (funcall S 'get-f))
 (defsetf S-a (S) (av)
   `(funcall ,S 'set-a ,av))
 (defsetf S-f (S) (fv)
   `(funcall ,S 'set-f ,fv))

Now I have the same functions I wanted using the defstruct, namely
make-S, S-a, S-f and two setf forms.  This time changing a with 
(setf (S-a test) 3) will also change the result of a funcall to (S-f
test).  
BUT.  If I want to change f with (setf (S-f test) new-closure) I need
to make the new-closure a function of two variables in it's arguments
list which is kind of unlikking it with the specific value of this
argument within the structure.  

I hope I make some sense to someone somewhere.

cheers, Joachim.
From: Marco Antoniotti
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <y6cbsxgibwp.fsf@octagon.mrl.nyu.edu>
Joachim De Beule <·······@arti.vub.ac.be> writes:

> Ok, here is something that more or less does what I want but it is
> very messy I think which is like a sign to me that I am not on the
> right track.  So I still would like to know if and why I am on the wrong
> track, if lisp has some ways to do this automaticaly.

Why do you need this?  Really, why do you need a function in a
defstruct?

>  (defun make-S (&key (a 3) 
>                      (f #'(lambda (x p) (+ p x))))
>    (let ((ia a)
> 	 (if f))
>      #'(lambda (dispatch &optional arg)
> 	 (case dispatch
> 	   ('get-a ia)
> 	   ('get-f #'(lambda (x) (funcall if x ia)))
> 	   ('set-a (setf ia arg))
> 	   ('set-f (setf if arg))))))
> 
>  (defun S-a (S) (funcall S 'get-a))
>  (defun S-f (S) (funcall S 'get-f))
>  (defsetf S-a (S) (av)
>    `(funcall ,S 'set-a ,av))
>  (defsetf S-f (S) (fv)
>    `(funcall ,S 'set-f ,fv))

Ok.  this is a good exercise in building your own semi-oo system, but
again, why?  In Common Lisp you have alternative ways of achieving the
same effect in a more elegant way.

Cheers


-- 
Marco Antoniotti =============================================================
NYU Bioinformatics Group			 tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                          fax  +1 - 212 - 995 4122
New York, NY 10003, USA				 http://galt.mrl.nyu.edu/valis
             Like DNA, such a language [Lisp] does not go out of style.
			      Paul Graham, ANSI Common Lisp
From: Eugene Zaikonnikov
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <6y1yyca3ub.fsf@localhost.localdomain>
* "Joachim" == Joachim De Beule <·······@arti.vub.ac.be> writes:

Joachim>  Hello all, Here is my simplified problem:

Joachim>  I want to define a structure with some slots dynamicaly
Joachim>  depending on some others.

Joachim>  A simple example would be:
Joachim>  (defstruct S (a 5) (f #'(lambda (x) (+ x a))))
Joachim>  the f-slot depends on the a-slot.

You've taken a wrong approach; I believe the consequence of funcalling
F is undefined. While your particular compiler may create closure over
structure member A on instantiation, others may (and CMUCL actualy
does) raise error about A being unbound.

What you are actually doing is attempting to define a method for a
structure. Why don't you want to use classes instead?

(defclass foo ()
  ((a :initform 5)))

(defmethod f ((ins foo) x)
    (+ (slot-value ins 'a) x))

(setq qux (make-instance 'foo))

* (f qux 5)
10
* (f qux 7)
12

-- 
  Eugene
From: David Bakhash
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <m3g0msgszr.fsf@cadet.dsl.speakeasy.net>
Eugene Zaikonnikov <······@cit.org.by> writes:

> Joachim>  I want to define a structure with some slots dynamicaly
> Joachim>  depending on some others.
> 
> You've taken a wrong approach [...]

yes.  no doubt that CLOS is the way to do this the right way.

The real question is, though:

Is there a way to have a beefed-up DEFSTRUCT-like construct in which
you can refer to `(THIS)', such as:

(defstruct* person
  (age 0)
  (years-left-to-live-function #'(lambda ()
                                   (- +maximum-lifespan+
                                      (person-age (this))))))

I really feel at a loss.  I don't know how one would do this
elegantly, and I'm really interested in seeing how some of the more
expert Lisp programmers would do it.

dave
From: Barry Margolin
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <vyRy5.71$NM4.2811@burlma1-snr2>
In article <··············@cadet.dsl.speakeasy.net>,
David Bakhash  <·····@alum.mit.edu> wrote:
>The real question is, though:
>
>Is there a way to have a beefed-up DEFSTRUCT-like construct in which
>you can refer to `(THIS)', such as:

No, there's nothing built-in that does that.  Structures are just ways to
give names to slots in a piece of memory, nothing more.  They don't create
any kind of lexical environment.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Eugene Zaikonnikov
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <6yu2b77wqh.fsf@localhost.localdomain>
* "David" == David Bakhash <·····@alum.mit.edu> writes:

[...]

David>  The real question is, though:

David>  Is there a way to have a beefed-up DEFSTRUCT-like construct in
David>  which you can refer to `(THIS)', such as:

David>  (defstruct* person (age 0) (years-left-to-live-function
David>  #'(lambda () (- +maximum-lifespan+ (person-age (this))))))

Well, I can't invent an _elegant_ solution, but that is doable with
some nasty macrology:

;;; Illustrative; put GENSYMs where appropriate if you like
(defmacro defstruct* (name &rest slots)
  (let* ((instantiation-slots nil)
	 (just-slots
	  (loop for slot in slots
		collecting (if (and (listp (second slot))
				    (eq 'function (first (second slot))))
			       (progn
				 (push slot instantiation-slots)
				 (list (first slot) nil))
			     slot))))
    `(progn
       (defstruct ,name ,@just-slots)
       (defmacro ,(intern (concatenate 'string (symbol-name 'make-) (symbol-name name) "*"))
	 ()
	 `(let* ((struct (funcall (function ,(intern (concatenate 'string (symbol-name 'make-) (symbol-name ',name))))))
		 (%this% struct))
	    ,@(loop for instance-slot in ',instantiation-slots
		    collecting
		    (list 'setf
			  (list (intern (concatenate 'string (symbol-name ',name) "-" (symbol-name (first instance-slot))))
				'struct)
			     (second instance-slot)))
	    struct)))))

(defstruct* foo (a 5) (b #'(lambda (x) (+ x (foo-a %this%)))))
(setq bar (make-foo*))

* (funcall (foo-b bar) 5)
10
* (setf (foo-a bar) 7)
7
* (funcall (foo-b bar) 5)
12
* 

Basically, we delegate methods definition to our own make-...* macro,
which binds %this% to a structure instance. However, this solution has
obvious drawback of being unable to handle methods redefinition. This
can be solved too, although I fail to see any reasons for why should we
mimic C++ object system when we have a real one.

-- 
  Eugene
From: Ola Rinta-Koski
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <wk1yya2h3i.fsf@ANJOVIS.i-did-not-set--mail-host-address--so-shoot-me>
Eugene Zaikonnikov <······@cit.org.by> writes:
> * "David" == David Bakhash <·····@alum.mit.edu> writes:
> David>  Is there a way to have a beefed-up DEFSTRUCT-like construct in
> David>  which you can refer to `(THIS)', such as:

> Well, I can't invent an _elegant_ solution, but that is doable with
> some nasty macrology:

  I have another, slightly related question. How would I go about
  defining a macro such that

  (defclass* foo ()
    (bar baz bat))

  would be equal to

  (defclass foo ()
    ((bar :accessor bar :initarg :bar :initform nil)
     (baz :accessor baz :initarg :baz :initform nil)
     (bat :accessor bat :initarg :bat :initform nil)))

  ?

  I find I'm constantly writing class definitions like the above,
  which strikes me as overly verbose.
-- 
  Some people just prove that human procreation is too cheap.
	-- Erik Naggum
From: Pierre R. Mai
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <87aecyq8fo.fsf@orion.bln.pmsf.de>
Ola Rinta-Koski <···@iki.fi.REMOVE.THIS> writes:

> Eugene Zaikonnikov <······@cit.org.by> writes:
> > * "David" == David Bakhash <·····@alum.mit.edu> writes:
> > David>  Is there a way to have a beefed-up DEFSTRUCT-like construct in
> > David>  which you can refer to `(THIS)', such as:
> 
> > Well, I can't invent an _elegant_ solution, but that is doable with
> > some nasty macrology:
> 
>   I have another, slightly related question. How would I go about
>   defining a macro such that
> 
>   (defclass* foo ()
>     (bar baz bat))
> 
>   would be equal to
> 
>   (defclass foo ()
>     ((bar :accessor bar :initarg :bar :initform nil)
>      (baz :accessor baz :initarg :baz :initform nil)
>      (bat :accessor bat :initarg :bat :initform nil)))
> 
>   ?
> 
>   I find I'm constantly writing class definitions like the above,
>   which strikes me as overly verbose.

Writing the macro is fairly simple:

(defmacro defclass* (name (&rest supers) (&rest slots) &rest options)
  `(defclass ,name ,supers
     ,(loop for slot in slots
            for key = (intern (symbol-name slot) "KEYWORD")
            collect
            `(,slot :accessor ,slot :initarg ,key :initform nil))
     ,@options))

The harder question is whether you should use a macro for this, and
not some editor code, or to put it another way:  Do you think that a
macro like this will increase _readability_, or only ease of writing:
I find that if some abbreviation only increses ease of writing, then
it should be handled by some slick editor macro, whereas abstractions
that increase ease of reading and provide more insight into the
intent behind some code should be handled by the macro system.

Letting the editor expand your short-hand for you will also allow you
to easily override the defaults (like the value of the :initform)
without rewriting the whole form or introducing yet more complex
macros.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Eugene Zaikonnikov
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <6yog1e7ys2.fsf@localhost.localdomain>
* "Ola" == Ola Rinta-Koski <···@iki.fi.REMOVE.THIS> writes:

[...]

Ola>  I have another, slightly related question. How would I go about
Ola>  defining a macro such that

Ola>  (defclass* foo () (bar baz bat))

Ola>  would be equal to

Ola>  (defclass foo () ((bar :accessor bar :initarg :bar :initform
Ola>  nil) (baz :accessor baz :initarg :baz :initform nil) (bat
Ola>  :accessor bat :initarg :bat :initform nil)))

Hmm... I recall this one was once asked and answered already, but as I
can't find the answer through Deja...

(defmacro defclass* (name ancestors slots)
  `(defclass ,name ,ancestors
     ,(loop for slot in slots
	    collecting
	    (if (or (atom slot)
		    (cdr slot))
		slot
	      (list (car slot)
		    :accessor (car slot)
		    :initarg (intern (symbol-name (car slot)) "KEYWORD")
		    :initform nil)))))

* (defclass* baz () (a (b :accessor the-b :initform 3) (c) (d)))
#<STANDARD-CLASS BAZ {48162C65}>
* (setq qq (make-instance 'baz :c 'dummy))
#<BAZ {482E1D3D}>
* (the-b qq)
3
* (c qq)
DUMMY
* (d qq)
NIL
* (slot-value qq 'a)

The slot A is unbound in the object #<BAZ {482D13C5}>


Hope this helps, 
           Eugene.
From: Tim Bradshaw
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <ey33dio8n50.fsf@cley.com>
* David Bakhash wrote:

> Is there a way to have a beefed-up DEFSTRUCT-like construct in which
> you can refer to `(THIS)', such as:

I had something that kind of did this with CLOS.  It defined a
metaclass (I think), instances (classes) of which could have
delayed-initialisation functions, for slots, which got passed a single
argument which was the instance (of the class), and whose result then
got stored into the slot.

This kind of works, except if you have two delayed-initialisation
slots then it would be nice for the system to be able to establish an
ordering so that things will work.  To do that `right' I think you
need to codewalk the initialisation form to establish what slots it
depends on, build a dependency graph, check that it's a DAG, and then
construct a form which initialises things in the right order.

This is all quite doable in Lisp of course, but it's not trivial work.
I think that David Coopers GDL system does something like this.

--tim
From: Thomas A. Russ
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <ymid7hstd8b.fsf@sevak.isi.edu>
Eugene Zaikonnikov <······@cit.org.by> writes:

> What you are actually doing is attempting to define a method for a
> structure. Why don't you want to use classes instead?
>
> (defclass foo ()
>   ((a :initform 5)))
>
> (defmethod f ((ins foo) x)
>     (+ (slot-value ins 'a) x))
> (setq qux (make-instance 'foo))
> 
> * (f qux 5)
> 10
> * (f qux 7)
> 12

Actually, you can define methods for structs as well as classes, so one
could also just do:

(defstruct foo (a 5))

(defmethod f ((ins foo) x)
  (+ (foo-a ins) x))

(setq qux (make-foo))

* (f qux 5)
10
* (f qux 7)
12


-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Eugene Zaikonnikov
Subject: Re: structur(e)(al) question
Date: 
Message-ID: <6yn1gwggpg.fsf@localhost.localdomain>
* "Thomas" == Thomas A Russ <···@sevak.isi.edu> writes:

Thomas>  Eugene Zaikonnikov <······@cit.org.by> writes:
>> What you are actually doing is attempting to define a method for a
>> structure. Why don't you want to use classes instead?
>> 
>> (defclass foo () ((a :initform 5)))
>> 
>> (defmethod f ((ins foo) x) (+ (slot-value ins 'a) x)) (setq qux
>> (make-instance 'foo))
>> 
>> * (f qux 5) 10 * (f qux 7) 12

Thomas>  Actually, you can define methods for structs as well as
Thomas>  classes, so one could also just do:

Thomas>  (defstruct foo (a 5))

Thomas>  (defmethod f ((ins foo) x) (+ (foo-a ins) x))

You're right of course. After a bit of reflection I can't find out why
I insisted on classes.

-- 
  Eugene