When I re-enter my blog, I am already authorized. How to avoid this?
my TypeName $x;
Hello Guest
  
  • Login
• Register…
• Start blog
  • Who, Where, When
• What can I do?
• What to Read?
  • Polls
• Avatars
• Interests
  • Cities and Countries
• Random blog
• Users search
  • Search
• Games
• Tests
• QAIX
  • Talxy Chat
• Horoscope
• Online
 
Зарегистрируйся!

QAIX > Perl web-programming > my TypeName $x; 9 May 2008 16:24:32

  Recent blog posts: 
  They have birthday today: 
  Forums:   
  Discuss: 
  Recent forum topics: 
  Recent forum comments:
  Moderators:

my TypeName $x;

Jonathan Worthington 9 May 2008 16:24:32
 Hi,

I'm looking for answers/clarificati­on on what (if taken as individual
programs) $x is in each case.

my Int $x; # $x is Int protoobject
say $x; # Int
say $x.WHAT; # Int

class Foo { }
my Foo $x; # $x is Foo protoobject
say $x; # Foo
say $x.WHAT; # Foo
# This means we can only assign to $x something that isa Foo?

role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?

subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the constraint

class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat

Thanks,

Jonathan
OptionsAdd comment
Jon Lang 6 May 2008 15:09:41 permanent link ]
 My thoughts:
.HOW returns information concerning the implementation type; .WHAT
returns information concerning the value type.
.HOW and .WHAT stringify to something resembling the declarations that
would be used to create them.

Also bear in mind that Perl 6 uses prototype-based object orientation,
except where it doesn't. As such, when I say that "$x is a Foo"
below, what I mean is that "$x is an object with Foo as its
implementation type".

Jonathan Worthington wrote:
Hi,
I'm looking for answers/clarificati­on on what (if taken as individual
programs) $x is in each case.
my Int $x; # $x is Int protoobject
say $x; # Int
say $x.WHAT; # Int

.WHAT is an Int; stringifies to "Int".

class Foo { }
my Foo $x; # $x is Foo protoobject
say $x; # Foo
say $x.WHAT; # Foo
# This means we can only assign to $x something that isa Foo?

.WHAT is a Foo; stringifies to "Foo".

role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?

This one's tricky: roles cannot be instantiated, so .WHAT cannot be a
Bar. My gut reaction is that it's an anonymous class that does Bar
and stringifies to "Bar". As long as you don't have both a role and a
class named "Bar", this should not be a problem, since the value type
isn't concerned with the implementation. If it is possible to have
both a role and a class with the same name, you might be able to look
at .WHAT.HOW (or .^WHAT) to figure out with which you're dealing.
That is, the implementation type of the value type ought to provide
more elaborate detail as to the nature of the value type.

subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the constraint

my guess: .WHAT is an EvenInt that stringifies to "EvenInt". If you
want to know about the structure of EvenInt (e.g., which class is it
based on, and which subset restrictions have been applied to it), you
would refer to .WHAT.HOW.

class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat

my guess: .WHAT is a Junction that stringifies to "Dog|Cat". To
access the details as to which classes are in the junction and how
they are joined, refer to appropriate methods (I believe that Junction
includes a method that returns a Set of its members) or maybe to
.WHAT.HOW.

As well:

class Dog { }
role Pet { }
my Pet Dog $x;
say $x;
say $x.WHAT;

My guess is that .WHAT would be a (dis)Junction of a Dog and an
anonymous class; the anonymous class does Pet and stringifies to
"Pet", while the Junction stringifies to "Pet Dog".

--
Jonathan "Dataweaver" Lang
Add comment
Jon Lang 6 May 2008 18:15:29 permanent link ]
 Upon further review:

It might be possible that $x.WHAT returns a Signature object, with the
value type of $x as the invocant (or return type?), and everything
else empty. But that merely begs the question of how to introspect a
Signature object. If I tell Perl 6 to say a Signature, what gets
displayed? Can I ask Perl 6 to look at a particular parameter in a
Signature? If so, what kind of object does the Signature object
return if I ask it to give me its invocant? Surely not another
Signature object? Whatever it is that Perl 6 returns in that case
would probably work better as the return type of the .WHAT method,
too.

