Re: Making every goops object applicable

2012-05-15 Thread Ludovic Courtès
Hi,

Krister Svanlund krister.svanl...@gmail.com skribis:

 Apparently this works by some flag being set by applicable-strukt in
 libguile for the object and that flag is checked during application,
 calling the 'procedure slot if it's set with some optimization assuming
 that 'procedure is the first slot.

There’s also a vtable flag that determines whether a struct is
applicable:

  #define SCM_STRUCT_APPLICABLE_P(X)(SCM_STRUCT_VTABLE_FLAG_IS_SET ((X), 
SCM_VTABLE_FLAG_APPLICABLE))

And indeed, the struct’s procedure is the first slot:

  #define scm_applicable_struct_index_procedure 0 /* The procedure of an 
applicable
 struct. Only valid if the
 struct's vtable has the
 applicable flag set. */

For instance, every struct whose vtable is applicable-struct-vtable
(defined in struct.c) is applicable.

Then you can investigate by looking at the indices defined in struct.h:

  scheme@(guile-user) (struct-vtable? class)
  $2 = #t
  scheme@(guile-user) (struct-ref class 1) ; scm_vtable_index_flags
  $3 = 12291
  scheme@(guile-user) (logand $3 4)  ; 
SCM_VTABLE_FLAG_APPLICABLE_VTABLE
  $4 = 0  ; → not applicable

  scheme@(guile-user) (logand (struct-ref applicable-struct-vtable 1) 4)
  $7 = 4  ; → applicable

So you could fiddle with the flags of a class to make its instances
applicable:

  scheme@(guile-user) (define (applicable-struct? s)
 (logand 4 (struct-ref (struct-vtable (struct-vtable 
s)) 1)))
  scheme@(guile-user) (applicable-struct? current-input-port)
  $27 = 4
  scheme@(guile-user) (define (applicable-struct-procedure s) (struct-ref s 0))

  scheme@(guile-user) (define-class appclass (class) (foo))
  scheme@(guile-user) (struct-set! appclass 1 (logior (struct-ref appclass 
1) 4))
  $32 = 12295
  scheme@(guile-user) (define-class foo ()
 (bar #:init-value (lambda args (pk 'apply args)))
 #:metaclass appclass)
  $33 = #appclass foo 16e0d20
  scheme@(guile-user) (define f (make foo))
  scheme@(guile-user) (applicable-struct? f)
  $34 = 4
  scheme@(guile-user) (applicable-struct-procedure f)
  $35 = #procedure 1863060 at current input:51:0 args
  scheme@(guile-user) (f 1 2 3)

  ;;; (apply (1 2 3))
  $36 = (1 2 3)

But there should certainly be a higher-level facility.  :-)

Thanks,
Ludo’.




Re: Making every goops object applicable

2012-05-15 Thread Mark H Weaver
Krister Svanlund krister.svanl...@gmail.com writes:
 For example an instance of a class inheriting a class that inherits
 applicable-struct that defines 'procedure is not applicable.

Looking at the code, it is clear that in order for a GOOPS instance to
be applicable, it is not enough for applicable-struct to be a
superclass.  It is also necessary for the _metaclass_ of its class to
have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set.

One such metaclass is already built-in: applicable-struct-class, which
is the metaclass for applicable-struct, but if you'd like to define
your own metaclass for applicable objects, you can set the bit manually
on the metaclass as described by Ludovic.

However, keep in mind that the presence of that bit in the metaclass
indicates that the first slot of all instances _must_ be the procedure
slot.

 Mark



Re: Making every goops object applicable

2012-05-15 Thread Neil Jerram
Mark H Weaver m...@netris.org writes:

 Krister Svanlund krister.svanl...@gmail.com writes:
 For example an instance of a class inheriting a class that inherits
 applicable-struct that defines 'procedure is not applicable.

 Looking at the code, it is clear that in order for a GOOPS instance to
 be applicable, it is not enough for applicable-struct to be a
 superclass.  It is also necessary for the _metaclass_ of its class to
 have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set.

 One such metaclass is already built-in: applicable-struct-class, which
 is the metaclass for applicable-struct,

So the solution to Krister's problem is to make sure that every class
he's interested in is defined as

  (define-class whatnot (supers...)
...
#:metaclass applicable-struct-class)

Right?

 but if you'd like to define
 your own metaclass for applicable objects, you can set the bit manually
 on the metaclass as described by Ludovic.

Would this be needed, if the above works?

 However, keep in mind that the presence of that bit in the metaclass
 indicates that the first slot of all instances _must_ be the procedure
 slot.

Might the (define-class ... #:metaclass applicable-struct-class)
ensure that, by some kind of of compute-slots customisation...?  I took
a look but unfortunately couldn't see this in the code.

   Neil





Re: Making every goops object applicable

2012-05-15 Thread Mark H Weaver
Hi Neil!

Neil Jerram n...@ossau.homelinux.net writes:
 Mark H Weaver m...@netris.org writes:
 Krister Svanlund krister.svanl...@gmail.com writes:
 For example an instance of a class inheriting a class that inherits
 applicable-struct that defines 'procedure is not applicable.

 Looking at the code, it is clear that in order for a GOOPS instance to
 be applicable, it is not enough for applicable-struct to be a
 superclass.  It is also necessary for the _metaclass_ of its class to
 have the SCM_VTABLE_FLAG_APPLICABLE_VTABLE bit set.

 One such metaclass is already built-in: applicable-struct-class, which
 is the metaclass for applicable-struct,

 So the solution to Krister's problem is to make sure that every class
 he's interested in is defined as

   (define-class whatnot (supers...)
 ...
 #:metaclass applicable-struct-class)

 Right?

That was indeed my suggestion, though your comments below raise an
additional complication that I hadn't considered: some additional magic
will be needed to ensure that the 'procedure' slot comes first.

 but if you'd like to define
 your own metaclass for applicable objects, you can set the bit manually
 on the metaclass as described by Ludovic.

 Would this be needed, if the above works?

No, but since this is part of an effort to implement Python 3 in Guile,
it's possible that they may need to create their own metaclass for other
reasons.

 However, keep in mind that the presence of that bit in the metaclass
 indicates that the first slot of all instances _must_ be the procedure
 slot.

 Might the (define-class ... #:metaclass applicable-struct-class)
 ensure that, by some kind of of compute-slots customisation...?

I guess so, but I'm not convinced that this is the right approach.  It
now seems reasonably clear that GOOPS has poor support for applicable
objects, so we should think about a more proper solution that's easy to
use.

I don't see why applicable objects should need a custom metaclass.  In
general, it seems to me that features that require custom metaclasses do
not compose well.  Subclasses of applicable-struct should just work
without users resorting to these hacks.

As I've suggested before, the most elegant solution I can think of is to
simply make a two-argument generic function called something like
'generic-apply'.  I suspect that there's some clever way to make this
very fast using the MOP, but I have yet to work out the details.
Unfortunately my copy of AMOP is 50 miles away at the moment.

Suggestions solicited, and if anyone wants to take the lead on this,
I'd be grateful.  If not, I'll try to come up with something.

 Thanks,
   Mark