@@ -10,8 +10,42 @@ In Raku lingo, an I<attribute> refers to a per-instance/object storage slot.
10
10
An C<Attribute> is used to talk about classes' and roles' attributes at the
11
11
metalevel.
12
12
13
- Normal usage of attributes does not require the user to use this class
14
- explicitly.
13
+ C<Attribute> is typically useful when working with the L<MOP|/language/mop>.
14
+ For instance, the attributes of any type that supports them can be
15
+ introspected using the C<attributes> metamethod, which returns a list of
16
+ C<Attribute> instances. Using these, we can inspect various properties of
17
+ a type's attributes, such as their names:
18
+ =begin code
19
+ class WithAttributes {
20
+ has $.attribute;
21
+ has $.attribute-two-electric-boogaloo;
22
+ has $.yet-another-attribute;
23
+ }
24
+ .say for WithAttributes.^attributes(:local).map(*.name);
25
+ # OUTPUT:
26
+ # $!attribute
27
+ # $!attribute-two-electric-boogaloo
28
+ # $!yet-another-attribute
29
+ =end code
30
+
31
+ Because of C<Attribute>, a type containing attributes, such as this:
32
+
33
+ =for code
34
+ class WithAttribute {
35
+ has $.attribute;
36
+ }
37
+
38
+ Is not something only the compiler knows how to generate. This class in
39
+ particular can be generated manually like so:
40
+
41
+ =for code :solo
42
+ BEGIN {
43
+ constant WithAttribute = Metamodel::ClassHOW.new_type: :name<WithAttribute>;
44
+ WithAttribute.^add_attribute: Attribute.new:
45
+ :name<$!attribute>, :type(Any), :package(WithAttribute),
46
+ :1has_accessor;
47
+ WithAttribute.^compose;
48
+ }
15
49
16
50
=head1 Traits
17
51
@@ -121,27 +155,31 @@ default accessor for the attribute will return a writable value.
121
155
122
156
multi trait_mod:<is>(Attribute:D $a, :$built!)
123
157
124
- By default, this trait allows setting up a I«private attribute» during object
125
- construction via C«.new». The same trait can be used to prevent setting up a
126
- I«public attribute» via C«.new» by passing it the Boolean value C«False».
158
+ By default, this trait allows setting up a I«private attribute» during
159
+ object construction via C«.new». The same trait can be used to prevent
160
+ setting up a I«public attribute» via C«.new» by passing it the Boolean
161
+ value C«False». Setting up an attribute with its value is ordinarily
162
+ handled by assigning the value, but if C<:bind> is passed, then it will
163
+ be bound instead:
127
164
128
165
class Foo {
129
166
has $!bar is built; # same as `is built(True)`
130
167
has $.baz is built(False);
168
+ has $!qux is built(:bind);
131
169
132
- method bar {
133
- $!bar
134
- }
170
+ method bar(::?CLASS:D:) { $!bar }
171
+ method qux(::?CLASS:D:) { $!qux }
135
172
}
136
173
137
- my $foo = Foo.new(bar => 1, baz => 2);
138
- say $foo.bar; # OUTPUT: «1»
139
- say $foo.baz; # OUTPUT: «Any»
174
+ my Foo:D $foo .= new: :bar[], :baz[], :qux[];
175
+ say $foo.bar.raku; # OUTPUT: «$[]»
176
+ say $foo.baz.raku; # OUTPUT: «Any»
177
+ say $foo.qux.raku; # OUTPUT: «[]»
140
178
141
179
The C<built> trait also allows named arguments to be specified. Currently
142
180
the C<:bind> named argument can be specified. In that case, any (default)
143
181
value will be B<bound> to the attribute, rather than assigned. This allows
144
- for specifying a C< Proxy> to an attribute:
182
+ for specifying a L<C<Proxy>|/type/ Proxy> to an attribute:
145
183
146
184
class Foo {
147
185
has $!foo is built(:bind) = Proxy.new: :STORE{...}, :FETCH{...}
@@ -151,19 +189,26 @@ Available as of the 2020.01 release of the Rakudo compiler.
151
189
152
190
=head1 Methods
153
191
154
- The usual way to obtain an object of type C<Attribute> is by introspection:
155
-
156
- class Useless {
157
- has @!things;
158
- }
159
- my $a = Useless.^attributes(:local)[0];
160
- say $a.raku; # OUTPUT: «Attribute.new»
161
- say $a.name; # OUTPUT: «@!things»
162
- say $a.package; # OUTPUT: «(Useless)»
163
- say $a.has_accessor; # OUTPUT: «False»
192
+ =head2 method new
193
+
194
+ =begin code :method
195
+ method new(
196
+ Attribute:_:
197
+ :$name!,
198
+ :$type!,
199
+ :$package!,
200
+ :$inlined = 0,
201
+ :$has_accessor = 0,
202
+ :$is_built = $has_accessor,
203
+ :$is_bound = 0,
204
+ :$positional_delegate = 0,
205
+ :$associative_delegate = 0,
206
+ *%other
207
+ )
208
+ =end code
164
209
165
- Modifying a private attribute from the outside is usually not possible, but
166
- since Attribute is at the level of the metaclass, all is fair game.
210
+ Creates a new attribute. The following named arguments are required:
211
+ - C<$name> contains the attribute's name, which should always be a
167
212
168
213
=head2 method name
169
214
@@ -283,7 +328,7 @@ Returns the value stored in this attribute of object C<$obj>.
283
328
say $private.get_value(Violated.new); # OUTPUT: «5»
284
329
285
330
Note that this method violates encapsulation of the object, and should be
286
- used with care. Here be dragons.
331
+ used with care.
287
332
288
333
=head2 method set_value
289
334
@@ -323,6 +368,21 @@ say Hero.^attributes(:local)[0]; # OUTPUT: «Positional @!inventory»
323
368
324
369
Since say implicitly calls C<.gist>, that is what produces the output here.
325
370
371
+ =head2 method is_built
372
+
373
+ method is_built()
374
+
375
+ Returns C<True> if the attribute had the L<C<is built>|#trait_is_built>
376
+ trait applied to it, otherwise returns C<False>.
377
+
378
+ =head2 method is_bound
379
+
380
+ method is_bound()
381
+
382
+ Returns C<True> if the attribute had the L<C<is built>|#trait_is_built>
383
+ trait applied to it with C<:bind> as an argument, otherwise returns
384
+ C<False>.
385
+
326
386
=head1 Optional introspection
327
387
328
388
=head2 DEPRECATED
0 commit comments