--
Jonathan "Dataweaver" Lang
Add comment
Brandon S. Allbery KF8NH 6 May 2008 18:32:03 permanent link ]
 
On 2008 May 6, at 10:15, Jon Lang wrote:

Signature? If so, what kind of object does the Signature object
return if I ask it to give me its invocant? Surely not another
Signature object? Whatever it is that Perl 6 returns in that case

Turtle? :)­

--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com
system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu­
electrical and computer engineering, carnegie mellon university KF8NH


Add comment
TSa 6 May 2008 19:55:15 permanent link ]
 HaloO,

Jon Lang wrote:
My thoughts:
.HOW returns information concerning the implementation type; .WHAT
returns information concerning the value type.

My addition to these thoughts is that the WHAT and HOW are
cascaded. Let's say we start at level 0 with the objects,
thingies or however we want to name the atoms of our discourse.
At the zero level HOW, WHAT etc. are vacuously identical with
the object. They fall apart on level 1 from each other and among
them selfs but they are all sets of level-0 objects. In general
a level n concept contains level 0..^n "objects" and is the name
for a something they share.


.HOW and .WHAT stringify to something resembling the declarations that
would be used to create them.

Yeah. Stringification is relatively easy.


class Foo { }
my Foo $x; # $x is Foo protoobject
say $x; # Foo
say $x.WHAT; # Foo
# This means we can only assign to $x something that isa Foo?
.WHAT is a Foo; stringifies to "Foo".

Note that $x is not initialized. This means the say has to
give something like "undef of Foo".


role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?
This one's tricky: roles cannot be instantiated, so .WHAT cannot be a
Bar.

What? I would say it is a level 1 WHAT. The next level concept
$x.WHAT.WHAT is role. BTW, there are not very many levels up.


My gut reaction is that it's an anonymous class that does Bar
and stringifies to "Bar". As long as you don't have both a role and a
class named "Bar", this should not be a problem, since the value type
isn't concerned with the implementation. If it is possible to have
both a role and a class with the same name, you might be able to look
at .WHAT.HOW (or .^WHAT) to figure out with which you're dealing.
That is, the implementation type of the value type ought to provide
more elaborate detail as to the nature of the value type.

Hmm, are these meta accessors commutative? I.e. are
$x.WHAT.HOW and $x.HOW.WHAT the identical level 2 entities?
I would rather opt for $x.HOW of a role .WHAT.WHAT to be
the level 1 undef which is a set of interesting level 0 values
of undef.


subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the constraint
my guess: .WHAT is an EvenInt that stringifies to "EvenInt". If you
want to know about the structure of EvenInt (e.g., which class is it
based on, and which subset restrictions have been applied to it), you
would refer to .WHAT.HOW.

I would argue that $x.WHAT.WHAT is subset. I think the
idea of introspection is to have $x.WHAT.of return Int
as a level 1 WHAT and $x.WHAT.where return the constraint
closure. That said I would expect $x.HOW to be the identical
level 1 HOW object that $x.WHAT.of.HOW returns. When Int.WHAT.WHAT
is a role then this is undef of Int.


class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat
my guess: .WHAT is a Junction that stringifies to "Dog|Cat". To
access the details as to which classes are in the junction and how
they are joined, refer to appropriate methods (I believe that Junction
includes a method that returns a Set of its members) or maybe to
.WHAT.HOW.

On level 1 the WHATs of Dog and Cat are distinct. Dog|Cat is a level 2
WHAT. The level 2 $x.WHAT.HOW is a union. $x.WHAT.WHAT is class.


As well:
class Dog { }
role Pet { }
my Pet Dog $x;
say $x;
say $x.WHAT;
My guess is that .WHAT would be a (dis)Junction of a Dog and an
anonymous class; the anonymous class does Pet and stringifies to
"Pet", while the Junction stringifies to "Pet Dog".

Again the say $x should print "undef of Pet Dog". Similar to above
$x.WHAT.HOW is an intersection. But $x.WHAT.WHAT is role|class and
the question is what their common abstraction is. Though, whatever
it is, you get it with $x.WHAT.WHAT.WHAT. But you can't call .new
on it. The $x.HOW might be Dog but $x can't store an object created
by its .new method because Dog.new.WHAT is in the part of the level
1 Dog that is not part of the level 2 WHAT Pet Dog. So to initialize
you need

