Henry Baragar Henry.Baragar-at-instantiated.ca |Perl 6| wrote:
On May 23, 2009 11:26:16 pm John M. Dlugosz wrote:
 > From whence did it get its Item container?

OK, my brain made a wrong turn some time on Tuesday.

Let me review the basics.

 From S02:
|$x| may be bound to any object, including any object that can be bound

to any other sigil.

Perl variables have two associated types: their "value type" and their
"implementation type".
Value type = "of", implementation type is the type of the container itself.

    my $spot is Scalar;             # this is the default

I think (that I may be getting out of my depth here) that the implementation type refers to the container at a deeper level. That is, Scalar is a Perl container and not a Java nor Ruby container, which allows having objects from different languages (with their different semantics) in a single application.

That's right. The way I learned it (and I worry about these early-learned principles being out of date!) is that using something other than the default Scalar class is like "tieing" in Perl 5. You create your own item container that (presumably, following Perl 5's names) implements STORE and FETCH. That could be a foreign variable I suppose.

If you wrote a class MyScalar, it could, for example, access the Windows "registry" when accessed, or automatically read or update a value from a GUI form.

 From S03:

A new form of assignment is present in Perl 6, called /binding/, used in
place of typeglob assignment. It is performed with the |:=| operator.
Instead of replacing the value in a container like normal assignment, it
replaces the container itself. For instance:

    my $x = 'Just Another';
    my $y := $x;
    $y = 'Perl Hacker';

At first, I thought that this was a aliasing mechanism, but now I worry that this is how we have to assign non-Perl variables in a Perl application. That is, the semantics of assignment differ depending the container type.

I'm assuming that the container defines what item assignment means. At the very least, it will have the STORE method. But I want to have infix:<=> definable in general without having to make it masquerade as an Item Container.

 From S12:

Method calls on mutable scalars always go to the object contained in the
scalar (autoboxing value types as necessary):

    $result = $object.doit();
    $length = "mystring".codes;

Method calls on non-scalar variables just calls the |Array|, |Hash| or

|Code| object bound to the variable:

    $elems = @array.elems;
    @keys  = %hash.keys;
    $sig   = &sub.signature;

Use the prefix |VAR| macro on a scalar variable to get at its underlying

|Scalar| object:

    if VAR($scalar).readonly {...}


So, if you say

    my $x;

then $x is bound to a newly-created Scalar (not worrying about
conflating the name the Role and the concrete type at this point).

    my $x = 'Just Another';

Now the "item assignment" operates on the container, storing the Str
instance within it.  $x is bound to a container, and the container
contains (only) one Str instance.

Rephrasing: $x is a Perl container holding a Str object whose content (value?) is 'Just Another'.
Agree.  Scalar is a type of item container.

Basically, I was thinking that scalar variables always are bound to item
containers which contain the actual value.  In fact, this was originally
drilled into me:  containers vs values!  That variables always directly
hold some kind of container.  I suppose that's been changed at some
point, perhaps long ago, but the synopses didn't dissuade me from that
early belief.

I don't think it has been changed, I think that if you don't understand how "tie" is implemented in Perl5 (which is referenced heavily in the synopsis), then it is easy to miss the distinctions being made. (It doesn't help that the Implementation type is in the middle of a bunch of "higher level" types).

Taken literally, it has: "$x may be bound to any object, including any object that can be bound to any other sigil." That means that $x may be bound to an item container containing some other object, or may be bound directly to some other kind of object. That's my fundamental understanding at this point. Unless something *really*strange* has become of "item container" ... (Larry, please?)
Anyway, as for your (Henry) example from Rakudo:

    my $x = 1, 2, 3;

According to the synopses, this should be analogous to the previous
example, where $x now is bound to an item that contains a Capture
containing 3 Ints.

Assuming Capture vs Array is simply out of date implementation, just
focus on the parameter passing.  $x is bound to a Scalar.  But What I
Mean is for the formal parameter @y to get bound to the item in the
container, the list of Ints.

===>    How does that happen?

The "List prefix precedence" section of Synopsis 3 says that it returns a list. It goes on a bit about the "contortions" that must be done to do this.
"it returns a list". What is "it"? And there is no operator listed under "list prefix precedence" here. The = is "pseudo-assignment" if you uniformly apply that term to ALL declarations, not just those that take place in different "episodes", like state and constant. Otherwise, it is "item assignment" since the left is a single scalar lvalue. The latter won't like the comma though. So the grammar might be taking it differently? Owell, write
   my $x;
   $x = 1,2,3 ;    # syntax legal??
just to avoid being distracted with yet another issue.

Now back to straightening out my misconceptions about scalars _always_
holding item containers.  If $x is bound to an Array, for example, the
compiled code can't be doing the indirection innately.

So it follows that the method forwarding is a property of the object
that the method is originally called on.  That is, the Scalar (and any
"tied" item container implementations) are written to forward all
methods to the contained object.  The compiler sees $x.foo() and doesn't
know anything about $x other than that it's some object, so it codes a
message dispatch to it.  If $x holds a normal object, the foo method
gets called via the normal dispatching rules.  But Scalar implements
something that catches all methods and forwards them to the contained item.

===>    Right?

Not quite (I think). As mentioned above, I think that the Scalar is the the thing that knows how/which dispatch to use.
That would be the .HOW of the object. I think we're not on the same page here.

That would imply that if a scalar happened to contain another scalar, e.g.
    my $x = Scalar.new;
($x is bound to a Scalar which contains a Scalar which contains undef)
then any method called on $x would trigger the same behavior when the
contained object gets it, and be forwarded all the way down, no matter
how many Scalars I nested in this manner.

So how does VAR work?  It can't just wrap another level around the
original object to cancel out the automatic indirection.  It can't tell
the compiler to generate different code, since the code knows nothing
about this interesting property of scalars.  Instead it must return a
proxy that knows how to trigger the actual methods on the scalar,
avoiding the forwarding behavior of normal method calls.

===>   Is that right?

Relying on rakudo again:

        > my $x; say $x.WHAT
        > my $x = Scalar.new; say $x.WHAT
        Could not find non-existent sub Scalar

VAR is not mentioned in that example.

Reply via email to