As with my previous question, this is an area where I can't tell if I've encountered a bug or a hole in my understanding of Raku's semantics. Last time it turned out to be a bug, but doubt lightning will strike twice!
In general, I know that I can pass named arguments to a function either with syntax that looks a lot like creating a Pair (e.g. f :a(42)) or with syntax that looks a lot like flattening a Hash (e.g., f |%h). (see argument destructuring in the docs). Typically, these two are equivalent, even for non-Scalar parameters:
sub f(:@a) { dd @a }
my %h = a => [4, 2];
f :a([4,2]);  # OUTPUT: «Array element = [4, 2]»
f |%h;        # OUTPUT: «Array element = [4, 2]»
However, when constructing an object with the default .new constructor, these two forms seem to give different results:
class C { has @.a; }
my %h = a => [4, 2];
C.new: :a([4,2];  # OUTPUT: «C.new(a => ([[4, 2]])»
C.new: |%h;       # OUTPUT: «C.new(a => [[4, 2],])»
That is, passing :a([4,2]) results in a two-element Array, but using the argument-flattening syntax results in a one-element Array containing a two-element Array.
Is this behavior intended?  If so, why?  And is there syntax I can use to pass |%h in and get the two-element Array bound to an @-sigiled attribute?  (I know using an $-sigiled attribute works, but I prefer the semantics of the @).
Is this behavior intended?
Yes. Parameter binding uses binding semantics, while attribute initialization uses assignment semantics. Assignment into an array respects Scalar containers, and the values of a Hash are Scalar containers.
If so, why?
The intuition is:
is copy on a parameter to get assignment semantics).And is there syntax I can use to pass |%h in and get the two-element Array bound to an @-sigiled attribute?
Coerce it into a Map:
class C { has @.a; }
my %h = a => [4, 2];
say C.new: |%h.Map;
Or start out with a Map in the first place:
class C { has @.a; }
my %h is Map = a => [4, 2];
say C.new: |%h;
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With