unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* GOOPS-based SRFI-35 implementation
@ 2004-02-28 15:53 Andreas Rottmann
  2004-03-03 16:02 ` Neil Jerram
  0 siblings, 1 reply; 8+ messages in thread
From: Andreas Rottmann @ 2004-02-28 15:53 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 1224 bytes --]

Hi!

I just wanted to announce that I've been working a bit on a
GOOPS-based implementation of SRFI-35 ("Conditions"). It seems to
basically work, except compound conditions, which are not-yet
implemented. My implementation is based on the SRFI reference
implementation, but differs a good deal because it uses GOOPS classes
instead of SRFI-9 ("Defining record types"). 

Right now, the thing lives in the module (itla srfi-35), since my iTLA
thingy[0] will use it. I'd like comments:

[0] http://yi.org/rotty/ITLA

* On issues with the code

* How to proceed to get this into Guile

* How I can ship it with iTLA in a way that's compatible with both
  Guile versions that don't come with this SRFI and Guile CVS (which
  might come with it in the near future /mehopes). I thought
  installing it into /usr/[local/]guile/srfi/srfi-35.scm might work,
  since this will be used if there is no such module in
  /usr/[local/]guile/1.X/srfi and the one in Guile will be prefered if
  present.

* Everything else that matters (or doesn't ;-)

The latest & greatest code is always available via Arch (see [0]),
though I've attached the code and test cases (basically the examples
in the SRFI; non-working stuff is commented out).


[-- Attachment #2: srfi-35.scm --]
[-- Type: text/plain, Size: 6162 bytes --]

(define-module (itla srfi-35)
  #:use-module (oop goops)
  #:use-module (oop goops util)
  #:use-module (srfi srfi-1)

  ;; (oop goops util) and (srfi srfi-1) both define any, every
  #:duplicates last
  
  #:export (make-condition-type
            condition-type? condition? condition-has-type?
            condition-ref
            make-condition make-compound-condition
            extract-condition
            &condition &message &error )
  #:export-syntax (define-condition-type condition))

(define-class <condition-meta> (<class>))
  
(define-class <condition> ()
  (%name #:accessor condition-type-name)
  #:metaclass <condition-meta>)

(define (condition-type? thing)
  (is-a? thing <condition-meta>))

(define (condition-type-all-fields type)
  (fold-right (lambda (slot lst)
                (let ((name (car slot)))
                  (if (eq? name '%name)
                      lst
                      (cons name lst))))
              '()
              (class-slots type)))

(define (make-condition-type name supertype fields)
  (if (not (symbol? name))
      (error "make-condition-type: name is not a symbol"
             name))
  (if (not (condition-type? supertype))
      (error "make-condition-type: supertype is not a condition type"
             supertype))
  (if (not
       (null? (lset-intersection eq?
                                 (condition-type-all-fields supertype)
                                 fields)))
      (error "make-condition-type: duplicate field name" ))
  
  (make-class (list supertype) (map list fields) #:name name))

(define-macro (define-condition-type ?name ?supertype ?predicate . ?field-acc)
  `(begin
     (define ,?name
       (make-condition-type ',?name
                            ,?supertype
                            (map car ',?field-acc)))
     (define (,?predicate thing)
        (and (condition? thing)
             (condition-has-type? thing ,?name)))
     ,@(map
        (lambda (f-a)
          ;;(format #t "defining accesor: ~S\n" (cadr f-a))
          `(define (,(cadr f-a) condition)
             (condition-ref (extract-condition condition ,?name)
                            ',(car f-a))))
        ?field-acc)))

;; Stolen from oop/goops.scm
(define (list2set l)	       
  (let loop ((l l)
	     (res '()))
    (cond		       
     ((null? l) res)
     ((memq (car l) res) (loop (cdr l) res))
     (else (loop (cdr l) (cons (car l) res))))))

;; This should be in goops.scm, really
(define-public (class-supers c)
  (letrec ((allsubs (lambda (c)
		      (cons c (mapappend allsubs
					 (class-direct-supers c))))))
    (list2set (cdr (allsubs c)))))

(define (condition-subtype? subtype supertype)
  (or (equal? subtype supertype)
      (memq supertype (class-supers subtype))))

(define (condition-type-field-supertype condition-type field)
  (let loop ((condition-type condition-type))
    (cond ((not condition-type) #f)
          ((memq field (condition-type-fields condition-type))
           condition-type)
          (else
           (loop (condition-type-supertype condition-type))))))

(define (condition? thing)
  (is-a? thing <condition>))

(define (make-condition type . field-plist)
  (let ((alist (let loop ((plist field-plist))
                 (if (null? plist)
                            '()
                     (cons (cons (car plist)
                                 (cadr plist))
                           (loop (cddr plist)))))))
    (if (not (lset= eq?
                    (condition-type-all-fields type)
                    (map car alist)))
        (error "condition fields don't match condition type"
               (condition-type-all-fields type) (map car alist)))
    (let ((condition (make type)))
      (for-each (lambda (pr)
                  (slot-set! condition (car pr) (cdr pr)))
               alist)
      condition)))

(define (condition-has-type? condition type)
  (if
   (any (lambda (has-type)
          (condition-subtype? has-type type))
        (condition-types condition))
  #t #f))

(define condition-ref slot-ref)

(define (type-field-alist-ref type-field-alist field)
  (let loop ((type-field-alist type-field-alist))
    (cond ((null? type-field-alist)
           (error "type-field-alist-ref: field not found"
                  type-field-alist field))
          ((assq field (cdr (car type-field-alist)))
           => cdr)
          (else
           (loop (cdr type-field-alist))))))

(define-class <compound-condition> (<condition>)
  (%components #:init-keyword #:components))

(define (make-compound-condition condition-1 . conditions)
  (if (null? conditions)
      condition-1
      (make <compound-condition>
        #:components (cons condition-1 conditions))))

(define (extract-condition condition type)
    (if (not (condition-subtype? (class-of condition) type))
        (error "extract-condition: invalid condition type"
                      condition type))
    condition)

(define-macro (condition . forms)
  ;; forms: (type1 (field1 value1) ...) ...)
  `(make-compound-condition
    ,@(map
       (lambda (form)
         `(make-condition
           ,(car form)
           ,@(fold (lambda (entry lst)
                     (cons `(quote ,(car entry)) (cons (cadr entry) lst)))
                   '()
                   (cdr form))))
       forms)))

(define (type-field-alist->condition type-field-alist)
  (really-make-condition
   (map (lambda (entry)
          (cons (car entry)
                (map (lambda (field)
                       (or (assq field (cdr entry))
                           (cons field
                                 (type-field-alist-ref type-field-alist field))))
                     (condition-type-all-fields (car entry)))))
        type-field-alist)))

(define (condition-types condition)
  (let ((own-class (class-of condition)))
    (cons own-class (class-direct-supers own-class))))

(define &condition <condition>)

(define-condition-type &message &condition
  message-condition?
  (message condition-message))

(define-condition-type &serious &condition
  serious-condition?)

(define-condition-type &error &serious
  error?)

;;; arch-tag: 1145fba2-0008-4c99-8304-a53cdcea50f9

[-- Attachment #3: srfi-35.test --]
[-- Type: text/plain, Size: 1926 bytes --]

#!/bin/sh
exec ${srcdir:-.}/guile-test-env guile -s "$0" "$@"
!#

(define-module (test-suite test-srfi-35)
  #:use-module (itla srfi-35)
  #:use-module (test-suite lib))

(define-condition-type &c &condition
  c?
  (x c-x))

(define-condition-type &c1 &c
  c1?
  (a c1-a))

(define-condition-type &c2 &c
  c2?
  (b c2-b))

(define v1 (make-condition &c1 'x "V1" 'a "a1"))
(define v2 (condition (&c2 (x "V2") (b "b2"))))
; (define v3 (condition (&c1 (x "V3/1") (a "a3"))
;                       (&c2 (b "b3"))))


(with-test-prefix "condition of type &c1"
  (pass-if "supertype predicate" (c? v1))
  (pass-if "predicate" (c1? v1))
  (pass-if "sibling predicate" (not (c2? v1)))
  (pass-if "parent field accessor" (string=? (c-x v1) "V1"))
  (pass-if "field accessor" (string=? (c1-a v1) "a1")))
  

(with-test-prefix "condition of type &c2"
  (pass-if "supertype predicate" (c? v2))
  (pass-if "predicate" (c2? v2))
  (pass-if "sibling predicate" (not (c1? v2)))
  (pass-if "parent field accessor" (string=? (c-x v2) "V2"))
  (pass-if "field accessor" (string=? (c2-b v2) "b2")))

; (with-test-prefix "condition of compound type (&c1 &c2)"
;   (pass-if "supertype predicate" (c? v2))
;   (pass-if "c1 predicate" (c1? v2))
;   (pass-if "c2 predicate" (c2? v2))
;   (pass-if "parent field accessor" (string=? (c-x v2) "V3/1"))
;   (pass-if "c1 field accessor" (string=? (c1-a v2) "a3"))
;   (pass-if "c2 field accessor" (string=? (c2-b v2) "b3")))

; (define v4 (make-compound-condition v1 v2))

; (c? v4)        => #t
; (c1? v4)       => #t
; (c2? v4)       => #t
; (c-x v4)       => "V1"
; (c1-a v4)      => "a1"
; (c2-b v4)      => "b2"

; (define v5 (make-compound-condition v2 v3))

; (c? v5)        => #t
; (c1? v5)       => #t
; (c2? v5)       => #t
; (c-x v5)       => "V2"
; (c1-a v5)      => "a3"
; (c2-b v5)      => "b2"

;; Local Variables:
;; mode: scheme
;; End:

;;; arch-tag: 774c4de9-d9f8-4754-8d40-38912ec7f3a1

[-- Attachment #4: Type: text/plain, Size: 270 bytes --]


Cheers, Andy
-- 
Andreas Rottmann         | Rotty@ICQ      | 118634484@ICQ | a.rottmann@gmx.at
http://yi.org/rotty      | GnuPG Key: http://yi.org/rotty/gpg.asc
Fingerprint              | DFB4 4EB4 78A4 5EEE 6219  F228 F92F CFC5 01FD 5B62

Make free software, not war!

[-- Attachment #5: Type: text/plain, Size: 139 bytes --]

_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-02-28 15:53 GOOPS-based SRFI-35 implementation Andreas Rottmann
@ 2004-03-03 16:02 ` Neil Jerram
  2004-03-04  0:20   ` Andreas Rottmann
  0 siblings, 1 reply; 8+ messages in thread
From: Neil Jerram @ 2004-03-03 16:02 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Andreas Rottmann <a.rottmann@gmx.at> writes:

> Hi!
> 
> I just wanted to announce that I've been working a bit on a
> GOOPS-based implementation of SRFI-35 ("Conditions"). It seems to
> basically work, except compound conditions, which are not-yet
> implemented. My implementation is based on the SRFI reference
> implementation, but differs a good deal because it uses GOOPS classes
> instead of SRFI-9 ("Defining record types"). 

Without having looked yet at your code, I think this is nice, because
it ties in with my general thoughts on how we might enhance Guile's
existing errors and exceptions and unify them with the proposals in
SRFIs 34, 35 etc.

So perhaps this is a good time to share and discuss those thoughts.
In my view there are two main problems with Guile's current
errors/exceptions.

- A given error/exception - i.e. a collection of throw args - is not
  at all self-describing as regards how the catcher should deal with
  it, print an error message, etc.

- There is no way to say sthg like "I want to catch all system
  errors", or "all numerical erros".

I think the solution to both these is that an error/exception should
be an instance of a GOOPS error/exception class (+ subclasses).  The
first problem is then solved by the class slots showing what
information is available about the error/exception, and class methods
to - for example - print a human-readable message describing the
error/exception.  The second problem is solved by arranging
error/exception classes in an inheritance hierarchy, and enhancing
`catch' so that it catches all errors/exceptions that satisfy `(is-a?
KEY)'.

If this is accepted, I further think that the errors/exceptions in the
new class hierarchy should be identical with the conditions specified
by SRFI-35.  Therefore, for example, `make-condition' would create and
return a GOOPS error/exception class and, given a
error/exception/condition object OBJ, `(condition-has-type? OBJ TYPE)'
would be identical to `(is-a? OBJ TYPE)'.

Even further, I think it follows that `throw' can become identical to
SRFI-34's `raise', with back-compatibility preserved by translating

  (throw KEY . ARGS)

to something like

  (throw (make <legacy-exception> #:key KEY #:args ARGS))

Finally, `catch' could be enhanced so that its KEY is either #t, a
symbol (legacy case) or an error/exception class; and SRFI-34's
`with-exception-handler' and `guard' provide different catching and
handler semantics, but operating on the same kind of
error/exception/condition objects.

Any comments?

        Neil


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-03 16:02 ` Neil Jerram
@ 2004-03-04  0:20   ` Andreas Rottmann
  2004-03-06 12:05     ` Neil Jerram
  0 siblings, 1 reply; 8+ messages in thread
From: Andreas Rottmann @ 2004-03-04  0:20 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Neil Jerram <neil@ossau.uklinux.net> writes:

> Andreas Rottmann <a.rottmann@gmx.at> writes:
>
>> Hi!
>> 
>> I just wanted to announce that I've been working a bit on a
>> GOOPS-based implementation of SRFI-35 ("Conditions"). It seems to
>> basically work, except compound conditions, which are not-yet
>> implemented. My implementation is based on the SRFI reference
>> implementation, but differs a good deal because it uses GOOPS classes
>> instead of SRFI-9 ("Defining record types"). 
>
> Without having looked yet at your code, I think this is nice, because
> it ties in with my general thoughts on how we might enhance Guile's
> existing errors and exceptions and unify them with the proposals in
> SRFIs 34, 35 etc.
>
> So perhaps this is a good time to share and discuss those thoughts.
> In my view there are two main problems with Guile's current
> errors/exceptions.
>
> - A given error/exception - i.e. a collection of throw args - is not
>   at all self-describing as regards how the catcher should deal with
>   it, print an error message, etc.
>
> - There is no way to say sthg like "I want to catch all system
>   errors", or "all numerical erros".
>
I've thought of this, too; this was my reason to use GOOPS in the
first place.

> I think the solution to both these is that an error/exception should
> be an instance of a GOOPS error/exception class (+ subclasses).  The
> first problem is then solved by the class slots showing what
> information is available about the error/exception, and class methods
> to - for example - print a human-readable message describing the
> error/exception.
>
So far, this is all implemented in my srfi-35 stuff as in my
Archive. I have additionally exported a handle-condition generic,
whose methods call (error "unhandled foo"), foo being an error
condition, message, serious condition. Also, there is a class
&compound-condition which doesn't exist in the SRFI (so methods for
compund conditions can be defined). Plus, there is a macro
guard/handle, which calls handle-condition:

(define-method (handle-method (&foobar-condition c))
 ...)

(guard/handle
  (some-code-that-maz-be-foobar))

>  The second problem is solved by arranging
> error/exception classes in an inheritance hierarchy, and enhancing
> `catch' so that it catches all errors/exceptions that satisfy `(is-a?
> KEY)'.
>
First part (inheritance hierarchy) also done.

> If this is accepted, I further think that the errors/exceptions in the
> new class hierarchy should be identical with the conditions specified
> by SRFI-35.  Therefore, for example, `make-condition' would create and
> return a GOOPS error/exception class and, given a
> error/exception/condition object OBJ, `(condition-has-type? OBJ TYPE)'
> would be identical to `(is-a? OBJ TYPE)'.
>
I'd have to specialize is-a? for this, since compound conditions all
share a class.

> Even further, I think it follows that `throw' can become identical to
> SRFI-34's `raise', with back-compatibility preserved by translating
>
>   (throw KEY . ARGS)
>
> to something like
>
>   (throw (make <legacy-exception> #:key KEY #:args ARGS))
>
> Finally, `catch' could be enhanced so that its KEY is either #t, a
> symbol (legacy case) or an error/exception class; and SRFI-34's
> `with-exception-handler' and `guard' provide different catching and
> handler semantics, but operating on the same kind of
> error/exception/condition objects.
>
> Any comments?
>
Sounds like a good plan, especially since it's been about that what I
was after ;-)

Cheers, Andy
-- 
Andreas Rottmann         | Rotty@ICQ      | 118634484@ICQ | a.rottmann@gmx.at
http://yi.org/rotty      | GnuPG Key: http://yi.org/rotty/gpg.asc
Fingerprint              | DFB4 4EB4 78A4 5EEE 6219  F228 F92F CFC5 01FD 5B62

Python is executable pseudocode, Perl is executable line-noise.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-04  0:20   ` Andreas Rottmann
@ 2004-03-06 12:05     ` Neil Jerram
  2004-03-06 14:52       ` Andreas Rottmann
  2004-03-08 20:07       ` Andreas Rottmann
  0 siblings, 2 replies; 8+ messages in thread
From: Neil Jerram @ 2004-03-06 12:05 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Andreas Rottmann <a.rottmann@gmx.at> writes:

> Neil Jerram <neil@ossau.uklinux.net> writes:
> 
> > Andreas Rottmann <a.rottmann@gmx.at> writes:
> >
> I've thought of this, too; this was my reason to use GOOPS in the
> first place.

Great - our thoughts are very much in sync then.  In my view, though,
the whole idea becomes much nicer and more useful if we integrate it
with existing Guile exceptions, so I hope we can agree with Marius to
do this.

> > I think the solution to both these is that an error/exception should
> > be an instance of a GOOPS error/exception class (+ subclasses).  The
> > first problem is then solved by the class slots showing what
> > information is available about the error/exception, and class methods
> > to - for example - print a human-readable message describing the
> > error/exception.
> >
> So far, this is all implemented in my srfi-35 stuff as in my
> Archive. I have additionally exported a handle-condition generic,
> whose methods call (error "unhandled foo"), foo being an error
> condition, message, serious condition. Also, there is a class
> &compound-condition which doesn't exist in the SRFI (so methods for
> compund conditions can be defined).

Seems sensible; also that it doesn't exist in the SRFI, because
&compound-condition is not a condition _type_ (even though it does
make sense as a GOOPS class).  Do you have an example in mind of how
methods on &compound-condition can be useful?

I'm not sure though about `condition' expanding to
`make-compound-condition' in the case there is only one type given.
Is this implied in some way by the SRFI?  I think it would be nicer to
detect the single type case and use `make-condition' instead.

> Plus, there is a macro
> guard/handle, which calls handle-condition:
> 
> (define-method (handle-method (&foobar-condition c))
>  ...)
> 
> (guard/handle
>   (some-code-that-maz-be-foobar))

(Not in the version that you posted, so I presume this is newer.)
Interesting.  I'm sceptical that it will be possible to define a
generally useful handler for a condition, but I could easily be wrong,
and there is negligible overhead from providing this.  (On the other
hand, it's only a few lines, so perhaps could be left to the
programmer to write for him/herself when needed?)

> > by SRFI-35.  Therefore, for example, `make-condition' would create and
> > return a GOOPS error/exception class and, given a
> > error/exception/condition object OBJ, `(condition-has-type? OBJ TYPE)'
> > would be identical to `(is-a? OBJ TYPE)'.
> >
> I'd have to specialize is-a? for this, since compound conditions all
> share a class.

Hmm.  My inclination is that it would be nicer if a compound condition
straightforwardly satisfied is-a? for all its component condition type
classes (without specialization of is-a?).  

The big benefit of this is that methods defined for the component
types will work on (instances of) the compound type as well, which
makes sense because we know that the compound type has all the slots
of the component type.

The possible problem is that `make-compound-condition' would have to
construct an appropriate subclass on the fly, and that this should
interact nicely with compound condition classes created explicitly by
the programmer, e.g.:

(define-class &my-condition (&i/o-condition &runtime-condition)
  ...)

In other words, given this define-class, the result of

(make-condition &my-condition ...)

should be indistinguishable from that of

(make-compound-condition &i/o-condition (...)
                         &runtime-condition (...))
 
but I think this is achievable.

This conflicts, though, with the introduction of &compound-condition
and the idea that &compound-condition provides a way to define methods
on compound conditions.  Since this ability is a Guile extension
anyway (w.r.t. SRFI-35), I think it would be reasonable to say that
the way to do this is to define the compound condition class
explicitly, using define-class as just above.

Regards,
        Neil


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-06 12:05     ` Neil Jerram
@ 2004-03-06 14:52       ` Andreas Rottmann
  2004-03-08 20:07       ` Andreas Rottmann
  1 sibling, 0 replies; 8+ messages in thread
From: Andreas Rottmann @ 2004-03-06 14:52 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Neil Jerram <neil@ossau.uklinux.net> writes:

> Andreas Rottmann <a.rottmann@gmx.at> writes:
>
>> Neil Jerram <neil@ossau.uklinux.net> writes:
>> 
>> > Andreas Rottmann <a.rottmann@gmx.at> writes:
>> >
>> I've thought of this, too; this was my reason to use GOOPS in the
>> first place.
>
> Great - our thoughts are very much in sync then.  In my view, though,
> the whole idea becomes much nicer and more useful if we integrate it
> with existing Guile exceptions, so I hope we can agree with Marius to
> do this.
>
Indeed. Making Guile use SRFI-35 conditions everywhere would be a
*very* nice thing to have.

>> Also, there is a class &compound-condition which doesn't exist in
>> the SRFI (so methods for compund conditions can be defined).
>
> Seems sensible; also that it doesn't exist in the SRFI, because
> &compound-condition is not a condition _type_ (even though it does
> make sense as a GOOPS class).  Do you have an example in mind of how
> methods on &compound-condition can be useful?
>
I've so far only used it this way:

(define-method (handle-condition (c &compound-condition))
  (cond
   ((and (message-condition? c)
         (error? c))
    (format (current-error-port) "itla-debuild: ~A\n" (condition-message c))
    (if (abort-condition? c)
        (exit 1)))
   (else
    (format #t "itla-debuild: unexpected condition ~S\n" c))))


And then somewhere raise a fatal error:

      (raise
       (condition
        (&message
         (message (format #f "Current working directory ~S is not part of working copy build area ~S"
                          (getcwd) (string-join wc-area-dirs "/"))))
         (&abort)))

> I'm not sure though about `condition' expanding to
> `make-compound-condition' in the case there is only one type given.
> Is this implied in some way by the SRFI?  I think it would be nicer to
> detect the single type case and use `make-condition' instead.
>
Well, I detect that in make-compound-condition itself, but that's not
the most obvious place (since the name make-compound-condition implies
that a call will indeed result in a compund condition).

>> Plus, there is a macro guard/handle, which calls handle-condition:
>> 
>> (define-method (handle-method (&foobar-condition c))
>>  ...)
>> 
>> (guard/handle
>>   (some-code-that-maz-be-foobar))
>
> (Not in the version that you posted, so I presume this is newer.)
>
Yes, but it's in my Archive:

% tla register-archive http://people.debian.org/~rotty/arch/a.rottmann@gmx.at/2004-main
% tla get itla--devo--0.1 itla
% $EDITOR itla/srfi/srfi-35.scm

> Interesting.  I'm sceptical that it will be possible to define a
> generally useful handler for a condition, but I could easily be wrong,
> and there is negligible overhead from providing this.  (On the other
> hand, it's only a few lines, so perhaps could be left to the
> programmer to write for him/herself when needed?)
>
I think this might come handy for top-level handlers. If there is
general consensus, I could take this out of (srfi srfi-35), of course.

>> > by SRFI-35.  Therefore, for example, `make-condition' would create and
>> > return a GOOPS error/exception class and, given a
>> > error/exception/condition object OBJ, `(condition-has-type? OBJ TYPE)'
>> > would be identical to `(is-a? OBJ TYPE)'.
>> >
>> I'd have to specialize is-a? for this, since compound conditions all
>> share a class.
>
> Hmm.  My inclination is that it would be nicer if a compound condition
> straightforwardly satisfied is-a? for all its component condition type
> classes (without specialization of is-a?).  
>
> The big benefit of this is that methods defined for the component
> types will work on (instances of) the compound type as well, which
> makes sense because we know that the compound type has all the slots
> of the component type.
>
> The possible problem is that `make-compound-condition' would have to
> construct an appropriate subclass on the fly,
>
That was my initial idea, I then however switched to a separate class
for some reason. "compound-condition-is-derived-class" seems like a
more coherent design to me now, however.

> In other words, given this define-class, the result of
>
> (make-condition &my-condition ...)
>
> should be indistinguishable from that of
>
> (make-compound-condition &i/o-condition (...)
>                          &runtime-condition (...))
>  
> but I think this is achievable.
>
> This conflicts, though, with the introduction of &compound-condition
> and the idea that &compound-condition provides a way to define methods
> on compound conditions.  Since this ability is a Guile extension
> anyway (w.r.t. SRFI-35), I think it would be reasonable to say that
> the way to do this is to define the compound condition class
> explicitly, using define-class as just above.
>
Sounds like a good plan, I'll look into this.

Andy
-- 
Andreas Rottmann         | Rotty@ICQ      | 118634484@ICQ | a.rottmann@gmx.at
http://yi.org/rotty      | GnuPG Key: http://yi.org/rotty/gpg.asc
Fingerprint              | DFB4 4EB4 78A4 5EEE 6219  F228 F92F CFC5 01FD 5B62

If atheism is a religion, then health is a disease. -- Clark Adams


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-06 12:05     ` Neil Jerram
  2004-03-06 14:52       ` Andreas Rottmann
@ 2004-03-08 20:07       ` Andreas Rottmann
  2004-03-10  9:17         ` Neil Jerram
  2004-03-11 15:38         ` Mikael Djurfeldt
  1 sibling, 2 replies; 8+ messages in thread
From: Andreas Rottmann @ 2004-03-08 20:07 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Neil Jerram <neil@ossau.uklinux.net> writes:

> Hmm.  My inclination is that it would be nicer if a compound condition
> straightforwardly satisfied is-a? for all its component condition type
> classes (without specialization of is-a?).  
>
> The big benefit of this is that methods defined for the component
> types will work on (instances of) the compound type as well, which
> makes sense because we know that the compound type has all the slots
> of the component type.
>
> The possible problem is that `make-compound-condition' would have to
> construct an appropriate subclass on the fly, and that this should
> interact nicely with compound condition classes created explicitly by
> the programmer, e.g.:
>

> (define-class &my-condition (&i/o-condition &runtime-condition)
>   ...)
>
> In other words, given this define-class, the result of
>
> (make-condition &my-condition ...)
>
> should be indistinguishable from that of
>
> (make-compound-condition &i/o-condition (...)
>                          &runtime-condition (...))
>  
I think you mean condition instead of make-compound-condition here.

> but I think this is achievable.
>
It may be, but this probably involves "caching" defined (via
define-class or the condition macro) condition types by their
supertypes. This, in turn, disallows defining different define-class
statements specifiying the same supers (if the supers are conditions).

Another, much more serious problem is the following:

(define-condition-type &c &condition
  c?
  (x c-x))

(define-condition-type &c1 &c
  c1?
  (a c1-a))

(define-condition-type &c2 &c
  c2?
  (b c2-b))

(define v2 (condition (&c2 (x "V2") (b "b2"))))
(define v3 (condition (&c1 (x "V3/1") (a "a3"))
                      (&c2 (b "b3"))))
(define v5 (make-compound-condition v2 v3)) ;; This is hairy

Here, we given your proposed model, we'd get this hierarchy:

(define-class &c ())
(define-class &c1 (&c))
(define-class &c2 (&c))
(define-class &c3 (&c1 &c2)) ;; Class constructed for v3
(define-class &c5 (&c2 &c3)) ;; Class constructed for v5

This will cause GOOPS to barf: "merge-lists: Inconsistent precedence graph"

I didn't see an obvious solution to this problem.

Andy
-- 
Andreas Rottmann         | Rotty@ICQ      | 118634484@ICQ | a.rottmann@gmx.at
http://yi.org/rotty      | GnuPG Key: http://yi.org/rotty/gpg.asc
Fingerprint              | DFB4 4EB4 78A4 5EEE 6219  F228 F92F CFC5 01FD 5B62

Make free software, not war!


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-08 20:07       ` Andreas Rottmann
@ 2004-03-10  9:17         ` Neil Jerram
  2004-03-11 15:38         ` Mikael Djurfeldt
  1 sibling, 0 replies; 8+ messages in thread
From: Neil Jerram @ 2004-03-10  9:17 UTC (permalink / raw)
  Cc: Guile Users, guile-devel

Andreas Rottmann <a.rottmann@gmx.at> writes:

> Neil Jerram <neil@ossau.uklinux.net> writes:
> 
> > (make-compound-condition &i/o-condition (...)
> >                          &runtime-condition (...))
> >  
> I think you mean condition instead of make-compound-condition here.

Yes, you're right.

> It may be, but this probably involves "caching" defined (via
> define-class or the condition macro) condition types by their
> supertypes. This, in turn, disallows defining different define-class
> statements specifiying the same supers (if the supers are conditions).

Good point.

> Another, much more serious problem is the following: [...]

Yes, I see.  OK, I'm convinced by your arguments.

On rereading, I see that SRFI-35's condition types follow a single
inheritance hierarchy, and that compound conditions are a way of
combining different types within the hierarchy.  This is quite
different from the multiple inheritance allowed by GOOPS.  I'd now say
that it remains to be seen whether it will be useful and workable to
combine GOOPS-defined multiple inheritance conditions with those that
can be defined by SRFI-35.

Regards,
        Neil


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: GOOPS-based SRFI-35 implementation
  2004-03-08 20:07       ` Andreas Rottmann
  2004-03-10  9:17         ` Neil Jerram
@ 2004-03-11 15:38         ` Mikael Djurfeldt
  1 sibling, 0 replies; 8+ messages in thread
From: Mikael Djurfeldt @ 2004-03-11 15:38 UTC (permalink / raw)
  Cc: Guile Users, djurfeldt, guile-devel, Neil Jerram

Andreas Rottmann <a.rottmann@gmx.at> writes:

> Here, we given your proposed model, we'd get this hierarchy:
>
> (define-class &c ())
> (define-class &c1 (&c))
> (define-class &c2 (&c))
> (define-class &c3 (&c1 &c2)) ;; Class constructed for v3
> (define-class &c5 (&c2 &c3)) ;; Class constructed for v5
>
> This will cause GOOPS to barf: "merge-lists: Inconsistent precedence graph"
>
> I didn't see an obvious solution to this problem.

Well, this is a bug in goops.scm:compute-std-cpl.  The solution is to
fix the bug.  However, this is non-trivial, and I don't have time
right now to fix it myself.  The algorithm should be the C3 algorithm
in http://www.webcom.com/haahr/dylan/linearization-oopsla96.html

M


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-03-11 15:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-28 15:53 GOOPS-based SRFI-35 implementation Andreas Rottmann
2004-03-03 16:02 ` Neil Jerram
2004-03-04  0:20   ` Andreas Rottmann
2004-03-06 12:05     ` Neil Jerram
2004-03-06 14:52       ` Andreas Rottmann
2004-03-08 20:07       ` Andreas Rottmann
2004-03-10  9:17         ` Neil Jerram
2004-03-11 15:38         ` Mikael Djurfeldt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).