my Pet Dog $x = .new does Pet;

After this $x.HOW.HOW is Dog. Since the anonymous class created by
does is not of interest the $x.WHAT remains the level 2 WHAT Pet Dog.


I know that this sounds like "turtles all the way down" but the
levels of abstraction are all derived from the source code. So,
as long as your source is finite so is the WHAT structure over
the objects. The worst that can happen is that there is a 1:1
mapping between a lower level at the one above it.
--

"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
"Simplicity does not precede complexity, but follows it." -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Add comment
Jon Lang 6 May 2008 22:01:36 permanent link ]
 TSa wrote:
Jon Lang wrote:
My thoughts:
.HOW returns information concerning the implementation type; .WHAT
returns information concerning the value type.

BTW, S12 more or less confirms the above: .WHAT returns a prototype
object that stringifies to its short name, while .HOW allows
introspection of the attributes and methods and composed roles and
inherited classes and...

My addition to these thoughts is that the WHAT and HOW are
cascaded. Let's say we start at level 0 with the objects,
thingies or however we want to name the atoms of our discourse.
At the zero level HOW, WHAT etc. are vacuously identical with
the object. They fall apart on level 1 from each other and among
them selfs but they are all sets of level-0 objects. In general
a level n concept contains level 0..^n "objects" and is the name
for a something they share.

In English, please?

I _think_ that you're saying that you can use WHAT and HOW
recursively: that is, you can talk about WHAT.WHAT, WHAT.HOW,
HOW.WHAT, HOW.HOW, etc. If so, note a few caveats:
first, if $x is a Foo, then $x.WHAT will be a Foo. As such, there is
no difference between $x.WHAT and $x.WHAT.WHAT. Likewise, forget
about my comments about $x.WHAT.HOW; since $x is of exactly the same
type as $x.WHAT, you can get the same information by saying $x.HOW as
you could about $x.WHAT.HOW.

Second, $x.HOW.WHAT gives you a prototype of the metaclass object. If
you're ever doing type checking that refers to the "metaclass class",
this might be useful; otherwise, don't bother.

Third, $x.HOW.HOW would let you look at the inner workings of the
"metaclass class". Going beyond that would be redundant, since you'd
be using a metaclass object to look at the metaclass class.

role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?
This one's tricky: roles cannot be instantiated, so .WHAT cannot be a
Bar.
What? I would say it is a level 1 WHAT. The next level concept
$x.WHAT.WHAT is role. BTW, there are not very many levels up.

Again, English please?

As I said, roles cannot be instantiated. $x is not a Bar; it is an
object of an anonymous class that does Bar. $x.WHAT is a prototype
object of $x, meaning that it, too, is an object of an anonymous class
that does Bar. The only difference between them is that $x may
eventually have a value assigned to it; $x.WHAT never will. Well...
that, and $x.WHAT stringifies differently than $x does.

subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the
# constraint
my guess: .WHAT is an EvenInt that stringifies to "EvenInt". If you
want to know about the structure of EvenInt (e.g., which class is it
based on, and which subset restrictions have been applied to it), you
would refer to .WHAT.HOW.
I would argue that $x.WHAT.WHAT is subset. I think the
idea of introspection is to have $x.WHAT.of return Int
as a level 1 WHAT and $x.WHAT.where return the constraint
closure. That said I would expect $x.HOW to be the identical
level 1 HOW object that $x.WHAT.of.HOW returns. When Int.WHAT.WHAT
is a role then this is undef of Int.

Ah; _that's_ what you mean by cascading levels. Ugh.

By my understanding, $x and $x.WHAT are both the same kind of thing:
they're both EvenInt. Again, the only difference is that $x.WHAT will
always be undefined and will stringify to "EvenInt".

class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat
my guess: .WHAT is a Junction that stringifies to "Dog|Cat". To
access the details as to which classes are in the junction and how
they are joined, refer to appropriate methods (I believe that Junction
includes a method that returns a Set of its members) or maybe to
.WHAT.HOW.
On level 1 the WHATs of Dog and Cat are distinct. Dog|Cat is a level 2
WHAT. The level 2 $x.WHAT.HOW is a union. $x.WHAT.WHAT is class.

Huh?

