Am 03.04.2012 17:10, schrieb Daniel Carrera:
(1..10).WHAT # => Range()
@foo = 1..10;
@foo.WHAT # => Array()
When you assign a range to @foo, the result is an array. Something
similar happens, for example, if you assign a scalar to @foo... The
context of the assignment causes Perl 6 to convert the value into an
array.
I was wondering if this sort of magic is limited to pre-defined types
(arrays, hashes, etc) or if it can be extended to any class that I
might create.
It's something inbetween. The distinction between the list assignment
and scalar assignment is syntactic. In the case of list assignment,
@foo.STORE(1..10) is called under the hood.
For example, imagine hat I create a 'Vector' class to do
basic linear algebra. Imagine that it works this way:
my @vec = Vector.new( 1,2,3,4 )
@vec * 3 # => ( 3,6,9,12 )
In other words, the '*' operator is overloaded to behave like scalar x
vector multiplication in linear algebra. I was thinking that it would
be neat if instead you could do this:
my Vector @vec;
@vec = 1,2,3,4;
@vec.WHAT # => Vector()
You can, very nearly. You just need to write
my @vec is Vector;
because you really want to change the type of the container, not just of
the contents (my Vector @vec would be an array containing Vector objects).
This syntax doesn't quite work yet in Rakudo (though it wouldn't be too
hard to get running), but this works:
use v6;
class Vector is Array {}
multi sub infix:<*>(Vector $a, Real $b) {
Vector.new( $a.list X* $b );
}
my @vec := Vector.new(1, 2, 3, 4);
say @vec.WHAT;
say @vec * 3;
Output:
Vector()
3 6 9 12
Using binding := instead of assignment replaces the array container with
a Vector object.
You can even write
my @vec := Vector.new;
@vec = 1, 2, 3, 4;
and get the same output.
(you can also override the .STORE method of a scalar, but that's a bit
creepy if you ask me).
Cheers,
Moritz