[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] branch main updated: Updated GOOPS sections of reference
From: |
Mikael Djurfeldt |
Subject: |
[Guile-commits] branch main updated: Updated GOOPS sections of reference |
Date: |
Thu, 28 Nov 2024 15:55:28 -0500 |
This is an automated email from the git hooks/post-receive script.
mdj pushed a commit to branch main
in repository guile.
The following commit(s) were added to refs/heads/main by this push:
new c78abcb76 Updated GOOPS sections of reference
c78abcb76 is described below
commit c78abcb765fcc85b335ab781bdaea13deddbaf1a
Author: Mikael Djurfeldt <mikael@djurfeldt.com>
AuthorDate: Thu Nov 28 21:39:09 2024 +0100
Updated GOOPS sections of reference
* doc/ref/goops.texi: Insert reference to the "definition" of
next-method the first time next-method is mentioned. Place the
definition of next-method in index. Don't use capital methods in generic
function names (corrected only in one node). In section about
next-method, say that you can provide custom arguments (which we can now
due to the optimizing compiler). New node "Inheritance and accessors"
explaining how new accessor methods are created for subclasses.
---
doc/ref/goops.texi | 87 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 30 deletions(-)
diff --git a/doc/ref/goops.texi b/doc/ref/goops.texi
index 1a75af89f..13aa73b81 100644
--- a/doc/ref/goops.texi
+++ b/doc/ref/goops.texi
@@ -192,10 +192,10 @@ understood by whatever methods get applied when the
@code{initialize}
generic function is applied to the newly allocated instance.
In practice, specialized @code{initialize} methods would normally call
-@code{(next-method)}, and so eventually the standard GOOPS
-@code{initialize} methods are applied. These methods expect
-@var{initargs} to be a list with an even number of elements, where
-even-numbered elements (counting from zero) are keywords and
+@code{(next-method)} (@pxref{Next-method}), and so eventually the
+standard GOOPS @code{initialize} methods are applied. These methods
+expect @var{initargs} to be a list with an even number of elements,
+where even-numbered elements (counting from zero) are keywords and
odd-numbered elements are the corresponding values.
GOOPS processes initialization argument keywords automatically for slots
@@ -857,6 +857,7 @@ to that descendant's ancestors too.
@node Next-method
@subsection Next-method
+@fnindex next-method
When you call a generic function, with a particular set of arguments,
GOOPS builds a list of all the methods that are applicable to those
arguments and orders them by how closely the method definitions match
@@ -865,45 +866,40 @@ list. If the selected method's code wants to call on to
the next method
in this list, it can do so by using @code{next-method}.
@lisp
-(define-method (Test (a <integer>)) (cons 'integer (next-method)))
-(define-method (Test (a <number>)) (cons 'number (next-method)))
-(define-method (Test a) (list 'top))
+(define-method (test (a <integer>)) (cons 'integer (next-method)))
+(define-method (test (a <number>)) (cons 'number (next-method)))
+(define-method (test a) (list 'top))
@end lisp
With these definitions,
@lisp
-(Test 1) @result{} (integer number top)
-(Test 1.0) @result{} (number top)
-(Test #t) @result{} (top)
+(test 1) @result{} (integer number top)
+(test 1.0) @result{} (number top)
+(test #t) @result{} (top)
@end lisp
-@code{next-method} is always called as just @code{(next-method)}. The
-arguments for the next method call are always implicit, and always the
-same as for the original method call.
+@code{next-method} can be called as just @code{(next-method)}. The
+arguments for the next method call are then implicit, and the same as
+for the original method call.
If you want to call on to a method with the same name but with a
different set of arguments (as you might with overloaded methods in C++,
-for example), you do not use @code{next-method}, but instead simply
-write the new call as usual:
+for example), you can pass custom arguments to @code{next-method}:
@lisp
-(define-method (Test (a <number>) min max)
+(define-method (test (a <number>) min max)
(if (and (>= a min) (<= a max))
(display "Number is in range\n"))
- (Test a))
+ (next-method a))
-(Test 2 1 10)
+(test 2 1 10)
@print{}
Number is in range
@result{}
(integer number top)
@end lisp
-(You should be careful in this case that the @code{Test} calls do not
-lead to an infinite recursion, but this consideration is just the same
-as in Scheme code in general.)
-
@node method* and define-method*
@subsection method* and define-method*
@@ -1042,10 +1038,9 @@ in the same position in less specialized methods. For
example if
@var{<B>},
@lisp
-> (define-method* (foo (obj <A>) #:optional (c 1)) c)
-> (define-method* (foo (obj <B>) #:optional c)) (next-method))
-> (foo b)
-$1 = #f
+(define-method* (foo (obj <A>) #:optional (c 1)) c)
+(define-method* (foo (obj <B>) #:optional c)) (next-method))
+(foo b) @result{} #f
@end lisp
The reason for this is that @var{c} will obtain the value @code{#f}
@@ -1058,10 +1053,9 @@ A keyword argument will not shadow a default value for
the same keyword
argument in less specialized methods. Example:
@lisp
-> (define-method* (foo (obj <A>) #:key (c 1)) c)
-> (define-method* (foo (obj <B>) #:key c)) (next-method))
-> (foo b)
-$1 = 1
+(define-method* (foo (obj <A>) #:key (c 1)) c)
+(define-method* (foo (obj <B>) #:key c)) (next-method))
+(foo b) @result{} 1
@end lisp
The reason for this is that the first (less specialized, called last)
@@ -1362,6 +1356,7 @@ The ordering of the returned slots is not significant.
@menu
* Class Precedence List::
* Sorting Methods::
+* Inheritance and accessors::
@end menu
@@ -1476,6 +1471,38 @@ a class C1 is more specific than another class C2, for
an object of
actual class C, if C1 comes before C2 in C's class precedence list.
@end itemize
+@node Inheritance and accessors
+@subsection Inheritance and accessors
+
+When a class @var{<A>} defines a getter, setter or accessor for one of
+its slots @var{x}, an @emph{accessor method} specialized to class
+@var{<A>} is created. Accessor methods are special in that they always
+refer to a concrete class. When you subclass @var{<A>}, a new accessor
+method for @var{x} is created automatically, specialized to the
+subclass:
+
+@lisp
+(define-class <A> () (x #:accessor x))
+(define-class <B> (<A>))
+(generic-function-methods x)
+@result{}
+(#<<accessor-method> (<B>) 7faa66b5b1c0>
+ #<<accessor-method> (<A>) 7faa66b5b240>)
+@end lisp
+
+Note, in particular, that the @var{x} accessor method specialized to
+@var{<A>} is @emph{not} applicable to objects of class @var{B}:
+
+@lisp
+(define o (make <B>))
+(compute-applicable-methods x (list o))
+@result{}
+(#<<accessor-method> (<B>) 7faa66b5b1c0>)
+@end lisp
+
+As a consequence, an accessor doesn't have a next-method. The fact that
+accessor methods always apply to concrete classes allows for extensive
+optimization.
@node Introspection
@section Introspection
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Guile-commits] branch main updated: Updated GOOPS sections of reference,
Mikael Djurfeldt <=