On Tue, May 6, 2008 at 8:09 PM, Larry Wall <[EMAIL PROTECTED]> wrote:
> On Tue, May 06, 2008 at 07:01:29PM -0700, Jon Lang wrote:
>  : 1. Apparently, my presumption that $x.WHAT was for retrieving the
>
> : value type was wrong; from the above, it's sounding like it is
>  : supposed to retrieve the implementation type.
>
>  I don't know what you mean by those terms.

Oh?  I took them straight out of S2:

"Explicit types are optional. Perl variables have two associated
types: their "value type" and their "implementation type". (More
generally, any container has an implementation type, including
subroutines and modules.) The value type is stored as its of property,
while the implementation type of the container is just the object type
of the container itself. The word returns is allowed as an alias for
of.

"The value type specifies what kinds of values may be stored in the variable."

By my reading of this: given "my Dog|Cat $x", the value type would be
"Dog|Cat", since you've specified that $x can store values that are
Dogs or Cats.

>  .WHAT gives you an value
>  of undef that happens to be typed the same as the object in $x,
>  presuming your metaobject believes in types.  .HOW gives you the
>  metaobject that manages everything else for this object.  It might
>  or might not believe in classes or types.

OK; that's what I thought you were saying.

>  : Is this correct?  If
>  : so, for what purpose does $x.WHAT exist that you can't do just as well
>  : with $x itself?
>
>  You can do type reasoning with the WHAT type just as you can with
>  a real value of the same type.  Int is a prototypical integer from
>  the standpoint of the type system, without actually having to *be*
>  any particular integer.

Yes; but what can you do with $x.WHAT that you _can't_ do just as
easily with $x itself?  After all, you've already got $x; and it has
already been initialized with an undefined Int upon creation, making
it a prototypical integer until such time as you assign a value to it.
 Furthermore, whether or not it has a value is utterly immaterial for
type-checking purposes.  So why would I ever say $x.WHAT instead of
just $x?

>  In contrast, the .HOW object for Int is very much *not* an Int.
>  Perl doesn't know or care what the type of the .HOW object is, as
>  long as it behaves like a metaclass in a duck-typed sort of way.
>  It's probably a mistake to try to use the type of the .HOW object in
>  any kind of type-inferential way.

That's more or less what I understood.

>  : If it's for the stringification of the container's
>  : name, couldn't that be accomplished just as easily by means of a
>  : $x.HOW method, such as $x.^name?
>
>  No, that's not what it's for at all.  It's only convenient that it
>  generally stringifies to something that looks like a package name,
>  assuming it's not an anonymous type.  But the primary purpose is to
>  provide a closed system of types that is orthogonal to whether the
>  object is defined or not.  In Haskell terms, they're all Maybe types,
>  only with a little more ability to carry error information about
>  *why* they're undefined, if they're undefined.

Right.  I didn't think that the stringification was a big deal; but it
was the only thing that I could find that differentiated $x from
$x.WHAT.

>  : 2. How _do_ you retrieve the value type of $x?
>
>  Do you mean the variable, or its contents?  The contents returns its
>  object type via $x.WHAT, which for an Int is always Int, regardless
>  of any extra constraints imposed by the container.

I've been assuming that the value type is associated to the variable;
otherwise, a simple assignment of a completely different container to
the variable would completely bypass any and all constraints.  Am I
wrong about this?

>  : That is, how can the
>  : program look at $x and ask for the constraints that are placed on it?
>
>  Placed by the variable, or by the type of the contents?  The
>  constraints on the value are solely the concern of whatever kind of
>  object it is.  If you mean the constraints of the container, then
>  VAR($x).WHAT will be, say, Scalar of Int where 0..*, and VAR($x).of
>  probably can tell you that it wants something that conforms to Int.
>  I'm not sure if the "of" type should include any constraints, or just
>  return the base type.  Probably a .where method would return extra
>  constraints, if any.

OK; I'll have to look up what I can about VAR.

>  : I don't see $x.HOW being useful for this, since HOW is essentially
>
> : there to let you look at the inner workings of the container; and none
>  : of the other introspection metamethods in S12 come close to addressing
>  : this question.
>
>  $x.HOW is not the inner workings of the container, but of the value.
>  You'd have to say VAR($x).HOW to get the inner workings of the
>  container.  Scalar containers always delegate to their contents.  In
>  contrast, @x.HOW would be equivalent to VAR(@x).HOW, because composite
>  objects used as scalars assume you're talking about the container.

...and you appear to be using "container" differently than I am; I was
(perhaps sloppily) using it as a synonym of "value".  I was thinking
in terms of implementation type:

"The implementation type specifies how the variable itself is
implemented. It is given as a trait of the variable:

    my $spot is Scalar;             # this is the default
    my $spot is PersistentScalar;
    my $spot is DataBase;"

...OK; I've been looking at this a bit skewed.  I've been seeing
"value type" as being attached to the variable and defining what can
and cannot be assigned to it, while "implementation type" was
registering in my mind as the class of the object that the variable is
pointing to.  Upon closer reading, that appears not to be the case.

OK; let me try this again:

How would I find out what type constraints have been placed on the
variable $x, in the sense of which values can be assigned to it?  I'm
getting ready to say "$x = $y"; but before I do, I want to check to
make sure that $x will accept $y's value:

   my Cat|Dog $x;
   my Dog|Elephant $y;
   $y = new Dog;
   # test to see if $x will be able to accept $y's value.  Since $y is
a Dog, the answer is yes.
   $y = new Elephant;
   # test to see if $x will be able to accept $y's value.  Since $y is
now an Elephant, the answer is no.

What code would I use to perform the above tests?

Likewise, let's say that I've defined a couple of subsets of Int:
prime numbers and even numbers.  $x is restricted to prime numbers,
and $y is restricted to even numbers; I want to check to see if $y's
value can be assigned to $x before actually attempting the assignment.

My impulse is to go with something where I can extract a
Signature-like pattern from $x which I can then use with
smart-matching; e.g.:

   if $y ~~ $x.valid_values { ... }

-- 
Jonathan "Dataweaver" Lang

Reply via email to