--
Jonathan "Dataweaver" Lang
Add comment
Larry Wall 7 May 2008 00:07:57 permanent link ]
 On Tue, May 06, 2008 at 10:54:51AM +0200, Jonathan Worthington wrote:
Hi,
I'm looking for answers/clarificati­on on what (if taken as individual
programs) $x is in each case.
my Int $x; # $x is Int protoobject
say $x; # Int
say $x.WHAT; # Int

What they said. $x is initialized with an Int protoobject.

class Foo { }
my Foo $x; # $x is Foo protoobject
say $x; # Foo
say $x.WHAT; # Foo
# This means we can only assign to $x something that isa Foo?

Yes, but that's because the container is checking, not the Foo
protoobject.

role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?

Correct, and for the same reason. The container checks the role--it
has little to do with what's in $x currently, which *cannot* have
the type of Bar, since you can't instantiate that.

subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the constraint

Yes, again, checked by the container, not by $x. $x cannot have the
type of a subset either! The actual type of $x is Int. Objects may
only be blessed as valid storage types of some kind or other. Subsets
are merely extra constraints on a storage type (here Int).

class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat

Well, maybe $x is just Object, or whatever is the closest type that
encompasses both Dog and Cat. But note that Object is just the most
generic kind of undef, so this is more or less equivalent to doing
no initialization in p5-think. I don't think I'm interested in making
the run-time system calculate a Dog|Cat storage type, so it comes out
to just a constraint.

Really, the main reason we initialize with an undef of the correct sort
is so that you can say

my Dog $x .= new();

But what would (Dog|Cat).new() do? Constructors are not required to
know about subset types or roles. Constructors just create plain ordinary
classes, I expect. Composition and constraint checking happen
elsehwere.

Larry
Add comment
Jon Lang 7 May 2008 06:01:29 permanent link ]
 Larry Wall wrote:
Jonathan Worthington wrote:
role Bar { }
my Bar $x; # $x is ???
say $x; # ???
say $x.WHAT; # ???
# This means we can only assign to $x something that does Bar?
Correct, and for the same reason. The container checks the role--it
has little to do with what's in $x currently, which *cannot* have
the type of Bar, since you can't instantiate that.
subset EvenInt of Int where { $_ % 2 == 0 };
my EvenInt $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that matches the constraint
Yes, again, checked by the container, not by $x. $x cannot have the
type of a subset either! The actual type of $x is Int. Objects may
only be blessed as valid storage types of some kind or other. Subsets
are merely extra constraints on a storage type (here Int).
class Dog { }
class Cat { }
my Dog|Cat $x; # $x is ???
say $x; # ???
say $x.WHAT; # Failure?
# This means we can only assign to $x something that isa Dog or isa Cat
Well, maybe $x is just Object, or whatever is the closest type that
encompasses both Dog and Cat. But note that Object is just the most
generic kind of undef, so this is more or less equivalent to doing
no initialization in p5-think. I don't think I'm interested in making
the run-time system calculate a Dog|Cat storage type, so it comes out
to just a constraint.
Really, the main reason we initialize with an undef of the correct sort
is so that you can say
my Dog $x .= new();
But what would (Dog|Cat).new() do? Constructors are not required to
know about subset types or roles. Constructors just create plain ordinary
classes, I expect. Composition and constraint checking happen
elsewhere.

Two questions:

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. Is this correct? If
so, for what purpose does $x.WHAT exist that you can't do just as well
with $x itself? 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?

2. How _do_ you retrieve the value type of $x? That is, how can the
program look at $x and ask for the constraints that are placed on it?
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.

--
Jonathan "Dataweaver" Lang
Add comment
Larry Wall 7 May 2008 07:09:54 permanent link ]
 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. .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.


: 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.

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.

: 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.

: 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.

: 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.

: 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.

Larry
Add comment
Jon Lang 7 May 2008 08:08:36 permanent link ]
 On Tue, May 6, 2008 at 8:09 PM, Larry Wall <larry@wall.org> 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
Add comment
TSa 8 May 2008 20:59:32 permanent link ]
 HaloO,

Larry Wall wrote:
.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.

Why does the metaobject have to believe in types? I think it
suffices to define that .WHAT returns a unique binding in the
scope of interest. This binding can naturally be checked with
=:= e.g. as in 3.WHAT =:= 4.WHAT =:= Int. Interesting is
that you need parens for negative numbers (-2).WHAT =:= Int.
Well, you can write that as WHAT -3 =:= Int.


