Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell if something is a Perl 6 container?

Tags:

I don't have no useful reason for knowing this, but I was wondering if I had a name such as $x, if that was a scalar variable (mutable thingy) or merely the name for something (immutable thingy). I'm not trying to accomplish anything; this is curiosity.

I was playing around with something like this:

my @a  = 'a', ('b', 'c' );
my @b  = 'd', 'e', 'f', @a;

my @ab = @a, @b, ( 1, 2 );

for @ab {
    put "name: {.^name} VAR: { .VAR.^name }";
    when .VAR.can('FETCH') { put "Container: $_" }
    when .VAR.can('STORE') { put "Container: $_" }
    when Scalar            { put "Scalar container: $_" }
    when Array             { put "Array Container: $_" }
    default                { put "Object: $_"    }
    }

I get:

name: Array VAR: Scalar
Array Container: a b c
name: Array VAR: Scalar
Array Container: d e f a b c
name: List VAR: Scalar
Object: 1 2

I can see that I can match the types Array type matches, but I thought checking that something can FETCH or STORE would be the right match.

like image 853
brian d foy Avatar asked Jan 11 '17 13:01

brian d foy


1 Answers

Not sure what you're asking here, but given your input, the output is as expected.

A simplified example for clarification:

my (@a, @b, @c);
my @ab = @a, @b, @c;

for @ab {
    say "{.^name} contained in a {.VAR.^name}";
}

which will output

Array contained in a Scalar

three times, no matter the contens of @a, @b and @c.

Remember, there's no implicit flattening in Perl6, and array mutbility (of non-native arrays) is realized by putting its elements in scalar containers.


Given the edit to your question, perhaps the following code will further clarify what's going on:

# make argument raw so binding won't mess with it
sub info($_ is raw) {
    dd $_;
    put "  value type: {.^name}";
    put "  VAR type: {.VAR.^name}";
    put "  can fetch: {so .VAR.can('FETCH')}";
    put "  can store: {so .VAR.can('STORE')}";
}

my \values = 42, my $ = 42, [1, 2], (1, 2);
info $_ for values;

put "\n";

# put values in array, which wraps them in a scalar container
info $_ for [values];

Note that only lists and arrays can STORE (but not FETCH), while scalars can do neither.

This might be a surprise: For one, we might have expected that anything assignable should provide a STORE.

Looking at the implementation, we see that for variables with sigil @ and %, we do call STORE, but not so for variables with a $ sigil. If we went further down the rabbit hole, we'd eventually end up at the VM level container specification, which is how assignment to scalar containers (or the invocation of a Proxy object's STORE method) is implemented.

like image 95
Christoph Avatar answered Sep 21 '22 11:09

Christoph