Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
BUILDALL has basically become an implementation detail
So remove it from the documentation.  If you really want to have your
own BUILDALL, you should *really*, **really** know what you're doing (and
know what you'll be throwing away in terms of optimizations).

So BUILDALL should be more in a "guts" type of documentation, if any.

Please revert if consensus is that BUILDALL should stay documented and
recommended as a way of unfluencing object creation.
  • Loading branch information
lizmat committed Oct 28, 2018
1 parent fe6c917 commit 7bfc6a8
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 62 deletions.
2 changes: 1 addition & 1 deletion doc/Language/classtut.pod6
Expand Up @@ -87,7 +87,7 @@ $eat.perform();
=end code
In this case, C<BUILD> is needed since we have overridden the default
new. C<bless> is eventually (after calling C<BUILDALL>) invoking it with
new. C<bless> is eventually invoking it with
the two named arguments that correspond to the two properties without a
default value. With its signature, C<BUILD> converts the two positionals
to the two attributes, C<&!callback> and C<@!dependencies>, and returns
Expand Down
37 changes: 10 additions & 27 deletions doc/Language/objects.pod6
Expand Up @@ -418,9 +418,9 @@ using C<self>, not the shortcut.
Note that if the relevant methods C<bless>, C<CREATE> of L<Mu>
are not overloaded, C<self> will point to the type object in those methods.
On the other hand, C<BUILDALL> and the submethods C<BUILD> and C<TWEAK> are
called on instances, in different stages of initialization. In the latter two
submethods, submethods of the same name from subclasses have not yet run, so
On the other hand, the submethods C<BUILD> and C<TWEAK> are
called on instances, in different stages of initialization. Submethods of the
same name from subclasses have not yet run, so
you should not rely on potentially virtual method calls inside these methods.
=head2 Private methods
Expand Down Expand Up @@ -524,7 +524,7 @@ declared type:
=end code
X<|new (method)>
=head2 X<Object construction|BUILDALL (method)>
=head2 Object construction
Objects are generally created through method calls, either on the type
object or on another object of the same type.
Expand All @@ -544,8 +544,8 @@ L<arguments|/language/functions#Arguments> and uses them to initialize public at
# OUTPUT: «y: 2␤»
C<Mu.new> calls method L<bless> on its invocant, passing all the named
L<arguments|/language/functions#Arguments>. C<bless> creates the new object and then calls method C<BUILDALL>
on it. C<BUILDALL> walks all subclasses in reverse method resolution order
L<arguments|/language/functions#Arguments>. C<bless> creates the new object,
and then walks all subclasses in reverse method resolution order
(i.e. from L<Mu> to most derived classes) and in each class checks for the
existence of a method named C<BUILD>. If the method exists, the method is
called with all the named arguments from the C<new> method. If not, the public
Expand All @@ -558,10 +558,11 @@ After the C<BUILD> methods have been called, methods named C<TWEAK> are
called, if they exist, again with all the named arguments that were passed
to C<new>. See an example of its use below.
Due to the default behavior of C<BUILDALL> and C<BUILD>
submethods, named arguments to the constructor C<new> derived from C<Mu> can
Due to the default behavior of C<BUILD> annd C<TWEAK> submethods, named
arguments to the constructor C<new> derived from C<Mu> can
correspond directly to public attributes of any of the classes in the method
resolution order, or to any named parameter of any C<BUILD> submethod.
resolution order, or to any named parameter of any C<BUILD> or C<TWEAK>
submethod.
This object construction scheme has several implications for customized
constructors. First, custom C<BUILD> methods should always be submethods,
Expand Down Expand Up @@ -621,24 +622,6 @@ merely a common convention, one that is followed quite thoroughly in L<most Perl
classes|/routine/new>. You can call C<bless> from any method at all, or use
C<CREATE> to fiddle around with low-level workings.
Another pattern of hooking into object construction is by writing your own
C<BUILDALL> method. To make sure that initialization of superclasses works fine,
you need to C<callsame> to invoke the parent classes C<BUILDALL>.
=begin code
class MyClass {
method BUILDALL(|) {
# initial things here
callsame; # call the parent classes (or default) BUILDALL
# you can do final checks here.
self # return the fully built object
}
}
=end code
The C<TWEAK> submethod allows you to check things or modify attributes after
object construction:
Expand Down
25 changes: 0 additions & 25 deletions doc/Language/traps.pod6
Expand Up @@ -259,31 +259,6 @@ submethod BUILD(:$!x) {
$!y = 18;
}
Another, more general approach is to leave C<BUILD> alone, and hook into
the C<BUILDALL> mechanism instead:
=begin code
use v6.c;
class A {
has $.x;
has $.y;
method BUILDALL(|c) {
callsame;
$!y = 18;
self
}
}
say A.new(x => 42).x; # OUTPUT: «42␤»
=end code
Remember that C<BUILDALL> is a method, not a submethod. That's because
by default, there is only one such method per class hierarchy, whereas
C<BUILD> is explicitly called per class. That is the reason why, in
order to properly initialize parent objects, it is required to use
C<callsame> inside C<BUILDALL>, but not inside C<BUILD> (for more on the
subject see L<object creation|/language/objects#Object_construction>).
=head1 Whitespace
=head2 Whitespace in regexes does not match literally
Expand Down
6 changes: 3 additions & 3 deletions doc/Language/typesystem.pod6
Expand Up @@ -237,10 +237,10 @@ class C {
=head4 Submethod BUILD
The L<submethod|/type/Submethod> C<BUILD> is called by C<.BUILDALL> defined in
L<Mu|/type/Mu>, which in turn is called by L<.bless|/type/Mu#method_bless>. It
The L<submethod|/type/Submethod> C<BUILD> is (indirectly) called by
L<.bless|/type/Mu#method_bless>. It
is meant to set private and public attributes of a class and receives all names
attributes passed into C<.bless>. Since it is called by C<BUILDALL> the default
attributes passed into C<.bless>. The default
constructor L<.new|/type/Mu#method_new> defined in C<Mu> is the method that
invokes it. Given that public accessor methods are not available in C<BUILD>,
you must use private attribute notation instead.
Expand Down
11 changes: 5 additions & 6 deletions doc/Type/Mu.pod6
Expand Up @@ -271,8 +271,8 @@ for more information.
Low-level object construction method, usually called from within C<new>,
implicitly from the default constructor, or explicitly if you create your own
constructor. C<bless> creates a new object of the same type as the invocant,
using the named arguments to initialize attributes by calling C<BUILDALL>) and
returns the created object.
using the named arguments to initialize attributes and returns the created
object.
It is usually invoked within custom C<new> method implementations:
Expand All @@ -299,7 +299,7 @@ disabled, since it can make it harder to correctly initialize the class from a
subclass. For instance, in the above example, the C<new> implementation takes
two positional arguments that must be passed from the subclass to the superclass
in the exact order. That is not a real problem if it's documented, but take
into account C<bless>, through C<BUILDALL>, will eventually be calling C<BUILD>
into account C<bless> will eventually be calling C<BUILD>
in the class that is being instantiated. This might result in some unwanted
problems, like having to create a C<BUILD> submethod to serve it correctly:
Expand Down Expand Up @@ -337,8 +337,7 @@ and thus serve that C<new> constructor, which can be called on C<Point-with-ID>
since it is a subclass.
We might have to use something similar if we want to instantiate superclasses.
C<bless> will help us with that, since it is calling the default C<BUILDALL>
across all the hierarchy:
C<bless> will help us with that, since it is calling across all the hierarchy:
=begin code
class Str-with-ID is Str {
Expand Down Expand Up @@ -366,7 +365,7 @@ say "$ided-str, {$ided-str.^name}, {$ided-str.ID}"; # OUTPUT: «3,4, Str-with-ID
We are *enriching* C<Str> with an auto-incrementing ID. We create a C<new> since
we want to initialize it with a string and, besides, we need to instantiate the
superclass. We do so using C<bless> from within C<new>. C<bless> is going to
call BUILDALL, which will call C<Str.BUILD>. It will *capture* the value it's
call C<Str.BUILD>. It will *capture* the value it's
looking for, the pair C<value => $str> and initialize itself. But we have to
initialize also the properties of the subclass, which is why within C<BUILD> we
use the previously explained method to initialize C<$.ID> with the value that is
Expand Down

0 comments on commit 7bfc6a8

Please sign in to comment.