.HOW gives you the
metaobject that manages everything else for this object. It might
or might not believe in classes or types.

Fair enough. I infer that the HOW deals with non-MMD dispatch only.
That is, MMD is purely WHAT based. Now consider

subset Even of Int where {$_ % 2 == 0}

multi foo (Int $x) { "Int" }
multi foo (Even $x) { "Even }

MMD collects the applicable targets first. That results in foo(3)
returning "Int" as expected. But foo(2) throws an exception because
the Even constraint allowed the second target into the set of
candidates. This is because 2.WHAT =:= Int is an exact match in both
cases. Now how do we use the constraints as tie breakers? That amounts
to comparing {$_ % 2 == 0} to {$_ .does: Int}. That might be possible
here because 2.WHAT.of =:= Int and the presence of a subset declaration
documents the programmer's intent nominally.

But when the subset is instead written

subset Even of Num where {$_ % 2 == 0}

then foo(2) says "Int" because 2.WHAT =:= Int is more specific than
Num *before* any subset declarations are used for tie breaking. Do we
want this behavior?

Now I assume the infix:<as> takes the WHAT of its rhs and stores
it in the WHAT of the lhs if the value of the lhs meets the constraint
of the rhs.WHAT. Whether that constitutes a mutation or not, is
debatable. This makes foo(2 as Num) return "Even" as expected.

Now I bring a container into my contemplation.

my Num $two = 2;

It is conjectured that this Num constraint on the container
behind the name $x somehow acts as the infix:<as> before. That
is foo($two) returns "Even". This implies that a container
*erases* type information in its FETCH method. Note that this
does not change the HOW dispatch on the value in $two. So e.g.
$two.add(2) dispatches e.g. to Int::add(Int ::T $other --> T).
BTW, this also implies that the ::T syntax captures the WHAT
of the arguments bound to $other so that it can be stuffed
into the WHAT of the return value. The compiler might actually
do that automatically. That is the genericity John Dluglosz is
talking about. Note that this WHAT assignment can fail!

sub foo (Int ::T $x is rw --> T) { $x++; }

$two = 2 as Even; # assignment OK, Even .does: Num

my $y = foo($two); # 3 as Even fails!

Even though the assignment $y = 3 would work, foo fails
to adhere to its own constraint! Typing is tricky business.
Note that $two == 3 as expected. The actual implementation
of ++ dispatches to 2.HOW, of course. That instanciates
the 3 with 3.WHAT =:= Int as usual. A corollary here is
that '2 as Even === 2' is false. Or does === check the HOWs?

The thing that is bothering me is to define a partial order
on the WHATs, i.e. a binary, reflexive, transitive and
anti-symmetric relation <: and perhaps its companion :>
that is not !<: because that drops the =:= case. In the spec
this goes as "type narrowness" or "topological order".

Since the typing shall be nominal I propose the syntax

subset Even <: Int where {$_ % 2 == 0}

to mean that containers carrying that type as their constraint
*automatically* re-assign the WHAT to Even whenever a matching Int
comes in. The rhs of <: is a pre-constraint in this case. The dispatcher
does the same when an Int versus Int tie occurs as above and
re-dispatches with this new type. An 'of' subset would not have
this automatic re-typing behavior.

The type checker might or might not be able to proof the validity
of <: in general but an implementation can restrict the sub-language
applicable in a where block to make the type system decidable.

For so-called mutable types this re-typing can become more involved.
That is there is a 1:1:n relation between the HOW and WHICH on the one
hand and the WHATs on the other. This sort of means that the WHAT
becomes a junction.

class C does A does B {...} # enters C into WHAT space

my $y = C.new; # $y.WHAT =:= C

my $b <: B; # automatically re-typing container
my $a <: A; # means e.g. my A $a is autotype

$b = $y; # now $y.WHAT =:= B
$a = $y; # now $y.WHAT =:= (A&B)

This last assignment has to enter the meet type (A&B) into the
type lattice because simply re-typing a B to an A is not possible
unless A <: B holds. This needs to be declared explicitly somewhere.
The declaration of class C doesn't do that, of course. So programs
not using <: don't incur the type calculation overhead.

If we repeat the above sequence with a class D and a variable $x
respectively, the value of $x ends up in the identical WHAT (A&B)
instance set. But the HOW of the instances of this WHAT becomes
inhomogeneous in the way how the combined roles A and B are done.

Note that this WHAT based MMD doesn't do anything with the objects.
This can be done only through the HOW dispatch. Another effect is
that (A|B) is never entered into WHAT space automatically. There
must be extra syntax to implement a join type that contains instances
outside of (A&B). My idea is to write

class C does A|B {...}

my B $b = C.new; # type error
my A $a = C.new; # type error

Correspondingly 'does A&B' would behave so that fresh instances
of C get WHAT (A&B) right from the start not lazily by constraint
checking of containers and dispatchers the value passes through.

This type calculus also can be applied when containers are bound
together.

class Cab does A does B {...}
class Ca does A {...}

my $x = C.new; # $x.WHAT =:= C
my $b <: B;
my $a <: A;

$a = $x; # OK, $x.WHAT =:= A
$b := $a; # OK, $x.WHAT =:= A&B

$a = Ca.new; # type error, constraint is now A&B

This constraint merging upon binding should be done for all containers,
BTW.


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.

Isn't it then more practical to make

my Int $x; # no initialization

mean

my Int $x = one(Int);

and do the reasoning junctively?


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.

I agree. But note that HOW and WHAT compete for the same slots
in the namespace which lets me think that we might need the
pseudo-namespaces HOW and WHAT besides things like OUR, MY,
OUTER, CALLER or GLOBAL.



: 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..*,

You mean a non-negative Int, right?

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.

Note that constraints are special closures that always return either
True or False, never throw exceptions and have no side effects. To
use them for type checking is easy. You just call them with a value.
But how do you compare them other than exhaustively sampling them?


Regards, TSa.
--

"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
"Simplicity does not precede complexity, but follows it." -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Add comment
TSa 9 May 2008 16:24:32 permanent link ]
 HaloO,

I wrote:
class C does A does B {...} # enters C into WHAT space
my $y = C.new; # $y.WHAT =:= C
my $b <: B; # automatically re-typing container
my $a <: A; # means e.g. my A $a is autotype
$b = $y; # now $y.WHAT =:= B
$a = $y; # now $y.WHAT =:= (A&B)
This last assignment has to enter the meet type (A&B) into the
type lattice because simply re-typing a B to an A is not possible
unless A <: B holds. This needs to be declared explicitly somewhere.
The declaration of class C doesn't do that, of course. So programs
not using <: don't incur the type calculation overhead.

I left out the fact that after the declaration of C as
above there are then the four types C, A, B, and A&B in
WHAT space. They form the following lattice with the left
of <: going downwards.

A B
\ /
A&B
|
C

This type A&B there means everything that makes the closure
{ .does: A && .does: B} return True. With a junction this
can of course be written {.does: A&B}. The lattice is calculated
lazily as described in my previous mail.

The thing I want to add is that all classes that inherit from C
without adding additional roles are incomparable to C as far
as WHAT is concerned but all of them will eventually end up as
subtypes of A&B in their WHAT if containers and the dispatcher
use automatic type re-assignment.


Regards, TSa.
--

"The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
"Simplicity does not precede complexity, but follows it." -- A.J. Perlis
1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
Add comment
 

Add new comment

As:
Login:  Password:  
 
 
  
 
Пожалуйста, относитесь к собеседникам уважительно, не используйте нецензурные слова, не злоупотребляйте заглавными буквами, не публикуйте рекламу и объявления о купле/продаже, а также материалы нарушающие сетевой этикет или УК РФ.


QAIX > Perl web-programming > my TypeName $x; 9 May 2008 16:24:32

see also:
Creating Microsoft Access Database…
Getting keyboard scancode, etc.
Reading MSWord Files in Perl
see also:
1) Automated FTP 2) txt to html 3)…
Printing epoch time
OLDB - ODBC
see also:
counting fork process, again
Iteration Question
Preventing null string from matching

  Copyright © 2001—2008 QAIX
Idea: Miсhael Monashev
You can find the help and FAQ in the Admin's blog.
Write us at:
If you would like to report an abuse of our service, such as a spam message, please .