Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Synopsis Questions

11 views
Skip to first unread message

Angel Faus

unread,
Apr 10, 2003, 9:22:36 PM4/10/03
to perl6-l...@perl.org
Hi,

First of all, thanks very much for the Synopsis 6 (very beautifull
indeed).

Some simple random questions:


- Variable types:

1st) Can we use variable types in subroutines signatures??

2nd) In:

sub add(int $x, int $y) {$x + $y}

Do we have enough information to allow the compiler to optimize this
sub?

I mean: $x and $y could be both tied to some heavyweight
implementation, so the compiler won't ever be able to use the type
system for anything useful (in terms of speed)...

Maybe the solution is to not allow mixing variable types and
lower-case value types:

my bit $b is Persistent; # error
my Bit $b is Persistent; # ok

After all, lower-case types are expected to be really, eh, simple.
They cannot have run-time properties associated to them, and one
could argue that a variable type is just a bunch of
FETCH/STORE/DELETE/etc. properties associated to that variable.

3rd) (more open, philosophical kind of question) What are the
legitimate uses of Variable Types? I mean, what can we do that would
be otherwise be impossible? (assuming a class system and some support
for Aspect-Oriented programming)

This may be look a silly question, but whenever I've used tied
variables in perl, I could have done with class-based overloading of
common operations (assignment, fetch, etc..).

Do we really need the dual type system?


- Hierarchical types:

Run-time time type checking is no problem for "simple" types because
it is reasonably fast. But run-time validation of hierarchical types
can be very expensive.

How do we handle this?

sub third_one(@x of Int) {
return @x[3]
}

my @a = 1..1000;
foo(@a);

Is it compile-time error or run-time slow-down?


- The leave Function:

Just to be sure about it: Are anonymous subs (like the -> sub in for
statements) exited with return or with leave?

If exited with return:

sub foo {
for 1..10 -> $i {
return if $i > 0;
}
print "abrakadabra";
}

foo(); # this prints "abrakadabra"

But if exited with leave:

sub foo {
my &is_long = sub {
if length($_) > 100 {return 1} else {return 0}
}

my $result = is_long("not so long sentence"):
print $result;
}

foo(); # this prints nothing because we jump
# over "print"

Mmm..... This is odd. I am quite sure I got something wrong here..


- Assuming on "use"

(use IO::Logging).assuming(logfile => ".log");

What happens if some subroutine in IO::Logging doesn't have the
"logfile" parameter. Is it a compile-time error, or will it be smart
and only curry on the functions that do use the "logfile" parameter?


That's all for now.. :-) Thanks againt to all for the excellent work.

-angel

Larry Wall

unread,
Apr 11, 2003, 2:44:53 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: 1st) Can we use variable types in subroutines signatures??

In general, no. Any variable type is lost if you bind a different
variable to the name, and sub pararameters do binding rather than
copying. There may be some kinds of variable typing that constrain
what you can bind against the variable, however.

Larry

Larry Wall

unread,
Apr 11, 2003, 2:42:03 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: Hi,

:
: First of all, thanks very much for the Synopsis 6 (very beautifull
: indeed).
:
: Some simple random questions:

If you have random questions, they should be put into separate message
threads, or we'll end up with one monstrous "Synopsis Questions" thread
containing 582 messages.

So I'll be answering each question in a separate message.

Larry

Angel Faus

unread,
Apr 11, 2003, 5:08:34 PM4/11/03
to Larry Wall, perl6-l...@perl.org
Friday 11 April 2003 20:42, Larry Wall wrote:
> : Some simple random questions:
>
> If you have random questions, they should be put into separate
> message threads, or we'll end up with one monstrous "Synopsis
> Questions" thread containing 582 messages.
>

Oops. Sorry about that.

I actually hoped that it was actually just a two-messages thread: The
questions, the answers, the approbatory silence. :-)

-angel

Larry Wall

unread,
Apr 11, 2003, 3:10:57 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: Just to be sure about it: Are anonymous subs (like the -> sub in for
: statements) exited with return or with leave?

Some anonymous subs are Routines, and exited with return. Others are
Blocks, and exited with leave. Pointy subs are Blocks.

Larry

Austin Hastings

unread,
Apr 11, 2003, 3:26:00 PM4/11/03
to Larry Wall, perl6-l...@perl.org

Meaning:

my Dog $d;
my Cat $c;

$c := $d;

$d.woof(); # Okay.
$d.meow(); # Bad?

$c.woof(); # Bad?
$c.meow(); # Okay?

Would that behavior change if I actually stuck an object in there?

my Dog $d = Dog.new("Rover");
my Cat $c := $d;

$d.woof();
$d.meow(); # Should always fail: neither the skin nor bones of a dog.

$c.woof(); # Does this succeed since underlying object can woof?
$c.meow(); # Does this compile okay but fail at runtime?

=Austin

Larry Wall

unread,
Apr 11, 2003, 3:17:23 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: - Assuming on "use"

:
: (use IO::Logging).assuming(logfile => ".log");
:
: What happens if some subroutine in IO::Logging doesn't have the
: "logfile" parameter. Is it a compile-time error, or will it be smart
: and only curry on the functions that do use the "logfile" parameter?

No error. Functions or methods that don't have the parameter in
question are merely duplicated.

Larry

Paul

unread,
Apr 11, 2003, 3:40:06 PM4/11/03
to Larry Wall, perl6-l...@perl.org

--- Larry Wall <la...@wall.org> wrote:

"duplicated"??

__________________________________________________
Do you Yahoo!?
Yahoo! Tax Center - File online, calculators, forms, and more
http://tax.yahoo.com

Luke Palmer

unread,
Apr 11, 2003, 3:41:40 PM4/11/03
to Austin_...@yahoo.com, la...@wall.org, perl6-l...@perl.org
> --- Larry Wall <la...@wall.org> wrote:
> > On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
> > : 1st) Can we use variable types in subroutines signatures??
> >
> > In general, no. Any variable type is lost if you bind a different
> > variable to the name, and sub pararameters do binding rather than
> > copying. There may be some kinds of variable typing that constrain
> > what you can bind against the variable, however.
> >
> > Larry
>
> Meaning:
>
> my Dog $d;
> my Cat $c;
>
> $c := $d;

Um, that's an error. $d is like a sub that returns Dogs, and $c is
like as sub that returns Cats. And if you pretend that Dogs are Cats,
you get very messed up when the Cat chases a Squirrel around the yard.

> $d.woof(); # Okay.
> $d.meow(); # Bad?

Yeah.

> $c.woof(); # Bad?
> $c.meow(); # Okay?

Irrelavent.

> Would that behavior change if I actually stuck an object in there?

Well, yeah, the $d.stuff would actually do something besides yell at you.

What he meant by variable type is lost is that the I<variable type> is
lost.

my $d is DogScalar;
my $c is CatScalar;

$c := $d; # Legal. $c is now a DogScalar

Variable type is just an interface, and binding is replacing the
implementation.

Luke

Nicholas Clark

unread,
Apr 11, 2003, 3:53:33 PM4/11/03
to Angel Faus, Larry Wall, perl6-l...@perl.org

Why stop at two? This week it will be two, then next week a there will be
a third message added to the thread with next week's answers. Repeat for
each increment of "this week". :-)

At least we can thank the moties that there will only be three answers to
any question (on the one hand, on the other hand, on the gripping hand)
I don't think I've seen a four value answer yet. But there's always next week.

Nicholas Clark

Me

unread,
Apr 11, 2003, 4:27:29 PM4/11/03
to Hod...@writeme.com, Larry Wall, perl6-l...@perl.org
> > : (use IO::Logging).assuming(logfile => ".log");
> > :
> > : What happens if some subroutine in IO::Logging doesn't have the
> > : "logfile" parameter.
> >
> > Functions or methods that don't have the parameter in
> > question are merely duplicated.
>
> "duplicated"??

The .assuming use creates a copy of the original IO::Logging
module with the parameter declaration parts of some of its
subs changed.

If any IO::Logging sub didn't have a $logfile parameter then
its declaration would be the same in the .assuming version of
the module (assuming the call shown in the first line above).

--
ralph

Larry Wall

unread,
Apr 11, 2003, 3:06:41 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: 2nd) In:

:
: sub add(int $x, int $y) {$x + $y}
:
: Do we have enough information to allow the compiler to optimize this
: sub?

Yes. In my previous message I said that parameters do binding rather
than copying, but this is an oversimplification. Since the parameters
are constant by default, the implied reference semantics can often
be changed to copy semantics.

: I mean: $x and $y could be both tied to some heavyweight

: implementation, so the compiler won't ever be able to use the type
: system for anything useful (in terms of speed)...
:
: Maybe the solution is to not allow mixing variable types and
: lower-case value types:
:
: my bit $b is Persistent; # error
: my Bit $b is Persistent; # ok
:
: After all, lower-case types are expected to be really, eh, simple.
: They cannot have run-time properties associated to them, and one
: could argue that a variable type is just a bunch of
: FETCH/STORE/DELETE/etc. properties associated to that variable.

It probably depends on whether Persistent thinks it can handle
a low-level type or not.

Larry

Larry Wall

unread,
Apr 11, 2003, 4:42:44 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: 3rd) (more open, philosophical kind of question) What are the
: legitimate uses of Variable Types? I mean, what can we do that would
: be otherwise be impossible? (assuming a class system and some support
: for Aspect-Oriented programming)
:
: This may be look a silly question, but whenever I've used tied
: variables in perl, I could have done with class-based overloading of
: common operations (assignment, fetch, etc..).
:
: Do we really need the dual type system?

We do if we're going to do optimizations based on the variable types.
If you only have value types, then it's difficult to know that a given
value is always going to be an integer.

The two concepts do fuzz into each other, though. When you declare
something as "int" rather than "Int", you're really saying something
about the variable type as well as the value type.

Larry

Larry Wall

unread,
Apr 11, 2003, 5:07:29 PM4/11/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
: - Hierarchical types:

:
: Run-time time type checking is no problem for "simple" types because
: it is reasonably fast. But run-time validation of hierarchical types
: can be very expensive.
:
: How do we handle this?
:
: sub third_one(@x of Int) {
: return @x[3]
: }
:
: my @a = 1..1000;
: foo(@a);
:
: Is it compile-time error or run-time slow-down?

Er, you mean third_on(@a)? Depending on the options surrounding
the call, it could be either, or neither. The calling code needs
to guarantee that the array passed is consistent with Int one way
or another. I suspect &third_one actually has two entry points, one
of which checks parameter types, and one of which doesn't. The first
could be thought of as a wrapper around the second. Then the calling
code can decide to check types itself (at either compile time or run
time), or it can decide to rely on the wrapper to check the types.
Once we get to the inner &third_one, the typing of the parameters is
guaranteed contractually to at least be some type that can behave
as an array of Int, even if it isn't one really.

That would, I think, be the default. This allows for weak typing
on the caller end with strong typing on the callee end. But one can
explicitly ask for strong typing on the caller end, or weak typing on
the callee end. The latter approach would allow for the Common Lisp
ideal of treating static type declarations as mere optimization hints,
such that stripping them out doesn't change the meaning of a correctly
running program, merely its speed. Note that we need to keep track of
the dynamic type information in any event for instrospective purposes.
Static typing allows us to make speed assumptions, and as a nice side
effect, catches certain kinds of errors sooner.

This is an oversimplification, of course. We're actually relying
on static typing to specify patterns for multimethod dispatch, and
that certainly affects the meaning of a program. That is why I
favor the weak-caller/strong-callee view of typing. Parameter types
are invariants within the subroutine, but from the external
viewpoint that contract can be fulfilled in any of several ways.

Larry

Piers Cawley

unread,
Apr 11, 2003, 7:41:27 PM4/11/03
to perl6-l...@perl.org
Larry Wall <la...@wall.org> writes:

You are, once again, my hero. I thank you from the heart of my bottom.

--
Piers

Me

unread,
Apr 12, 2003, 5:08:48 AM4/12/03
to Larry Wall, perl6-l...@perl.org
Larry:

> When you declare something as "int" rather than "Int",
> you're really saying something about the variable type
> as well as the value type.

Especially given this dual power of variable types, which
sort of type specification do you expect to see more often
in p6 code, variable or value types?

I'm wondering if p6 culture might perhaps gravitate toward
having newbies learning to favor certain standard (shipped
with Core) variable types instead of the corresponding value
types. Perhaps coders will use variable typing in the first
instance, and only "fall back" to using value types if
there's some specific reason to do so?

--
ralph

Brent Dax

unread,
Apr 13, 2003, 4:42:41 AM4/13/03
to af...@corp.vlex.com, perl6-l...@perl.org
Angel Faus:
# - The leave Function:
#
# Just to be sure about it: Are anonymous subs (like the -> sub in for
# statements) exited with return or with leave?
...
# Mmm..... This is odd. I am quite sure I got something wrong here..

Yup. What you got wrong is the distinction. IIUC, it's not whether the
sub is anonymous or not that determines leave vs. return--it's
keywordness.

Pointy subs and bare blocks don't begin with a keyword, so you must use
leave. Anonymous and named subs both have keywords at the beginning, so
you can use leave or return.

Yes, that does mean that C<sub {...}> and C<< -> {...} >> aren't exactly
equivalent.

--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)

>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism


Angel Faus

unread,
Apr 14, 2003, 3:08:26 PM4/14/03
to perl6-l...@perl.org
Friday 11 April 2003 22:42, Larry Wall wrote:
> On Fri, Apr 11, 2003 at 03:22:36AM +0200, Angel Faus wrote:
> : Do we really need the dual type system?
>
> We do if we're going to do optimizations based on the variable
> types. If you only have value types, then it's difficult to know
> that a given value is always going to be an integer.
>

I don't understand this.

my Int $i;
$i = 1; # ok
$i = "foo"; # run-time (or even compile-time) error

Why is not the value type enough? I am missing something here..

> The two concepts do fuzz into each other, though. When you declare
> something as "int" rather than "Int", you're really saying
> something about the variable type as well as the value type.

This is getting kind of fuzzy for me. Are we going to get a more
detailed explanation about the type system in a future Apocalypse??
Please?

In a previous post you said that binding destroys the variable type.
And S6 says that variable types are intended to replace the "tie"
system in perl5.

So if I write:

sub do_stuff_with_db(%db is rw) {
%db{whatever} = "anything"; ## <<---
}

my %db is DB_File('my.db', O_CREAT|O_RDWR);
# or whatever syntax does it have

do_stuff_with_db(%db);

What's the effect of the assignment in init_db? Will the changes
reflect in the contents of "my.db" file? When?

Do I need to take a reference in order to make the variable type
survive?

sub do_stuff($h is Ref of Hash) {$h.{anything} = 'whatever'}
my %h is PersistentHash;
do_stuff(\\%h); # Ok, changes apply (?)

Another example. Let's say I created a variable type called Logged
that logs any access to the variable (is this a reasonable use of
variable types?)

Will this only log the operations that happen in the same subroutine
body that created the variable? (because any further sub call will
untype it)


And what happens when a subroutine returns a variable. Does it also
loose its variable type?

-angel

Luke Palmer

unread,
Apr 14, 2003, 3:15:18 PM4/14/03
to af...@corp.vlex.com, perl6-l...@perl.org
Angel wrote:

> Larry wrote:
> > The two concepts do fuzz into each other, though. When you declare
> > something as "int" rather than "Int", you're really saying
> > something about the variable type as well as the value type.
>
> This is getting kind of fuzzy for me. Are we going to get a more
> detailed explanation about the type system in a future Apocalypse??
> Please?

A12, no doubt. But I assume that in the interim more and more will be
revealed.

> In a previous post you said that binding destroys the variable type.
> And S6 says that variable types are intended to replace the "tie"
> system in perl5.
>
> So if I write:
>
> sub do_stuff_with_db(%db is rw) {
> %db{whatever} = "anything"; ## <<---
> }
>
> my %db is DB_File('my.db', O_CREAT|O_RDWR);
> # or whatever syntax does it have
>
> do_stuff_with_db(%db);
>
> What's the effect of the assignment in init_db? Will the changes
> reflect in the contents of "my.db" file? When?

Right when you say %db{whatever} = "anything".

> Do I need to take a reference in order to make the variable type
> survive?
>
> sub do_stuff($h is Ref of Hash) {$h.{anything} = 'whatever'}
> my %h is PersistentHash;
> do_stuff(\\%h); # Ok, changes apply (?)

No, that was the most annoying part of P5 ties. You no longer need to
reference to maintain the tie through sub calls.

What he means when he said the variable type is lost in binding is
this:

my $a is Foo;
my $b is Bar;
$b := $a;

$b loses its variable type, not $a. Having variable types in
signatures is futile.

>
> Another example. Let's say I created a variable type called Logged
> that logs any access to the variable (is this a reasonable use of
> variable types?)
>
> Will this only log the operations that happen in the same subroutine
> body that created the variable? (because any further sub call will
> untype it)

Nope, when it's bound, the Logged container will get bound with it.

> And what happens when a subroutine returns a variable. Does it also
> loose its variable type?

I hope not. That might depend on whether you do:

my $a = subcall();

or

my $a := subcall();

Where the latter would keep the variable type, and the former
wouldn't. It'd be tough to return fancy lazy structures and things in
that case, so it might copy the variable either way. Dunno.

Luke

Paul

unread,
Apr 14, 2003, 3:18:58 PM4/14/03
to af...@corp.vlex.com, perl6-l...@perl.org

--- Angel Faus <af...@corp.vlex.com> wrote:
> [big snip]

> And what happens when a subroutine returns a variable. Does it also
> loose its variable type?

Sorry, most of that was lost on me, but let me see if I'm looking where
you're looking, and if so, if I can clear it up a little. If not, maybe
someone will straighten me out, too. :)

sub foo { my Int @i = (0..9); } # types var now has appropriate values

Ok, this should create and populate a lexically scoped variable
containing appropriately typed data, then return it. Since arrays pass
by ref unless otherwise instructed, I'm making the assumption that the
same will be true on return, and that the return keywork won't be
necessary for the last value in the block.

Doesn't that mean that

my Int @x = foo(); # receiving typed array ref with typed values

should work, but that

my Str @y = foo(); # wrong sort of array, wrong sort of values

would not? Now, for how many reasons would it not?

my @z = foo(); # should work ok; default is Scalar

but could I then say

my Str @y = @z; # I'd guess so; it should coerce types, right?

Am I off base?

Michael Lazzaro

unread,
Apr 14, 2003, 5:03:05 PM4/14/03
to perl6-l...@perl.org
My understanding, from the previous on-list discussions:

On Monday, April 14, 2003, at 12:18 PM, Paul wrote:
> Doesn't that mean that
> my Int @x = foo(); # receiving typed array ref with typed values
> should work,

Yes.

> but that
>
> my Str @y = foo(); # wrong sort of array, wrong sort of values
>
> would not? Now, for how many reasons would it not?

Would break, compiletime, because the types don't match: foo returns an
array of Ints, but @y requires an array of Strs. It won't do a type
coercion for you, because, for starters, that would make signature
typing much less useful -- everything would go off runtime coercing,
all willy-nilly, instead of giving you a simple error saying that you
screwed up your types.


> my @z = foo(); # should work ok; default is Scalar

Yes. @z is an array of "untyped" scalars, which can hold any scalar
type, including Ints. So you're copying a bunch of Ints into @z, but
@z itself doesn't change type -- it's still an array of Scalars.


> but could I then say
>
> my Str @y = @z; # I'd guess so; it should coerce types, right?

Oof. This is a unique boundary case -- assignments from untyped to
explicitly typed variables, that is. I believe the general decision
was that it would DWYM in this case, since otherwise you'd have to type
either everything in your program, or nothing, practically speaking.
So I think the above introduces (silent) runtime checking -- to avoid
the runtime checks, make sure you type all your vars.

Consider the (simpler) scalar case:

my Int $i;
my $j;
my Str $s;

$j = $i; # OK: $j can store any scalar, including an Int
$i = $j; # RUNTIME CHECK on $j to see if it's an Int, otherwise die

$j = $s; # OK: $j can store any scalar, including a Str
$s = $i; # COMPILETIME ERROR; type mismatch
$s = $j; # RUNTIME CHECK on $j to see if it's a Str, otherwise die

Given that, I think the array case would produce similar behaviors:

my Int @i;
my @j;
my Str @s;

@j = @i; # OK: @j can store any scalars, including Ints
@i = @j; # RUNTIME CHECK on each element of @j
# to see if it's an Int, otherwise die

@j = @s; # OK: @j can store any scalars, including Strs
@s = @i; # COMPILETIME ERROR; type mismatch
@s = @j; # RUNTIME CHECK on @j
# to see if it's a Str, otherwise die

Note that those last two seem counterintuitive to me, but I think
that's how it has to work in order to make any sense.

So yeah, I'd bet "runtime coercion" on that last one.

MikeL

Michael Lazzaro

unread,
Apr 14, 2003, 8:15:37 PM4/14/03
to perl6-l...@perl.org

On Monday, April 14, 2003, at 02:03 PM, Michael Lazzaro wrote:
> Given that, I think the array case would produce similar behaviors:
>
> my Int @i;
> my @j;
> my Str @s;
>
> @j = @i; # OK: @j can store any scalars, including Ints
> @s = @i; # COMPILETIME ERROR; type mismatch
> @s = @j; # RUNTIME CHECK on each element of @j

> # to see if it's a Str, otherwise die
>
> Note that those last two seem counterintuitive to me, but I think
> that's how it has to work in order to make any sense.

Sorry... the "counterintuitive" part being that the above would seem to
imply that

@s = @i; # COMPILETIME ERROR

@s = @j = @i; # OK: RUNTIME CHECKING

Weird.

> So yeah, I'd bet "runtime coercion" on that last one.

Sorry again. I mean "runtime checking", not "runtime coercion".

I am blindly assuming that assigning a typed value to an untyped
variable doesn't "erase" the type of that value: values stored in the
variable stay typed, if they had a type to begin with. Making an
untyped $var is just an indication that the variable can accept any
(scalar) type; it will store it happily, and spit it back out happily.

But an explicitly typed Int is not a Str, so assigning my Str @s = @j
will give an error if @j contains explicitly typed Ints, even if @j
itself was originally declared as untyped. But it's not an error if
contains mere untyped scalars, which may be used as Ints or Strs at
will.

my Int @i = (1,2,3); # OK: 1,2,3 coerced to Ints

my @j = (1,2,3); # OK: array of untyped scalars
# that just happen to be Ints

my Str @s = @i; # WRONG: compile error
my Str @s = @j; # OK: untyped scalars coerced to Strs

# BUT NOTE -- EVIL!

@j = @i; # OK: storing Ints into untyped @j
@s = @j; # RUNTIME ERROR: now using explicit Ints as Strs

Sigh. Maybe?

One interesting thing about the above is that the literal list

(1,2,3)

would be a list of untyped scalars, not a list of integers, despite
appearances. They'd only turn into ints or Ints if the context
required it.

MikeL

Paul

unread,
Apr 15, 2003, 12:16:08 AM4/15/03
to Michael Lazzaro, perl6-l...@perl.org

--- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
>
> On Monday, April 14, 2003, at 02:03 PM, Michael Lazzaro wrote:
> > Given that, I think the array case would produce similar behaviors:
> >
> > my Int @i;
> > my @j;
> > my Str @s;
> >
> > @j = @i; # OK: @j can store any scalars, including Ints
> > @s = @i; # COMPILETIME ERROR; type mismatch
> > @s = @j; # RUNTIME CHECK on each element of @j
> > # to see if it's a Str, otherwise die
> >
> > Note that those last two seem counterintuitive to me, but I think
> > that's how it has to work in order to make any sense.
>
> Sorry... the "counterintuitive" part being that the above would seem
> to imply that
>
> @s = @i; # COMPILETIME ERROR
> @s = @j = @i; # OK: RUNTIME CHECKING
>
> Weird.

I dunno. It doesn't sound so wierd to me, because in my mind I still
associate the basic Scalar type with an intrinsically polymorphic
behavior. Assigning @i to @s is a no-no because Ints aren't Strings,
but assinging @i to @j is ok because Ints *are* Scalars...then
assigning @j to @s is ok because Strings are Scalars, too.

I do not assume that the Scalars in @j retain their excusivity to
Int-ness, though, and that may be where I'm wrong....but a Scalar can
be an Int *or* a String, so I'm thinking the Ints in @i would be
assigned to the Int-ness of @j, and then the Strings in @s would be
assigned from the String-ness of @j, with the conversion happening
implicitly inside the Scalar type. Think of it kind of like untainting
with a pattern match. :)



> > So yeah, I'd bet "runtime coercion" on that last one.
>
> Sorry again. I mean "runtime checking", not "runtime coercion".
>
> I am blindly assuming that assigning a typed value to an untyped
> variable doesn't "erase" the type of that value: values stored in the

> variable stay typed, if they had a type to begin with. Making an
> untyped $var is just an indication that the variable can accept any
> (scalar) type; it will store it happily, and spit it back out
> happily.

But wouldn't it retain it's own Scalar-ness, including the Int/String
transparency?

> But an explicitly typed Int is not a Str, so assigning my Str @s = @j
> will give an error if @j contains explicitly typed Ints, even if @j
> itself was originally declared as untyped. But it's not an error if
> contains mere untyped scalars, which may be used as Ints or Strs at
> will.

I disagree, but I'd *really* like to hear from the design team on this
one!



> my Int @i = (1,2,3); # OK: 1,2,3 coerced to Ints
>
> my @j = (1,2,3); # OK: array of untyped scalars
> # that just happen to be Ints
>
> my Str @s = @i; # WRONG: compile error
> my Str @s = @j; # OK: untyped scalars coerced to Strs
>
> # BUT NOTE -- EVIL!
>
> @j = @i; # OK: storing Ints into untyped @j
> @s = @j; # RUNTIME ERROR: now using explicit Ints as Strs
>
> Sigh. Maybe?

I wouldn't think so.



> One interesting thing about the above is that the literal list
>
> (1,2,3)
>
> would be a list of untyped scalars, not a list of integers, despite
> appearances. They'd only turn into ints or Ints if the context
> required it.
> MikeL

Agreed. But I'd think the same was true of anything filtered through a
Scalar type. The typing system should accept anything appropriate, and
not make itself so intrusive that it taints the whole program, or no
one will be able to use modules and classes that use typing.

This really does smack of the coercion debates of a week or three ago,
though, doesn't it? :)

__________________________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com

Michael Lazzaro

unread,
Apr 15, 2003, 1:29:23 PM4/15/03
to Hod...@writeme.com, perl6-l...@perl.org

On Monday, April 14, 2003, at 09:16 PM, Paul wrote:
> --- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
>> I am blindly assuming that assigning a typed value to an untyped
>> variable doesn't "erase" the type of that value: values stored in the
>
>> variable stay typed, if they had a type to begin with. Making an
>> untyped $var is just an indication that the variable can accept any
>> (scalar) type; it will store it happily, and spit it back out
>> happily.
>
> But wouldn't it retain it's own Scalar-ness, including the Int/String
> transparency?

Yes, but my impression was that if you explicitly had typed something
to be an Int, you would never get automatic coercion to a Str or other
type (well, aside from stringification, which all types can participate
in.) So if:

my Int $i;
my Str $s;
my $k;

$s = $i; # COMPILE ERR
$k = $i; # OK; stores an Int, not a Scalar
$s = $k; # RUNTIME ERROR; can't put Int in Str-typed var

My rationale is that it would be (silently) too expensive to allow,
since it would render explicit typing of ints and strs pointless -- if
it's always going to autoconvert between the two, even if you have them
explicitly typed, what's the point of giving them explicit types?
Would you gain anything?

My more abstracted logic, identical to the above, is:

my Foo $f = Foo.new; # $f contains obj of type Foo
my Baz $b = Baz.new; # $b contains obj of type Baz
my $k; # untyped var

$b = $f; # COMPILE ERR
$k = $b; # $k now contains an obj of type Baz
$f = $k; # RUNTIME ERROR; can't put Baz in Foo-typed var

$k.foo; # note; calls foo method of Baz object

In this more abstract case, it's more obviously an error to say $f = $k
= $b.

So $k is still an "untyped" var, but it doesn't _strip_ the type of
things that are put inside it -- it can just hold "anything", even
typed values. (The apparent alternative would be that, whenever you
put something inside an untyped scalar var, it would be coerced into
being of type "Scalar"... but that doesn't make much sense, because
then what would C<ref $k> be? And what would happen if you said C<$b =
$k = $b>, would it work?

>> But an explicitly typed Int is not a Str, so assigning my Str @s = @j
>> will give an error if @j contains explicitly typed Ints, even if @j
>> itself was originally declared as untyped. But it's not an error if
>> contains mere untyped scalars, which may be used as Ints or Strs at
>> will.
>
> I disagree, but I'd *really* like to hear from the design team on this
> one!

Yes, please! Heeeeellllllp!


>> my Int @i = (1,2,3); # OK: 1,2,3 coerced to Ints
>>
>> my @j = (1,2,3); # OK: array of untyped scalars
>> # that just happen to be Ints
>>
>> my Str @s = @i; # WRONG: compile error
>> my Str @s = @j; # OK: untyped scalars coerced to Strs
>>
>> # BUT NOTE -- EVIL!
>>
>> @j = @i; # OK: storing Ints into untyped @j
>> @s = @j; # RUNTIME ERROR: now using explicit Ints as Strs
>>
>> Sigh. Maybe?
>
> I wouldn't think so.

<snip>


> This really does smack of the coercion debates of a week or three ago,
> though, doesn't it? :)

Indeed. Around March 14ish, I think. I read through that debate again
(whether types coerce in sub parameter lists, and couldn't find
anything applicable to this case. It was left with the gist of "you
can use an untyped scalar as an Int or Str", but was not concrete about
other cases, like this one.

I'm still maintaining, until contradicted :-), that you can
automatically "typecast" or "coerce" between typed and untyped vars,
but you can't automatically typecast from one type to another, e.g. you
can't say C<my Baz $b = Foo.new>, or therefore even

my Int $i = Str.new('1');

Without running afoul of the compiler. Mind you, I could be completely
wrong about all of this, and Int and Str could have special-case magic
that allowed them to be used interchangeably. Again, I would find that
surprising, since it would seem(?) to render the explicit typing
useless.

MikeL

Paul

unread,
Apr 15, 2003, 3:39:50 PM4/15/03
to Michael Lazzaro, perl6-l...@perl.org
--- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
> On Monday, April 14, 2003, at 09:16 PM, Paul wrote:
> > --- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
> >> I am blindly assuming that assigning a typed value to an
> >> untyped variable doesn't "erase" the type of that value:
> >> values stored in the variable stay typed, if they had a
> >> type to begin with. Making an untyped $var is just an
> >> indication that the variable can accept any (scalar) type;
> >> it will store it happily, and spit it back out happily.
> >
> > But wouldn't it retain it's own Scalar-ness, including the
> > Int/String transparency?
>
> Yes, but my impression was that if you explicitly had typed
> something to be an Int, you would never get automatic coercion
> to a Str or other type (well, aside from stringification, which
> all types can participate in.)

And there's no corresponding Int-ification, so I can't really say that
supports my argument. :) Still, I read the type specification
differently.

my Int $i;

Means $i can only contain a valid Integer value, right?
That doesn't *necessarily* mean that the valid integer value stored in
it could not also qualify as a valid String value to be stored in
another variable, like this:

my Int $i = 1; # what is 1?
my Str $s = 1; # what is 1?

So:

my Int $i;
my Scalar $s;
my $u = 1; # untyped

should allow

$i = $u; # obvious
$s = $u; # acceptable stringification, yes?

> So if:
>
> my Int $i;
> my Str $s;
> my $k;
>
> $s = $i; # COMPILE ERR
> $k = $i; # OK; stores an Int, not a Scalar
> $s = $k; # RUNTIME ERROR; can't put Int in Str-typed var
>
> My rationale is that it would be (silently) too expensive to allow,
> since it would render explicit typing of ints and strs pointless --
> if it's always going to autoconvert between the two, even if you have
> them explicitly typed, what's the point of giving them explicit
types?
> Would you gain anything?

In general, I'd say that a common "untyped" scalar has an Integer and a
String representation, possibly as internal members of the simpler and
more explicit types, and that they're both likely to be cached once
used. Declaring

my Int $i;

says that this variable need *never* bother with any internal
representation other than an Int, and perhaps allowing it to be
internally represented as the leaner, faster animal than the more
generic and inclusive Scalar, so that it simply fails (appropriately)
if an invalid operation (such as saving a String to it) is attempted.

That seems to me to be a much cleaner representation than one in which
the object has to do all the run-time type checking. "You've promised
it will only be used for Ints, so if you crash your program with an
invalid assignment that's your problem....."

Now, let me compliment you on this piece of representative logic. You
haven't changed my mind yet, but only because I don't know the
implementation. This (below) was great thinking, and I had to give it
suitable cogitation in return. :)

> My more abstracted logic, identical to the above, is:
>
> my Foo $f = Foo.new; # $f contains obj of type Foo
> my Baz $b = Baz.new; # $b contains obj of type Baz
> my $k; # untyped var
>
> $b = $f; # COMPILE ERR
> $k = $b; # $k now contains an obj of type Baz
> $f = $k; # RUNTIME ERROR; can't put Baz in Foo-typed var
>
> $k.foo; # note; calls foo method of Baz object

In this case, you're storing values that are *inherently* typed.
A Foo object is always a Foo object, unless it happens to be a
subclass, which is still basically a *modified* Foo object. Likewise a
Baz is a Baz (and I assume they are *not* related by inheritance).

Should the compiler let you assign a Foo to a Baz? Probably not, but
*_only_if_it_can_tell_*. It *should* be able to tell, in which case it
should be able to determine the inheritance issue as well, and stop you
at compile time. But if it can't tell, then I say it should allow the
assignment, and let normal operation substitute for extensive run-time
checking unless someone implements a pragma that asserts types. It will
know the first time it's called as $b.bloop that $b is a Baz and Baz's
can't bloop, so it's an exception and it'll crash.

It should *not* try to coerce the type, any more than $s+=1 should.
That would simply be an error, because $s is a Str and it doesn't know
how to add 1. $s++ might work if that's still overloaded to
auto-increment strings, which could cause some confusion, because
though that particular example might not bite you badly, something else
might do something wholly unexpected....but that's a logic flaw in the
program. Better to avoid such things if we can, but I'm apparently in
C-style thinking mode right now, so I'll just toss it out and let
someone shoot me down, lol....

> In this more abstract case, it's more obviously an error to say
> $f = $k = $b.

Agreed. For this example it *would* be an error, but that's because
neither the untyped $k nor the inherently Baz *value* know how to
represent themselves as Foo's. If Baz were a subclass of Foo, it would
be a harder question. If Baz's had a toFoo method, I'd say it was OK.

> So $k is still an "untyped" var, but it doesn't _strip_ the type of
> things that are put inside it -- it can just hold "anything", even
> typed values. (The apparent alternative would be that, whenever you
> put something inside an untyped scalar var, it would be coerced into
> being of type "Scalar"... but that doesn't make much sense, because
> then what would C<ref $k> be?

I'd say

$u = $i; # $u is untyped, $i is Int
ref $u; # I'd say Int
$s = $i; # COMPILE ERROR; Int's don't .toString implicitly
$s = $i.toString; # OK; explicit stringification
$s = $u; # OK; Scalars *should* .toString implicitly
ref $s; # Str, obviously
ref $u; # ??? I'd say Int still

That is, it would not alter the reference type of the *value*, but if
used in a context that the variable type supports it should return the
appropriate type. For a Foo, stringification is supported; for Scalar
as well, so that

$u = $f; # $u is untyped
ref $u; # Foo
$s = $f; # ok, $s now the stringification of $f
$b = $u; # RUNTIME ERROR: no "Bazification" available

That *might* violate the principle of least surprise if someone called
$s.fooMethod(), but hey, they *explicitly* asked for $s to be a Str,
and Str probably doesn't have .fooMethod, so that's one of those things
we can't prevent.

> And what would happen if you said C<$b = $k = $b>, would it work?

The value in $k is a Baz, so no Bazification is *required*. The value
fits the context, so I'd say Yes, it'd work.



> >> But an explicitly typed Int is not a Str, so assigning
> >> my Str @s = @j
> >> will give an error if @j contains explicitly typed Ints,
> >> even if @j itself was originally declared as untyped.
> >> But it's not an error if contains mere untyped scalars,
> >> which may be used as Ints or Strs at will.

I disagree. I'm probably *wrong*, lol....
But I'd say if it were explicitly declared as

my Int @j;

then it would definitely be a compile-time error.
If it were declared as

my @j;

then I'd say it should implicitly .toString each element as required to
fit the context even if the *values* were Int.

It's more DWIMmy, and still makes the type system powerful and useful.

To plot out the rule:
if a VARIABLE is untyped, it can accept any VALUE of an
appropriate type.
if a VARIABLE is declared to hold a specific type of VALUE,
then that VARIABLE can hold no other type.
if a VALUE if explicitly cast to a certain type, then it can
only be stored in a VARIABLE that can accept that type.
if a VALUE of an explicit type is accessed in a context that
can store that type, no coercion should be done.
if a CONTEXT requires a specific type, and a VALUE imlements
a conversion to that type, *implicit* conversion should be
governed by the type of the VARIABLE containing the VALUE;
by default, any EXPLICITLY TYPED variable should *NOT* do
any implicit conversions.
if a VARIABLE is UNTYPED, it should implicitly use any appropriate
method to coerce the value returned to the type appropriate
for the context, IIF such a method is inherently provided.

Thus,
untyped-to-Int should coerce to Int; untyped scalars can be Ints
untyped-to-Str should coerce to Int; untyped scalars can be Strs
Int-to-untyped should NOT coerce; untyped scalars can be Ints
Str-to-untyped should NOT coerce; untyped scalars can be Strs
untyped-to-Foo should NOT coerce; untyped doesn't know how
Foo-to-untyped should NOT coerce; untyped scalars can be Foos

In most cases, the advantages are preserved, and any run-time hit is
minimal.

As a possible additive, just to make sure there's a headache for the
implementors to throw out :)

a TYPE DEFINITION may state EXPLICITLY that it will allow
implicit conversions, but should allow individual instances
to override this back to the default behavior above.

Obviously, that might take some additional syntax, and is probably
better implemented as a pragma or some such.

> > I disagree, but I'd *really* like to hear from the design team
> > on this one!
>
> Yes, please! Heeeeellllllp!

lol -- *please*? <blinkblinkblink>

> >> my Int @i = (1,2,3); # OK: 1,2,3 coerced to Ints
> >> my @j = (1,2,3); # OK: array of untyped scalars
> >> # that just happen to be Ints
> >> my Str @s = @i; # WRONG: compile error
> >> my Str @s = @j; # OK: untyped scalars coerced to Strs

These work by that plan....

> >> # BUT NOTE -- EVIL!
> >> @j = @i; # OK: storing Ints into untyped @j
> >> @s = @j; # RUNTIME ERROR: now using explicit Ints as Strs
> >> Sigh. Maybe?
> > I wouldn't think so.

Same argument as above.

> <snip>
> > This really does smack of the coercion debates of a week or three
> > ago, though, doesn't it? :)
>
> Indeed. Around March 14ish, I think. I read through that debate
> again (whether types coerce in sub parameter lists, and couldn't find

> anything applicable to this case. It was left with the gist of "you
> can use an untyped scalar as an Int or Str", but was not concrete
> about other cases, like this one.

I felt rather unsatisfied about that discussion. Like eating egg-drop
soup for lunch -- really good, but a half-hour later the soup is gone
and you have the munchies again. :)

> I'm still maintaining, until contradicted :-), that you can
> automatically "typecast" or "coerce" between typed and untyped vars,
> but you can't automatically typecast from one type to another, e.g.
> you can't say C<my Baz $b = Foo.new>, or therefore even
>
> my Int $i = Str.new('1');
>
> Without running afoul of the compiler.

Agreed, though you should be able to say

my Str $s = Int.new('1').toString;

> Mind you, I could be completely wrong about all of this,
> and Int and Str could have special-case magic that allowed
> them to be used interchangeably. Again, I would find that
> surprising, since it would seem(?) to render the explicit typing
> useless.

Pretty much, but I think we could work the rules I posted here into
something generically useful. Maybe?

John Williams

unread,
Apr 16, 2003, 3:29:52 PM4/16/03
to Michael Lazzaro, perl6-l...@perl.org
I'm mainly throwing in another point of view, to see if it helps us
triangulate.

On Tue, 15 Apr 2003, Michael Lazzaro wrote:
> Yes, but my impression was that if you explicitly had typed something
> to be an Int, you would never get automatic coercion to a Str or other
> type (well, aside from stringification, which all types can participate
> in.) So if:
>
> my Int $i;
> my Str $s;
> my $k;
>
> $s = $i; # COMPILE ERR
> $k = $i; # OK; stores an Int, not a Scalar
> $s = $k; # RUNTIME ERROR; can't put Int in Str-typed var
>
> My rationale is that it would be (silently) too expensive to allow,
> since it would render explicit typing of ints and strs pointless -- if
> it's always going to autoconvert between the two, even if you have them
> explicitly typed, what's the point of giving them explicit types?
> Would you gain anything?

We need to play Sesame Street with the design team. "Some of these
things might not be like the others; some of these things are kinda the
same..."

my Int $i;
my Str $s;

$s = "$i"; # string context via circumfix:""
$s = Str($i); # string context function
$s = $i; # = imposes the left context on the right

DWOOMers suggest that the 3rd case should be a compile time error. That's
OK with me, but one of those incredibly lucid justifications from the
design team would probably make us all feel better about it.

> My more abstracted logic, identical to the above, is:
>
> my Foo $f = Foo.new; # $f contains obj of type Foo
> my Baz $b = Baz.new; # $b contains obj of type Baz
> my $k; # untyped var
>
> $b = $f; # COMPILE ERR

Is it? How strict is the compiler going to be?

class FuBaz is Foo is Baz;
my Foo $f = FuBaz.new; # OK: a FuBaz isa Foo.
my Baz $b;

$b = $f; # OK at runtime: a FuBaz isa Baz.

Should it be a compile time error if it might work at runtime?

I'm not asserting a YES or NO answer to that question. I'm mainly
suggesting that you may have to take the bitter (typecasting) with the
sweet (typed variables), because the only alternative is to allow
everything at compile time and do runtime checking only.

> I'm still maintaining, until contradicted :-), that you can
> automatically "typecast" or "coerce" between typed and untyped vars,

That's the same as saying that the Scalar type is magical, in that it will
try to coerce whenever possible, and the compiler will never die when a
Scalar is used in place of another type. Assigning anything TO a Scalar
could be done if Scalar were the base Object class. I'm not saying that
is the case; only that it doesn't require magic. Assigning anything FROM
a Scalar requires some magic, which may only be that the compiler allows
it.

It's OK with me if Scalar is magical, but people who like types more than
I do might want a barrier between typed and untyped (Scalar) values, so a
confirmation or contradiction would be nice.


Almost all the typecasting I do in other languages is not coersion
(converting the value), but merely reassuring the compiler that I know
what I'm doing. e.g. If I put my Corvette in the parking lot, I have to
typecast it as a Corvette or Automobile when I come back, because some
Vehicles don't even have doors. If someone moved my Corvette, and put a
Motorcyle in its place, I'll still get a runtime error when I try to open
the door, in spite of the typecast.

The big question in my mind is HOW MUCH typecasting will be required.
Will Scalar be magical, in that it won't incur compile time checking of
type, while all other types will? For example, neither Vehicle nor Scalar
has a method OpenDoor, but will they be treated differently at compile
time because Scalar is considered "untyped"?

my @ParkingLot is Array of Scalar;
@ParkingLot[42].OpenDoor; # OK at compile time?

my @ParkingLot is Array of Vehicle;
@ParkingLot[42].OpenDoor; # ERROR at compile time?

Can other objects inherit this "untyped" behavior from Scalar?

class Vehicle is Scalar;
my @ParkingLot is Array of Vehicle;
@ParkingLot[42].OpenDoor; # OK? inherited untyped-ness?
@ParkingLot[30] = Toy.new; # ERROR: not a Vehicle.

~ John Williams


Austin Hastings

unread,
Apr 16, 2003, 4:23:27 PM4/16/03
to John Williams, Michael Lazzaro, perl6-l...@perl.org

Here's a suggestion:
=========================
All typecrossing is a potential error.

"No type" is the same as "Scalar": Could be anything, including an
(autoderefed) Array or Hash ref.

Any widening type conversion (into a superclass) is okay. (Scalar =
Int, or Scalar = Str, or Vehicle = Car, or ...)

Any non-widening type conversion is an error at compile time. (You're
contradicting your own declarations. If you want to say Car = Vehicle,
then write and invoke C<multi Car(Vehicle)>.)

Any non-widening type conversion at run-time is checked: the
"underlying" type of the object is looked up, and if a C<toType> method
is present, it is called, otherwise a runtime error occurs.
==========================

I think this gives us a decent set of "normal" rules, with a
low-performance "search for a way to DWYM" fallback. If it can succeed,
it will, and if it can't, it will at least print a message telling you
how you could MAKE it succeed.

>
> > My more abstracted logic, identical to the above, is:
> >
> > my Foo $f = Foo.new; # $f contains obj of type Foo
> > my Baz $b = Baz.new; # $b contains obj of type Baz
> > my $k; # untyped var
> >
> > $b = $f; # COMPILE ERR
>
> Is it? How strict is the compiler going to be?

Absolutely. Baz = Foo will be an error, unless a Foo is a Baz.

> class FuBaz is Foo is Baz;
> my Foo $f = FuBaz.new; # OK: a FuBaz isa Foo.
> my Baz $b;
>
> $b = $f; # OK at runtime: a FuBaz isa Baz.
>
> Should it be a compile time error if it might work at runtime?

Now you've changed the game by introducing multiple inheritance. In
this case, IMO, the error stands. You declared $f to be a Foo, not a
FuBaz. If $f eventually contains "just-a-Foo", the assignment will
surely be an error. Fix your code.

> I'm not asserting a YES or NO answer to that question. I'm mainly
> suggesting that you may have to take the bitter (typecasting) with
> the sweet (typed variables), because the only alternative is to allow
> everything at compile time and do runtime checking only.

No, in this case the alternative is to put on your bOOts and do some
enforcement. The type system is P6 is going to be capable of strong
typing. It's just going to have a relaxed attitude about it, so that
not EVERYTHING has to be strong typed.

But it's like joining the Army: once you agree, you don't get to act
surprised when you get yelled at.

> > I'm still maintaining, until contradicted :-), that you can
> > automatically "typecast" or "coerce" between typed and untyped
> vars,
>
> That's the same as saying that the Scalar type is magical, in that it
> will try to coerce whenever possible, and the compiler will never die
> when a Scalar is used in place of another type. Assigning anything
> TO a Scalar could be done if Scalar were the base Object class. I'm
> not saying that is the case; only that it doesn't require magic.
> Assigning anything FROM a Scalar requires some magic, which may
> only be that the compiler allows it.

I >hope< that Scalar is the base Object class.

>
> It's OK with me if Scalar is magical, but people who like types more
> than I do might want a barrier between typed and untyped (Scalar)
> values, so a confirmation or contradiction would be nice.
>

I think Larry has already commented once on the desirability of
allowing "DWIM" between weak and strong code -- 1-liners calling
modules, for instance.

> Almost all the typecasting I do in other languages is not coersion
> (converting the value), but merely reassuring the compiler that I
> know what I'm doing. e.g. If I put my Corvette in the parking lot,
> I have to typecast it as a Corvette or Automobile when I come back,
> because some Vehicles don't even have doors. If someone moved my
Corvette, and
> put a
> Motorcyle in its place, I'll still get a runtime error when I try to
> open
> the door, in spite of the typecast.
>
> The big question in my mind is HOW MUCH typecasting will be required.
> Will Scalar be magical, in that it won't incur compile time checking
> of type, while all other types will? For example, neither Vehicle
> nor Scalar has a method OpenDoor, but will they be treated
> differently at compile time because Scalar is considered "untyped"?
>
> my @ParkingLot is Array of Scalar;
> @ParkingLot[42].OpenDoor; # OK at compile time?

This is such a good example.

My own argument says that this should be an error -- you declared it as
Scalar, which is the same thing, really, as saying

my @ParkingLot;

after all, and that type doesn't have an OpenDoor.

But this is the way most "relaxed" interfaces are going to work:
someone calls a strict package, gets an object, and then wants to do
something with it.

> my @ParkingLot is Array of Vehicle;
> @ParkingLot[42].OpenDoor; # ERROR at compile time?
>
> Can other objects inherit this "untyped" behavior from Scalar?
>
> class Vehicle is Scalar;
> my @ParkingLot is Array of Vehicle;
> @ParkingLot[42].OpenDoor; # OK? inherited untyped-ness?
> @ParkingLot[30] = Toy.new; # ERROR: not a Vehicle.

No. Regardless of the underlying type, you've created a type with your
declaration. While C<my Vehicle $v;> may be a scalar in behavior, it's
a Vehicle in type terms.

Another Suggestion:
======================
Perhaps we need an C<is untyped> trait, which would be the default for
unmarked declarations:

my $x = 0; # untyped
my Int $x = 0; # Int
my Scalar $x = 0; # Scalar: Can store anything, but has few methods

my @a; # untyped: no type checking is done
my Int @a; # Int
my Scalar @a; # Scalar, as above.
my Scalar @a is untyped; # untyped, again.

I see an analog here with the variable/value type discussion. In this
case, we want to explicitly disable compile-time typechecking. (Ergo, a
variable trait.)

Another Suggestion:
=====================

By extension, we can implement private inheritance this way:

my $a is Foo is Bar is Baz is typed(Foo, Baz);

This C<typed(...)> declaration "rewrites" the public interface for $a
-- no Bar methods may be called on it.


Comment?

=Austin

Michael Lazzaro

unread,
Apr 16, 2003, 4:40:06 PM4/16/03
to John Williams, perl6-l...@perl.org

On Wednesday, April 16, 2003, at 12:29 PM, John Williams wrote:
>> I'm still maintaining, until contradicted :-), that you can
>> automatically "typecast" or "coerce" between typed and untyped vars,
>
> That's the same as saying that the Scalar type is magical, in that it
> will
> try to coerce whenever possible, and the compiler will never die when a
> Scalar is used in place of another type. Assigning anything TO a
> Scalar
> could be done if Scalar were the base Object class. I'm not saying
> that
> is the case; only that it doesn't require magic. Assigning anything
> FROM
> a Scalar requires some magic, which may only be that the compiler
> allows
> it.

I sortof consider "Scalar" and "untyped" to be two separate things --
in that I'm not sure that these two lines are actually identical:

my Scalar $dog; # NOT TO BE CONFUSED WITH C<$dog is Scalar>!
my $dog;

The first is explicitly typed, the second is not... I'm thinking the
second ("untyped") needs to be somewhat magical, if it's to work
correctly, but that the first needs to be distinctly non-magical.

Maybe I'm thinking about it sortof as being like this:

class scalar;
class Int is scalar;
class Str is scalar;

class Scalar is Int|Str;

...though that's not quite right, obviously. But do you understand
what I'm aiming at -- the concept that there's a difference between
"scalar", as the root type of all scalar types, and "scalar", meaning
"of unknown type"?

So that this would generate compile-time errors to help you enforce
strict typing:

my Int $i = 1;

my Str $s;
my Scalar $k;

$k = $i; # OK;

$s = $k; # COMPILATION ERR; can't coerce Scalar to Str

But this would generate an error only at runtime, because of the
runtime-checking inserted when using "untyped" vars:

my Int $i = 1;

my Str $s;
my $k; # <== note the difference!

$k = $i; # OK;

$s = $k; # RUNTIME ERR; can't coerce Int to Str

(Or, identically, using Bar and Baz instead of Int and Str)

???

MikeL

Paul

unread,
Apr 16, 2003, 5:09:24 PM4/16/03
to Michael Lazzaro, John Williams, perl6-l...@perl.org

--- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
> On Wednesday, April 16, 2003, at 12:29 PM, John Williams wrote:
> >> I'm still maintaining, until contradicted :-), that you can
> >> automatically "typecast" or "coerce" between typed and untyped
> >> vars,
> >
> > That's the same as saying that the Scalar type is magical, in
> > that it will try to coerce whenever possible, and the compiler
> > will never die when a Scalar is used in place of another type.
> > Assigning anything TO a Scalar could be done if Scalar were the
> > base Object class. I'm not saying that is the case; only that
> > it doesn't require magic. Assigning anything FROM a Scalar
> > requires some magic, which may only be that the compiler allows
> > it.
>
> I sortof consider "Scalar" and "untyped" to be two separate things --
> in that I'm not sure that these two lines are actually identical:
>
> my Scalar $dog; # NOT TO BE CONFUSED WITH C<$dog is Scalar>!
> my $dog;
>
> The first is explicitly typed, the second is not... I'm thinking the
> second ("untyped") needs to be somewhat magical, if it's to work
> correctly, but that the first needs to be distinctly non-magical.

That explains a lot. I still see an untyped as "defaulting" to a basic
Scalar. I thought of Scalar as being something *designed* to be
generic.

> Maybe I'm thinking about it sortof as being like this:
> class scalar;
> class Int is scalar;
> class Str is scalar;
> class Scalar is Int|Str;
> ...though that's not quite right, obviously. But do you understand
> what I'm aiming at -- the concept that there's a difference between
> "scalar", as the root type of all scalar types, and "scalar", meaning
> "of unknown type"?

I see it, but I thought the compiler would say "what is that? I
dunno...let's just call it a Scalar, then."

> So that this would generate compile-time errors to help you enforce
> strict typing:
> my Int $i = 1;
> my Str $s;
> my Scalar $k;
> $k = $i; # OK;
> $s = $k; # COMPILATION ERR; can't coerce Scalar to Str
> But this would generate an error only at runtime, because of the
> runtime-checking inserted when using "untyped" vars:
> my Int $i = 1;
> my Str $s;
> my $k; # <== note the difference!
> $k = $i; # OK;
> $s = $k; # RUNTIME ERR; can't coerce Int to Str

Ok, one is compile-time, one is run-time, but both err.
I posted before that I think neither of *those* should fail, so I won't
rehash all that. It was just my understanding that what you're calling
"untyped" was actually *always* typed.

That's very much like the inheritance anology people keep making. Ints
"are" Scalars, and Scalars "can be" Ints.

Speaking of which....

> (Or, identically, using Bar and Baz instead of Int and Str)
> ???
> MikeL

If Bar and Baz inherit from Foo, can you do this?

my Foo $f;
my Bar $b = new Bar;
my Baz $z = new Baz;
$f = $b; # I'd hope this was ok
$b = $z; # I'd hope this was not.

or (if you really know what you're doing),

my Foo $o = ($x??Bar::Baz).new; # not for the faint of heart :)

I could see times where this might be handy, though I'd as likely just
not type $o in the first place if I knew I was going to be doing that
sort of thing. Speaking of which.... If the compiler knows $o is a Foo,
and that Bar inherits from Foo, then I see two likely options:

1) my Foo $o = new Bar; # blows up because $o isn't a Bar
or
2) my Foo $o = new Bar; # OK because $o *IS* a Foo, and Bar.isa("Foo")

I'd like to see the latter, but have *no* idea what sort of overhead
that would impose.

I'd be even happier if there were a pragma that let you bend the rules:

1) my Foo $o = new Bar; # blows up because $o isn't a Bar
or
2) use Container::Inheritance Bar => Foo;
my Foo $o = new Bar; # OK because $o *IS* a Foo, and Bar.isa("Foo")

Not that I expect to need it often enough to *write* it, lol....

John Williams

unread,
Apr 16, 2003, 6:48:33 PM4/16/03
to Austin Hastings, Michael Lazzaro, perl6-l...@perl.org
On Wed, 16 Apr 2003, Austin Hastings wrote:
> Here's a suggestion:
> =========================
> All typecrossing is a potential error.
>
> "No type" is the same as "Scalar": Could be anything, including an
> (autoderefed) Array or Hash ref.
>
> Any widening type conversion (into a superclass) is okay. (Scalar =
> Int, or Scalar = Str, or Vehicle = Car, or ...)
>
> Any non-widening type conversion is an error at compile time. (You're
> contradicting your own declarations. If you want to say Car = Vehicle,
> then write and invoke C<multi Car(Vehicle)>.)

You're not saying I need to write a multi for every typecast I might do,
are you?

> Any non-widening type conversion at run-time is checked: the

But you just said that was a compile time error. I'll assume it was
typecast somehow.

> "underlying" type of the object is looked up, and if a C<toType> method
> is present, it is called, otherwise a runtime error occurs.

We need to distinguish between "conversion" and "typecasting". Often we
are not converting anything, but merely remembering what the type
originally was.

my Foo $x = (typecast) my Object $z = Foo.new;

Come to think of it, I'm not even sure what the syntax for typecasting
would be. Str() imposes string context, and presumably causes conversion
to string if the object supports it, but the string returned would not be
the original object. So how do I shut up the compiler exceptions without
shutting up runtime exceptions (and without invoking runtime conversion)?

> > class FuBaz is Foo is Baz;
> > my Foo $f = FuBaz.new; # OK: a FuBaz isa Foo.
> > my Baz $b;
> >
> > $b = $f; # OK at runtime: a FuBaz isa Baz.
> >
> > Should it be a compile time error if it might work at runtime?
>
> Now you've changed the game by introducing multiple inheritance. In

Multiple inheritance was always part of perl's game. "Non-widening"
assignment has the same problem in single inheritance.

> this case, IMO, the error stands. You declared $f to be a Foo, not a
> FuBaz. If $f eventually contains "just-a-Foo", the assignment will
> surely be an error. Fix your code.

Yes, the error stands, but the point is that the code is right and the
compiler is wrong. Typecasting (in cases like this where it does not
invoke an automatic type conversion) just tells the compiler to shut up;
it doesn't "fix" anything.

<peeve> And a lot of the time all those type casts are just empty code
which makes generic code look ugly. </peeve>

Sure I can write a generic set class which hold Scalars, so they don't
need to be typecast every time I retrieve one, but can I write a
ParkingLot which holds Vehicle subclasses without needing one of those
empty typecasts every time I retrieve one? Hmm... Maybe I can override
the array FETCH routine to return a Scalar instead of a Vehicle. (or
otherwise mark it's return value as untyped.)


> But it's like joining the Army: once you agree, you don't get to act
> surprised when you get yelled at.

But do we have to explicitly
{
use no strict typechecking;
...
}
in order to take a leave of absence? :)

Or can enlisted vars still talk civilly to civilian vars? :)


> I >hope< that Scalar is the base Object class.

But if it has magical untyped behaviour which is not inherited, well, that
wouldn't be very OO.

> I think Larry has already commented once on the desirability of
> allowing "DWIM" between weak and strong code -- 1-liners calling
> modules, for instance.
>

> > The big question in my mind is HOW MUCH typecasting will be required.
> > Will Scalar be magical, in that it won't incur compile time checking
> > of type, while all other types will? For example, neither Vehicle
> > nor Scalar has a method OpenDoor, but will they be treated
> > differently at compile time because Scalar is considered "untyped"?
> >
> > my @ParkingLot is Array of Scalar;
> > @ParkingLot[42].OpenDoor; # OK at compile time?
>
> This is such a good example.
>
> My own argument says that this should be an error -- you declared it as
> Scalar, which is the same thing, really, as saying
>
> my @ParkingLot;
>
> after all, and that type doesn't have an OpenDoor.
>
> But this is the way most "relaxed" interfaces are going to work:
> someone calls a strict package, gets an object, and then wants to do
> something with it.

There's the rub. We don't have a grip on which code is "weak" or
"relaxed" or "untyped" yet. Or how to make code or variables act that
way.


> Another Suggestion:
> ======================
> Perhaps we need an C<is untyped> trait, which would be the default for
> unmarked declarations:
>
> my $x = 0; # untyped
> my Int $x = 0; # Int
> my Scalar $x = 0; # Scalar: Can store anything, but has few methods
>
> my @a; # untyped: no type checking is done
> my Int @a; # Int
> my Scalar @a; # Scalar, as above.
> my Scalar @a is untyped; # untyped, again.
>
> I see an analog here with the variable/value type discussion. In this
> case, we want to explicitly disable compile-time typechecking. (Ergo, a
> variable trait.)

That would fit in nicely with MikeL's conception that Scalar and "untyped"
are two different things. I kinda like it. Especially if it just
deferred all type checking on the variable until runtime.

~ John Williams

Dave Whipp

unread,
Apr 16, 2003, 11:18:20 PM4/16/03
to perl6-l...@perl.org
Michael Lazzaro wrote:

> I sortof consider "Scalar" and "untyped" to be two separate things -- in
> that I'm not sure that these two lines are actually identical:

Thank you, I was about to post the same thing.

> ...

Here's my take on it.

There are 3 fundamental types of container: hash, array and scalar.
Programmers are free to define additional container types. All variables
are containers.

An array is a container that holds multiple objects indexed by an
integer; a hash indexes (by default) by a string. A scalar can hold
multiple objects (or primitive values), indexed by type.

When you say

$a = 1;

you are setting up

$a = scalar(Int=>1, Str=>"1");

which is equivalent to saying that the type of any numeric or string
literal is a junction of Int|Str. But its the literal that has this
type, not the variable. Is just so happens that Parrot is set up so that
this junction is easy to implement :-)

An extension of this would be to to have a "Scaler" container that is a
souped up "scalar". This could hold any junction of types and thier
associated objects. Thus I could create

my $pluto is = Scalar(
Str => "Pluto",
Planet => Planet.new("Pluto"),
Animal => Dog.new("Pluto"));

This could be passed to any function that wants either a Str, a Planet
or an Animal.

But what about coercion?

Lets say I setup a type:

typedef Wierd is Scalar( Str | Planet | Animal ) will coerce(
multi (Str) returns Planet { Planet.new($^s) }
| multi (Str) returns Animal { Animal.new($^s) }
| multi (Planet|Animal) returns Str { $^obj.name }
);

The anonymous multimethod defines the valid coercians (yes, there's a
couple missing)


The summary: a Scalar is a container that appears to hold only one
object, but that object might vary depending on context. A "scalar" is a
primitive container, but can be thought of as:

typedef scalar is Scalar(str|int|Object|Code) will coerce(
multi (str) returns int {...}
| multi (int) returns str {...}
| multi (str) returns Str {...}
| multi (int) returns Num {...}
| multi (Object) returns Str { $^o.toString }
| multi (Object) returns Num { $^o.num }
| multi (Object) returns $(want.type) { $^o.dynamic_cast(want.type) }
);


Dave.

Austin Hastings

unread,
Apr 16, 2003, 8:45:55 PM4/16/03
to John Williams, Michael Lazzaro, perl6-l...@perl.org

> -----Original Message-----
> From: John Williams [mailto:will...@tni.com]
> Sent: Wednesday, April 16, 2003 5:49 PM
> To: Austin Hastings
> Cc: Michael Lazzaro; perl6-l...@perl.org
> Subject: Re: HELP! Type Coercions [was Re: Do we really need the dual
> type system?]
>
>
> On Wed, 16 Apr 2003, Austin Hastings wrote:
> > Here's a suggestion:
> > =========================
> > All typecrossing is a potential error.
> >
> > "No type" is the same as "Scalar": Could be anything, including an
> > (autoderefed) Array or Hash ref.
> >
> > Any widening type conversion (into a superclass) is okay. (Scalar =
> > Int, or Scalar = Str, or Vehicle = Car, or ...)
> >
> > Any non-widening type conversion is an error at compile time. (You're
> > contradicting your own declarations. If you want to say Car = Vehicle,
> > then write and invoke C<multi Car(Vehicle)>.)
>
> You're not saying I need to write a multi for every typecast I might do,
> are you?

Potentially, yes. (Look at C++ for the worst-possible-case of this...)

> > Any non-widening type conversion at run-time is checked: the
>
> But you just said that was a compile time error. I'll assume it was
> typecast somehow.

No, just thinking faster than I type. The phrasing should have been "any
conversion which is known to be non-widening at compile time", and then
"any non-widening conversion at run-time". The idea for the second
essentially
being to catch the untyped -> typed conversions.

> > "underlying" type of the object is looked up, and if a C<toType> method
> > is present, it is called, otherwise a runtime error occurs.
>
> We need to distinguish between "conversion" and "typecasting". Often we
> are not converting anything, but merely remembering what the type
> originally was.

So perhaps we shouldn't worry about that case directly, and instead just
require some DWIMery: narrowing conversions are not compile errors, but will
have to be checked at run-time.


>
> my Foo $x = (typecast) my Object $z = Foo.new;
>
> Come to think of it, I'm not even sure what the syntax for typecasting
> would be. Str() imposes string context, and presumably causes conversion
> to string if the object supports it, but the string returned would not be
> the original object. So how do I shut up the compiler exceptions without
> shutting up runtime exceptions (and without invoking runtime conversion)?

Let's propose some new syntax, ideally involving the colon. This way Larry
can be torn between rejecting it out of hand (Rule #1) or handing it over to
Damian for rejection (Damian gets the object stuff). :-}


The simplest way would be to require a restart: build a function called
C<untype>
that returns its arguments with no type. This would force full run-time
checking on the assignment.

sub *untype($x) { my $y = $x; $y; }

Alternatively, we could go with the "typed" idea I mentioned earlier, and
say

my Foo $x = (my Object $z = Foo.new).typed(Foo);

I like this better than the "obvious" .Foo trait, because when dealing with
multiply typed vars, it's easier:

my $x is Slicer is Dicer is Grinder;
my $j = $x;
$x = $j.Slicer.Dicer.Grinder; # Doubtful
$x = $j.typed(Slicer, Dicer, Grinder);

> > > class FuBaz is Foo is Baz;
> > > my Foo $f = FuBaz.new; # OK: a FuBaz isa Foo.
> > > my Baz $b;
> > >
> > > $b = $f; # OK at runtime: a FuBaz isa Baz.
> > >
> > > Should it be a compile time error if it might work at runtime?
> >
> > Now you've changed the game by introducing multiple inheritance. In
>
> Multiple inheritance was always part of perl's game. "Non-widening"
> assignment has the same problem in single inheritance.
>
> > this case, IMO, the error stands. You declared $f to be a Foo, not a
> > FuBaz. If $f eventually contains "just-a-Foo", the assignment will
> > surely be an error. Fix your code.
>
> Yes, the error stands, but the point is that the code is right and the
> compiler is wrong. Typecasting (in cases like this where it does not
> invoke an automatic type conversion) just tells the compiler to shut up;
> it doesn't "fix" anything.
>
> <peeve> And a lot of the time all those type casts are just empty code
> which makes generic code look ugly. </peeve>
>
> Sure I can write a generic set class which hold Scalars, so they don't
> need to be typecast every time I retrieve one, but can I write a
> ParkingLot which holds Vehicle subclasses without needing one of those
> empty typecasts every time I retrieve one? Hmm... Maybe I can override
> the array FETCH routine to return a Scalar instead of a Vehicle. (or
> otherwise mark it's return value as untyped.)

This goes back to the "automatically ignore narrowing conversions, but
verify them at compile time" logic.

> > But it's like joining the Army: once you agree, you don't get to act
> > surprised when you get yelled at.
>
> But do we have to explicitly
> {
> use no strict typechecking;
> ...
> }
> in order to take a leave of absence? :)
>
> Or can enlisted vars still talk civilly to civilian vars? :)
>

Always. It's the reverse case that is causing the problem. All those
harmless
little old ladies wondering why the TSA has to search *them*...

>
> > I >hope< that Scalar is the base Object class.
>
> But if it has magical untyped behaviour which is not inherited, well, that
> wouldn't be very OO.

Yep. Maybe "rvalue" is the base object class? :-)

>
> > I think Larry has already commented once on the desirability of
> > allowing "DWIM" between weak and strong code -- 1-liners calling
> > modules, for instance.
> >
> > > The big question in my mind is HOW MUCH typecasting will be required.
> > > Will Scalar be magical, in that it won't incur compile time checking
> > > of type, while all other types will? For example, neither Vehicle
> > > nor Scalar has a method OpenDoor, but will they be treated
> > > differently at compile time because Scalar is considered "untyped"?
> > >
> > > my @ParkingLot is Array of Scalar;
> > > @ParkingLot[42].OpenDoor; # OK at compile time?
> >
> > This is such a good example.
> >
> > My own argument says that this should be an error -- you declared it as
> > Scalar, which is the same thing, really, as saying
> >
> > my @ParkingLot;
> >
> > after all, and that type doesn't have an OpenDoor.
> >
> > But this is the way most "relaxed" interfaces are going to work:
> > someone calls a strict package, gets an object, and then wants to do
> > something with it.
>
> There's the rub. We don't have a grip on which code is "weak" or
> "relaxed" or "untyped" yet. Or how to make code or variables act that
> way.

I disagree. I think any code which doesn't have type information in it will
have to default to (slow and) untyped or weakly typed. That's the land of
one-offs
and microscripting, for sure.

Your (& MikeL's) examples, mixing untyped with typed code, are where I think
a
signicant fraction of P6 coders are going to want to live. The "objects, but
only where I want them" school.

So it behooves us to get that stuff right, and we're trying to prioritize
what
"right" is, here.

I think that your point before, about most typecasts being ugly noise that
obscures the code without doing anything more than reminding the compiler
of information that the coder already knows, is a good one. It should be
enshrined in the OO6P user requirements: MIXED MODE CODE SHOULD BE EASY TO
READ.


> > Another Suggestion:
> > ======================
> > Perhaps we need an C<is untyped> trait, which would be the default for
> > unmarked declarations:
> >
> > my $x = 0; # untyped
> > my Int $x = 0; # Int
> > my Scalar $x = 0; # Scalar: Can store anything, but has few methods
> >
> > my @a; # untyped: no type checking is done
> > my Int @a; # Int
> > my Scalar @a; # Scalar, as above.
> > my Scalar @a is untyped; # untyped, again.
> >
> > I see an analog here with the variable/value type discussion. In this
> > case, we want to explicitly disable compile-time typechecking. (Ergo, a
> > variable trait.)
>
> That would fit in nicely with MikeL's conception that Scalar and "untyped"
> are two different things. I kinda like it. Especially if it just
> deferred all type checking on the variable until runtime.

Yeah, but deferring all checking until runtime sucks. See Dan's weblog for
more
commentary in that direction.

=Austin

Paul

unread,
Apr 17, 2003, 11:38:14 AM4/17/03
to John Williams, Austin Hastings, Michael Lazzaro, perl6-l...@perl.org
> But do we have to explicitly
> {
> use no strict typechecking;
> ...
> }
> in order to take a leave of absence? :)

I think the use() is wrong there, unless P6 is changing the rule.
Shouldn't that just be
{ no strict typechecking; # ?
# ...
}


> > I >hope< that Scalar is the base Object class.
>
> But if it has magical untyped behaviour which is not inherited, well,
> that wouldn't be very OO.

Not sure what this means -- elaborate?

> > > my @ParkingLot is Array of Scalar;
> > > @ParkingLot[42].OpenDoor; # OK at compile time?
> >
> > This is such a good example.
> >
> > My own argument says that this should be an error -- you
> > declared it as Scalar, which is the same thing, really, as
> > saying
> > my @ParkingLot;
> > after all, and that type doesn't have an OpenDoor.
> >
> > But this is the way most "relaxed" interfaces are going to work:
> > someone calls a strict package, gets an object, and then wants
> > to do something with it.
>
> There's the rub. We don't have a grip on which code is "weak" or
> "relaxed" or "untyped" yet. Or how to make code or variables act
> that way.

And this had *better* work:

use Foo;
my $f = Foo.new;
$f.bar();

Now, $f is just a scalar, right? Completely untyped by any explicit
statement.... but the value in it is a Foo which knows how to bar().

If a Foo *doesn't* know how to bar(), then I'd expect that to be a
runtime error. I'd *love* it if the compiler could catch it! But if Foo
can bar(), are you saying this *shouldn't* work? Lunacy. That would
require *every* object to be typed. Let's not go there, at least not
unless you

use strict types;

> > Another Suggestion:
> > ======================
> > Perhaps we need an C<is untyped> trait, which would be the default
> > for unmarked declarations:
> >
> > my $x = 0; # untyped
> > my Int $x = 0; # Int
> > my Scalar $x = 0; # Scalar: Can store anything, but has few methods
> >
> > my @a; # untyped: no type checking is done
> > my Int @a; # Int
> > my Scalar @a; # Scalar, as above.
> > my Scalar @a is untyped; # untyped, again.
> >
> > I see an analog here with the variable/value type discussion. In
> > this case, we want to explicitly disable compile-time typechecking.
> > (Ergo, a variable trait.)
>
> That would fit in nicely with MikeL's conception that Scalar and
> "untyped" are two different things. I kinda like it. Especially
> if it just deferred all type checking on the variable until runtime.

But I still don't think you can have an untyped variable in a typed
system, unless you define a type named "Untyped", which I still say is
spelled "Scalar".

Luke Palmer

unread,
Apr 17, 2003, 12:18:08 PM4/17/03
to Austin_...@yahoo.com, will...@tni.com, mlaz...@cognitivity.com, perl6-l...@perl.org
> Let's propose some new syntax, ideally involving the colon. This way Larry
> can be torn between rejecting it out of hand (Rule #1) or handing it over to
> Damian for rejection (Damian gets the object stuff). :-}
>
>
> The simplest way would be to require a restart: build a function called
> C<untype>
> that returns its arguments with no type. This would force full run-time
> checking on the assignment.
>
> sub *untype($x) { my $y = $x; $y; }
>
> Alternatively, we could go with the "typed" idea I mentioned earlier, and
> say
>
> my Foo $x = (my Object $z = Foo.new).typed(Foo);
>
> I like this better than the "obvious" .Foo trait, because when dealing with
> multiply typed vars, it's easier:
>
> my $x is Slicer is Dicer is Grinder;
> my $j = $x;
> $x = $j.Slicer.Dicer.Grinder; # Doubtful
> $x = $j.typed(Slicer, Dicer, Grinder);

If there I<is> going to be an explicit typecast method, I was thinking
the C<as> operator.

foo($x as Dicer);

Reads nicely. I don't know what my position is on actual conversions
is just yet, but that would be a nice syntax.


> I disagree. I think any code which doesn't have type information in
> it will have to default to (slow and) untyped or weakly
> typed. That's the land of one-offs and microscripting, for sure.
>
> Your (& MikeL's) examples, mixing untyped with typed code, are where
> I think a signicant fraction of P6 coders are going to want to
> live. The "objects, but only where I want them" school.
>
> So it behooves us to get that stuff right, and we're trying to
> prioritize what "right" is, here.

Agreed.

> I think that your point before, about most typecasts being ugly
> noise that obscures the code without doing anything more than
> reminding the compiler of information that the coder already knows,
> is a good one. It should be enshrined in the OO6P user requirements:
> MIXED MODE CODE SHOULD BE EASY TO READ.

Without the MIXED MODE part. Code should be easy to read whether or
not it's using types, and whether or not everything around it is using
types. We want it to DTRT, but that happens to be a tough call in
this situation.

Luke

Paul

unread,
Apr 17, 2003, 12:25:47 PM4/17/03
to Dave Whipp, perl6-l...@perl.org

--- Dave Whipp <da...@whipp.name> wrote:
> Michael Lazzaro wrote:
> > I sortof consider "Scalar" and "untyped" to be two separate
> > things -- in that I'm not sure that these two lines are
> > actually identical:
>
> Thank you, I was about to post the same thing.
>
> Here's my take on it.
>
> There are 3 fundamental types of container: hash, array and scalar.
> Programmers are free to define additional container types. All
> variables are containers.

Yes, but Hashes and Arrays are just aggregates of (by default) Scalars.
You can declare them as

my Int @array;

but that merely says that the aggregate expects its *elements* to be of
the explicit type, rather than defaulting to standard Scalars.



> An array is a container that holds multiple objects indexed by an
> integer; a hash indexes (by default) by a string. A scalar can hold
> multiple objects (or primitive values), indexed by type.

This is a neat concept...but isn't that basically a hash?
P5 hashes were indexed explicitly by strings, but in P6 they're more
flexible, aren't they?


> When you say
> $a = 1;
> you are setting up
> $a = scalar(Int=>1, Str=>"1");
> which is equivalent to saying that the type of any numeric or string
> literal is a junction of Int|Str. But its the literal that has this
> type, not the variable. Is just so happens that Parrot is set up so
> that this junction is easy to implement :-)

Idealogically, perhaps -- but you could say the same of P5 scalars,
which aren't typed at all. Your point here, I take it, is that it's the
data that's typed, not the scalar, and that the data might have a
multiplicity of *possible* types, based on context if not explicitly
specified. I say the scalar is implicitly typed, and that it's type
behaves like (if it literally isn't) a superclass for assignment terms.
A numeric value might be a string in the appropriate context, and then
a number in a different context, and then a string again. e.i., Str
then Num then Str. Isn't that what a Scalar does?

So is that functionality to be limited to Int/Num/Str, and we require
yet another implementation for "untyped" vars?

<btw> Is Str going to be the ideal type for binary data? </btw>

> An extension of this would be to to have a "Scaler" container that is
> a souped up "scalar". This could hold any junction of types and thier

> associated objects. Thus I could create
>
> my $pluto is = Scalar(
> Str => "Pluto",
> Planet => Planet.new("Pluto"),
> Animal => Dog.new("Pluto"));
>
> This could be passed to any function that wants either a Str, a
> Planet or an Animal.

This is a neat idea, though I thought that's what objects were for, or
even hashes.

> But what about coercion?
> Lets say I setup a type:
>
> typedef Wierd is Scalar( Str | Planet | Animal ) will coerce(
> multi (Str) returns Planet { Planet.new($^s) }
> | multi (Str) returns Animal { Animal.new($^s) }
> | multi (Planet|Animal) returns Str { $^obj.name }
> );
> The anonymous multimethod defines the valid coercians (yes, there's a

> couple missing)

<aside>
Compile error: you have multiple multi's with (Str). Also, can
you do anonymous multi's, or are you just proposing an idea?
Either way, I think I get your point....
</aside>

I'd say it was better to just make it a class with .toPlanet and
.toAnimal and .toStr methods.

> The summary: a Scalar is a container that appears to hold only one
> object, but that object might vary depending on context. A "scalar"
> is a primitive container, but can be thought of as:
>
> typedef scalar is Scalar(str|int|Object|Code) will coerce(
> multi (str) returns int {...}
> | multi (int) returns str {...}
> | multi (str) returns Str {...}
> | multi (int) returns Num {...}
> | multi (Object) returns Str { $^o.toString }
> | multi (Object) returns Num { $^o.num }
> | multi (Object) returns $(want.type)
> { $^o.dynamic_cast(want.type) }
> );

Ok -- how is this different from just making Scalar do those things,
and calling untyped vars Scalars?

Likewise, at the risk of getting a little off-topic,

%type = { Str => 0, Int => 1, Foo => 2, Bar => 3 };
my @obj;
push @obj, $_.new for keys %type;
print ref( @obj[ %type{$_} ] ) for qw / Foo Bar Str Int /;
my Foo $f = @obj[2];

Assuming stringification doesn't render that entirely uncompilable,
what's to stop this sort of thing from being exemplary (if oversimple)
of actual, useful code?

@obj is completely "untyped", so I assume the type of each array
element is *Scalar*. Wouldn't it work? Shouldn't it? Particularly the
last line.

And if Bar inherits from Foo, you should also be able to say
my Foo $f = @obj[3];

I wouldn't advise making a *habit* of it, but it's valid code, valid
technique, and something we need to decide, yes?

Dan Sugalski

unread,
Apr 17, 2003, 1:04:14 PM4/17/03
to perl6-l...@perl.org
At 8:18 PM -0700 4/16/03, Dave Whipp wrote:
>Michael Lazzaro wrote:
>
>>I sortof consider "Scalar" and "untyped" to be two separate things
>>-- in that I'm not sure that these two lines are actually identical:
>
>Thank you, I was about to post the same thing.
>
>>...
>
>Here's my take on it.
>
>There are 3 fundamental types of container: hash, array and scalar.
>Programmers are free to define additional container types. All
>variables are containers.
>
>An array is a container that holds multiple objects indexed by an
>integer; a hash indexes (by default) by a string. A scalar can hold
>multiple objects (or primitive values), indexed by type.
>
> When you say
>
> $a = 1;
>
>you are setting up
>
> $a = scalar(Int=>1, Str=>"1");

No. No, you're not. You're setting up:

$a = 1;

and that's it. The string version is produced by $a's string
conversion code. It would be perfectly valid for the string value of
$a to be "One". (Or, if you've a locale in force, "Uno" or "Ichi") I
think it's important to realize and remember that you're assigning in
*exactly* the value you're assigning in, and nothing more. And that
the assignee may well preprocess what you're assigning in before
accepting it. Otherwise you build up an expectation of assignment
that's incorrect, and that may lead to subtle errors later.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Dave Whipp

unread,
Apr 17, 2003, 1:14:08 PM4/17/03
to Hod...@writeme.com, Dave Whipp, perl6-l...@perl.org
--- Paul <ydb...@yahoo.com> wrote:
> Ok -- how is this different from just making Scalar do those
> things and calling untyped vars Scalars?

Corercion is imposed: it's a function of the container, not of the
value that's stored in the container..

Conceptual flow:
prog stores Int in container
... time passess ...
a context asks container for a Str
container says "sure, I can give you one of those" and:
calls Int.toString (or whatever) on its contained value
caches the result for future reference
supplies the Str to the context.

At no point is the Int "isa" Scalar: its an object that has a
toString method, stored in a container that has been authorised to
call that method when needed.

Dave.

Paul

unread,
Apr 17, 2003, 1:17:53 PM4/17/03
to Luke Palmer, Austin_...@yahoo.com, will...@tni.com, mlaz...@cognitivity.com, perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> If there I<is> going to be an explicit typecast method, I was
> thinking the C<as> operator.
>
> foo($x as Dicer);
>
> Reads nicely. I don't know what my position is on actual conversions
> is just yet, but that would be a nice syntax.

That's beautiful, and solves a lot of problems.

my Foo $f; # Foo superclass
my Bar $b = Bar.new; # Bar subclasses Foo
my $f = $b; # COMPILE ERROR: type mismatch
my $f = $b as Foo; # OK, typechecks and allows it

my $u; # "untyped" scalar


my Int $i = 1;

my Str $s = "1";
my $i = $s; # ERROR
my $i = $s as Int; # ??? I'd say maybe? I'd rather not....
my $u = $s; # OK? I'd rather see even this explicit
my $u = $s as Scalar;# only allowed if as() type valid for $s?
my $i = $u as Int; # OK, explicitly typecast

It could disallow any typecasting to a more restrictive form unless
explicitly requested with "as", and then could do run-time checking to
verify it. But what about to a less restrictive form? Int to Scalar?
To be honest, though I know a lot of people would rather not have to
type it, I'd personally rather see *any* typecasting require this, even
from Int or Str to Scalar. Again, though, maybe only under

use strict typecasting;

though I'd prefer that to be the default if you just say

use strict;

Even better, coerce anything any way you can in non-strict run mode,
but require *everything* to be explicit if under strict. That leaves
one-off's maximum flexibility and there's real power in that -- to
shoot yourself in the foot, or to accomplish Great Things, but power,
nonetheless. It also slows things down a lot while all the default
typechecking and coercions are going on....

But you could invoke stricture and the compiler could strip out all the
coercion and typechecking code everywhere except those explicitly
declared cases, which would only need to check and convert between
explicitly known types. Don't typecast, and the overhead is completely
gone. Speed and efficiency!

Then there's the case that classes and modules are strict be default,
so they would compile as leaner and cleaner unless explicitly decalred
with "no strict types" or whatever the argument was.

Ooh, this is very sweet.

Am I overreacting here? :)

Michael Lazzaro

unread,
Apr 17, 2003, 1:39:07 PM4/17/03
to Luke Palmer, Austin_...@yahoo.com, will...@tni.com, perl6-l...@perl.org
Changed thread title, 'cause this is _way_ too speculative:

On Thursday, April 17, 2003, at 09:18 AM, Luke Palmer wrote:
> If there I<is> going to be an explicit typecast method, I was thinking
> the C<as> operator.
>
> foo($x as Dicer);
>
> Reads nicely. I don't know what my position is on actual conversions
> is just yet, but that would be a nice syntax.

Agreed, 'as' looks very nice. I'd like it to be a word, not a
parentheses-based thingy that looks like C typecasting. But I'll see
that 'as', and raise you another keyword.

I have, for a long time, been advocating C<from> and C<to>, because
they work nicely in OO-based coding -- you can define them as keywords
that look a lot like multimethods:

foo($x to Dicer);
-or-
foo(Dicer from $x);

or, to flesh it out:

class Foo {
has $.attr1;

from Bar { ... } # how to make a Foo out of a Bar obj
from Baz { ... } # how to make a Foo out of a Baz obj

to Bar { ... } # how to make a Bar out of a Foo obj
to Baz { ... } # how to make a Baz out of a Foo obj

method zap { ... }
}

my Foo $foo = Foo.new;
my Bar $bar;

$bar = $foo to Bar; # creates a new C<Bar> obj
$bar = Bar from $foo; # same thing
$bar from $foo; # same thing, but deeper magic


You could even have parameters:

class Foo { to Bar ($bar : +$opt) {...} }

$foo to Bar( opt => "blarp" );

The reason I like (something like) this so much is because it makes the
coercion methods very distinct, both to the user and to the compiler:
C<from> things are basically variants of the constructor, and C<to>
things are redundant backups to the C<from> constructors... alternate
ways of constructing other classes that you can define in _this_ class,
if you feel that would be cleaner in certain cases.

But the fact that they are explicit "kinds" of methods, with their own
keywords, opens the possibility for doing lots of interesting "chained"
coercions. If the compiler knows you can do:

Class A { ... }
Class B { from A { ... } }
Class C { from B { ... } }

then it can also automagically know that you can say

$c from $a;

... and chain the coercions. Very similar to how multimethods search
for 'best match' variants, in fact.

My hope is that something like this can help save us from C++ hell,
where you need umpteen multimethod variants for every pissant little
object type, even where the conversions should be obvious. The caveat
is that it's hard not to make it _too_ powerful, where it's choosing to
do a chain of ten conversions that you really didn't intend to happen.

MikeL

Michael Lazzaro

unread,
Apr 17, 2003, 1:42:39 PM4/17/03
to Dave Whipp, perl6-l...@perl.org

On Wednesday, April 16, 2003, at 08:18 PM, Dave Whipp wrote:
> Michael Lazzaro wrote:
>
>> I sortof consider "Scalar" and "untyped" to be two separate things --
>> in that I'm not sure that these two lines are actually identical:
>
> Thank you, I was about to post the same thing.
>
>> ...
>
> Here's my take on it.
<snip>

By gum, it looks like we're all on the same page, or getting there. My
only big question is what the names of the two things are -- the "root
of all scalars" word, and the "junction of all builtin scalars" word.
In other words, what's this shorthand for:

my $x;

does it mean

my untyped $x;
my scalar $x;
my Scalar $x;

What's that damn word?

Well, that and hearing from the design team on whether or not this
train left the tracks a while back, and we're all just in free-fall to
the rocks below at this point...


MikeL

Paul

unread,
Apr 17, 2003, 1:38:15 PM4/17/03
to Dave Whipp, perl6-l...@perl.org

--- Dave Whipp <dave_...@yahoo.com> wrote:
> --- Paul <ydb...@yahoo.com> wrote:
> > Ok -- how is this different from just making Scalar do those
> > things and calling untyped vars Scalars?
>
> Corercion is imposed: it's a function of the container, not of the
> value that's stored in the container..
>
> Conceptual flow:
> prog stores Int in container
> ... time passess ...
> a context asks container for a Str
> container says "sure, I can give you one of those" and:
> calls Int.toString (or whatever) on its contained value
> caches the result for future reference
> supplies the Str to the context.
>
> At no point is the Int "isa" Scalar: its an object that has a
> toString method, stored in a container that has been authorised to
> call that method when needed.
>
> Dave.

Ok, you say "it's a function of the container, not of the value"; then
you say "context asks container for a Str" and "container...calls
Int.toString". That makes coercion a function of the container
*dependent* on the type of the value. If it were a Str type asked for
an Int, it would break there.

More importantly, just besause your example doesn't require inheritance
doesn't mean an Int isn't "isa" Scalar.

I'd say that used in a Foo context, a Scalar (which isn't "isa" Foo)
would still have to behave appropriately. If a Foo object were stored
in it, $o.bar() would call that object's bar() method, even though that
isn't a method of Scalar.

So either I missed your point or lost the thread, or the point is moot.


Now, if the *is* no bar() method in Foo, there's obviously a problem,
but that may not be a type issue. Still, Foo objects might inherit
bar() from a superclass. Shouldn't that work?

In that case, if the $o were typed as Foo, you'd still expect it to
work. What if it were typed as that superclass? Then it would work. If
Foo had overridden bar(), the *value*'s bar() should be the one called.
The typing of the variable is just a security and efficiency check.

So exactly what are the benefits of having a typed variable, other than
enforcing better checking on your code? People talk about making the
code faster, and I make assumptions that it means less overhead, but we
keep talking about examples where the overhead keeps creeping back in.
Is the type coercion the only overhead? Because if that's the case
correct typing would *still* make a great speed increase as values are
checked once and verified, instead of having to walk inheritance trees
and perform implicit method calls to supply appropriate data.

Which means that if Bar inherits from Foo, assigning a Bar object to a
Foo typed variable would still cost typechecking overhead as it
traverses the inheritance tree, but the overhead would be proportional
to the proximity of the types, and one step isn't bad. I assume no one
would do that unless they needed it. If it was a mistake that slowed
the program, but worked anyway, they might not care. If it was
intended, it might be worth the overhead to simplify an algorithm to a
more maintainable state. Again, *no* types might be simpler, but *some*
typing still enforces some code integrity and provides some speed
increase.

Am I missing something again?

Dan Sugalski

unread,
Apr 17, 2003, 1:48:34 PM4/17/03
to Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 10:42 AM -0700 4/17/03, Michael Lazzaro wrote:
>On Wednesday, April 16, 2003, at 08:18 PM, Dave Whipp wrote:
>>Michael Lazzaro wrote:
>>
>>>I sortof consider "Scalar" and "untyped" to be two separate things
>>>-- in that I'm not sure that these two lines are actually
>>>identical:
>>
>>Thank you, I was about to post the same thing.
>>
>>>...
>>
>>Here's my take on it.
><snip>
>
>By gum, it looks like we're all on the same page, or getting there.
>My only big question is what the names of the two things are -- the
>"root of all scalars" word, and the "junction of all builtin
>scalars" word. In other words, what's this shorthand for:
>
> my $x;
>
>does it mean
>
> my untyped $x;
> my scalar $x;
> my Scalar $x;
>
>What's that damn word?

I think the word you're looking for is "thingie".

Dave Whipp

unread,
Apr 17, 2003, 1:49:31 PM4/17/03
to Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Michael Lazzaro <mlaz...@cognitivity.com> wrote:
> By gum, it looks like we're all on the same page, or getting there.
> My only big question is what the names of the two things are -- the
> "root of all scalars" word, and the "junction of all builtin
> scalars" word. In other words, what's this shorthand for:
>
> my $x;
>
> does it mean
>
> my untyped $x;
> my scalar $x;
> my Scalar $x;
>
> What's that damn word?

Well Huffman says it can be as long a phrase as we like -- because
we'll never type it. I'm thinking something like:

{my $x}
eq:perl6
{my any(*@*primitive_types, Object) $a is scalar}

Its not un-typed: its any-typed.

Dave.

Dave Whipp

unread,
Apr 17, 2003, 2:07:18 PM4/17/03
to Hod...@writeme.com, Dave Whipp, perl6-l...@perl.org

--- Paul <ydb...@yahoo.com> wrote:
> More importantly, just besause your example doesn't require
> inheritance doesn't mean an Int isn't "isa" Scalar.

Ignoring the implementation for a moment, if Int were implemented in
Perl6, then it would, itself, be a container:

class Int
{
has char @digits is private;
...
}

However, an Int is not a Scalar, because if it were then you would be
able to store Ints, Strs and Foos in it (otherwise you'd be violating
Liskov). An Int (in the above definition) can only contain an array
of chars. It may have some rules that allow it to give you objects of
other types (if you ask it nicely).

So an Int is not a Scalar: its a container, that can be used as a
value, that can be stored in a Scalar: and a Scalar has some rules
that allow it to manipulate Ints behind the scenes, to give you other
types (if you ask it nicely).


Dave.

John Williams

unread,
Apr 17, 2003, 2:57:11 PM4/17/03
to Austin_...@yahoo.com, Michael Lazzaro, perl6-l...@perl.org
On Wed, 16 Apr 2003, Austin Hastings wrote:
> > We need to distinguish between "conversion" and "typecasting". Often we
> > are not converting anything, but merely remembering what the type
> > originally was.
>
> So perhaps we shouldn't worry about that case directly, and instead just
> require some DWIMery: narrowing conversions are not compile errors, but will
> have to be checked at run-time.

Heck, now that someone actually says it, that really seems quite logical.

The compile time logic could be something like this:
For the expression $a = $b,
if $b.type ISA $a.type : OK ( $b is same or subclass of $a )
elsif $a.type ISA $b.type : defer until runtime ($a is subclass of $b)
else : compile time ERROR

If we assume[1] that Scalar is the base of all classes, then we get the
desired typed <-> untyped behavior for free. I like it! (Unknown type
situations are always deferred of course.)

We still need an occasional typecast for the really bizarre situations
like my multiply-inherited-siblings example. I like the suggested "as"
keyword for that, especially since I'm already used to it in Delphi.

OTOH, one could always force runtime checking with an intermediate untyped
variable. $a = my $xxx = $b. Naah, I still like "as" better.

[1] Scalar might be a container class. Maybe Object is the base class for
values.


On second thought, one could consider $a = $b as a sort of typecast
already, since both sides have type information already. (Not that I'm
saying it really is, just that we have enough information.) The real
problem is with this:

class Foo is Bar { method foo; }
my Bar $b = Foo.new;
...
$b.foo;

Since foo is not a method of Bar, and the compiler doesn't really know
which subclass of Bar it might be from, this would be a compile time error
unless:

(A) I write ($b as Foo).foo;
(B) The compiler always punts until runtime.
(C) The compiler searches all known subclasses of Bar for foo.

(A) is ugly, and results in a lot of useless code which makes the useful
code hard to read. It is also what most languages do. I hope we can find
a way to avoid it.

(B) is not very efficient.

(C) sucks. I'm embarrassed to even suggest it.

Are there any other alternatives?


Actually, I think I favor (B). At runtime it asks "Can $b foo?".

In (A) we already know that a Foo can foo, but we still have to ask at
runtime "Is $b a Foo?" to validate the typecast, so it doesn't eliminate
all runtime cost. We may not even be able to precompute which foo to
call, because $b could also be a subclass of Foo which overrides foo.
fooey!


> Alternatively, we could go with the "typed" idea I mentioned earlier, and
> say
>
> my Foo $x = (my Object $z = Foo.new).typed(Foo);
>
> I like this better than the "obvious" .Foo trait, because when dealing with
> multiply typed vars, it's easier:
>
> my $x is Slicer is Dicer is Grinder;
> my $j = $x;
> $x = $j.Slicer.Dicer.Grinder; # Doubtful
> $x = $j.typed(Slicer, Dicer, Grinder);

That (or using properties: $j but typed(Slicer,Dicer,Mixer)) looks more
like Mixin classes to me.

~ John Williams


Luke Palmer

unread,
Apr 17, 2003, 3:23:42 PM4/17/03
to will...@tni.com, Austin_...@yahoo.com, mlaz...@cognitivity.com, perl6-l...@perl.org
> On Wed, 16 Apr 2003, Austin Hastings wrote:
> > > We need to distinguish between "conversion" and "typecasting". Often we
> > > are not converting anything, but merely remembering what the type
> > > originally was.
> >
> > So perhaps we shouldn't worry about that case directly, and instead just
> > require some DWIMery: narrowing conversions are not compile errors, but will
> > have to be checked at run-time.
>
> Heck, now that someone actually says it, that really seems quite logical.
>
> The compile time logic could be something like this:
> For the expression $a = $b,
> if $b.type ISA $a.type : OK ( $b is same or subclass of $a )
> elsif $a.type ISA $b.type : defer until runtime ($a is subclass of $b)
> else : compile time ERROR
>
> If we assume[1] that Scalar is the base of all classes, then we get the
> desired typed <-> untyped behavior for free. I like it! (Unknown type
> situations are always deferred of course.)

I.... don't think so. The type-is-interface theory (which I'll post
soon--I think it'll make Perl OO a lot more tolerable than other OOs)
makes it so the third clause will never be executed. And then you
don't get compile time type errors, which is why you wanted strong
typing in the first place.

> We still need an occasional typecast for the really bizarre situations
> like my multiply-inherited-siblings example. I like the suggested "as"
> keyword for that, especially since I'm already used to it in Delphi.

Or we could require typecasts in all cases where $b isn'ta $a. See
below.

> OTOH, one could always force runtime checking with an intermediate untyped
> variable. $a = my $xxx = $b. Naah, I still like "as" better.

Thank ghod. I would consider the other way a disgusting workaround.

> On second thought, one could consider $a = $b as a sort of typecast
> already, since both sides have type information already. (Not that I'm
> saying it really is, just that we have enough information.) The real
> problem is with this:
>
> class Foo is Bar { method foo; }
> my Bar $b = Foo.new;
> ...
> $b.foo;
>
> Since foo is not a method of Bar, and the compiler doesn't really know
> which subclass of Bar it might be from, this would be a compile time error
> unless:
>
> (A) I write ($b as Foo).foo;
> (B) The compiler always punts until runtime.
> (C) The compiler searches all known subclasses of Bar for foo.
>
> (A) is ugly, and results in a lot of useless code which makes the useful
> code hard to read. It is also what most languages do. I hope we can find
> a way to avoid it.
>
> (B) is not very efficient.
>
> (C) sucks. I'm embarrassed to even suggest it.
>
> Are there any other alternatives?

Yeah. Don't write code like that! If you're going to use it like a
Foo, don't declare it like a Bar. That's what typing is all about!

> Actually, I think I favor (B). At runtime it asks "Can $b foo?".

Yeah, great. Now we have Perl5 OO back. :-/

I think it's about time I finish up and post my type-is-interface doc,
to get people thinking more clearly about what isa and can
relationships are. Or to be ignored like other long well-thought-out
docs on here. (IIRC, Austin just posted something nice recently...)

Luke

John Williams

unread,
Apr 17, 2003, 3:45:30 PM4/17/03
to Luke Palmer, perl6-l...@perl.org
On 17 Apr 2003, Luke Palmer wrote:
> > class Foo is Bar { method foo; }
> > my Bar $b = Foo.new;
> > ...
> > $b.foo;
> >
> > Since foo is not a method of Bar, and the compiler doesn't really know
> > which subclass of Bar it might be from, this would be a compile time error
> > unless:
> >
> > (A) I write ($b as Foo).foo;
> > (B) The compiler always punts until runtime.
> > (C) The compiler searches all known subclasses of Bar for foo.
> >
> > Are there any other alternatives?
>
> Yeah. Don't write code like that! If you're going to use it like a
> Foo, don't declare it like a Bar. That's what typing is all about!

Think about generic programming.

If I want to have a generic container for Bars or subclasses of Bars, I
have to do a typecast every time I take something out of the
container. (Unless Bar already does everything it's subclasses might do,
which won't happen with a truely generic container.)

I'm currently maintaining code which uses a lot of such generic
containers, and while the containers make it easy to do things, all the
typecasts make it hard to read want I am doing.

~ John Williams


Austin Hastings

unread,
Apr 17, 2003, 3:57:59 PM4/17/03
to Dan Sugalski, perl6-l...@perl.org

So if I say

my $a is Scalar is MovieDate;

my $a = 2003;

print $a;
print "$a";

Will I get 2003, or MMIII, or one each?

=Austin

Luke Palmer

unread,
Apr 17, 2003, 4:12:29 PM4/17/03
to will...@tni.com, perl6-l...@perl.org
> On 17 Apr 2003, Luke Palmer wrote:
> > > class Foo is Bar { method foo; }
> > > my Bar $b = Foo.new;
> > > ...
> > > $b.foo;
> > >
> > > Since foo is not a method of Bar, and the compiler doesn't really know
> > > which subclass of Bar it might be from, this would be a compile time error
> > > unless:
> > >
> > > (A) I write ($b as Foo).foo;
> > > (B) The compiler always punts until runtime.
> > > (C) The compiler searches all known subclasses of Bar for foo.
> > >
> > > Are there any other alternatives?
> >
> > Yeah. Don't write code like that! If you're going to use it like a
> > Foo, don't declare it like a Bar. That's what typing is all about!
>
> Think about generic programming.

I do that more than a healty person should... :)

> If I want to have a generic container for Bars or subclasses of Bars, I
> have to do a typecast every time I take something out of the
> container. (Unless Bar already does everything it's subclasses might do,
> which won't happen with a truely generic container.)
>
> I'm currently maintaining code which uses a lot of such generic
> containers, and while the containers make it easy to do things, all the
> typecasts make it hard to read want I am doing.

I don't understand. Why do you have to typecast every time you take
something out of the container? If you're taking things out of the
container, and using methods that they're not guaranteed to have,
you're asking for trouble.

Are you talking about the generic container just being a container of
Objects? If you are, then that's the problem. That, IMO, is not a
reasonable approach to generic programming (that's how Java does it,
and Java doesn't do it well, trust me).

If you have a container of Bars, don't call it a container of Objects,
call it a container of Bars. Perl 6 will allow you to do this:

my Bar @array;

When you have a container of Objects, there's no guarantee that nobody
put a Cat in there. That's why you have to typecast. And Perl will
allow you to guarantee that nobody put a Cat in there. (Or, under my
proposal, it will guarantee that nobody put a Cat that doesn't think
it's a Bar in there.)

Luke

John Williams

unread,
Apr 17, 2003, 4:44:58 PM4/17/03
to Luke Palmer, perl6-l...@perl.org
On 17 Apr 2003, Luke Palmer wrote:
> > I'm currently maintaining code which uses a lot of such generic
> > containers, and while the containers make it easy to do things, all the
> > typecasts make it hard to read want I am doing.
>
> I don't understand. Why do you have to typecast every time you take
> something out of the container? If you're taking things out of the
> container, and using methods that they're not guaranteed to have,
> you're asking for trouble.

Actually, they are collections of database record objects. Each database
table has a differenct class. Each table may have different business
rules implemented as methods.

So I have generic lists to hold database objects, but to really do
something useful (the business rules), I have to call methods which are
completely unknown to the base record object type.

> Are you talking about the generic container just being a container of
> Objects? If you are, then that's the problem. That, IMO, is not a
> reasonable approach to generic programming (that's how Java does it,
> and Java doesn't do it well, trust me).

I believe you.

> If you have a container of Bars, don't call it a container of Objects,
> call it a container of Bars. Perl 6 will allow you to do this:
>
> my Bar @array;

That solves one level deep. (And hooray for perl! Most languages cannot
even do that.)

I also have, for example, a listcache, which allows me to cache lists of
records from the database. The lists are registered at runtime, so there
is no way the GetList function can tell the compiler what kind of list is
being returned.

> When you have a container of Objects, there's no guarantee that nobody
> put a Cat in there. That's why you have to typecast.

But the typecast only makes the compiler happy. You still have to check
at runtime to be sure it's not a Cat. I guess I don't believe the few
errors it catches are worth the verbosity.

> And Perl will
> allow you to guarantee that nobody put a Cat in there. (Or, under my
> proposal, it will guarantee that nobody put a Cat that doesn't think
> it's a Bar in there.)

Thanks for linking to that smalltalk article. It expresses my discontent
with OO typing very well.

~ John Williams


Paul

unread,
Apr 17, 2003, 5:46:51 PM4/17/03
to John Williams, Austin_...@yahoo.com, Michael Lazzaro, perl6-l...@perl.org

--- John Williams <will...@tni.com> wrote:
> The compile time logic could be something like this:
> For the expression $a = $b,
> if $b.type ISA $a.type : OK ( $b is same or subclass of $a )
> elsif $a.type ISA $b.type : defer to runtime ($a is subclass of $b)
> else : compile time ERROR

Should you be allowed to assign to a more restrictive type?
Hmm... well if I say

$superclass = $subclass; # as a holding variable
# code . . . then laterrestore with
$subclass = $superclass;

I could see that as useful, but I'd rather have to be a bit more
explicit -- maybe with

$subclass = $superclass as SubClass;


> If we assume[1] that Scalar is the base of all classes, then we get
> the desired typed <-> untyped behavior for free. I like it!
> (Unknown type situations are always deferred of course.)

Works for me. :)

> class Foo is Bar { method foo; }
> my Bar $b = Foo.new;
> ...
> $b.foo;
>
> Since foo is not a method of Bar, and the compiler doesn't really
> know which subclass of Bar it might be from, this would be a compile
> time error unless:
>
> (A) I write ($b as Foo).foo;
> (B) The compiler always punts until runtime.
> (C) The compiler searches all known subclasses of Bar for foo.
>
> (A) is ugly, and results in a lot of useless code which makes
> the useful code hard to read. It is also what most languages do.
> I hope we can find a way to avoid it.

Thought it would still be nice to have available as an optional
compile-time optimization for those who *know* that's what they want.

> (B) is not very efficient.

Depends -- as you point out, below, there are costs, and there are
costs. :)



> (C) sucks. I'm embarrassed to even suggest it.

Don't be -- I think thereare times when it's appropriate, btus damned
sure not as the ONLY option! On the other hand, in one-off
mini-scripts, maybe that's exactly the sort of power and flexibility
you want.



> Are there any other alternatives?
>
> Actually, I think I favor (B). At runtime it asks "Can $b foo?".

I'm still wondering -- shouldn't it be asking "can what's *in* $b
.foo()?"

> In (A) we already know that a Foo can foo, but we still have to ask
> at runtime "Is $b a Foo?" to validate the typecast,

exactly....

> so it doesn't eliminate all runtime cost. We may not even be able
> to precompute which foo to call, because $b could also be a subclass
> of Foo which overrides foo. fooey!

Again, exactly. There's no getting away from the runtime costs without
explicitly pre-stating that you know exactly what you're doing and that
if it doesn't work that way it must have been a mistake. I want to be
able to turn on that sort of Soup-Nazi oversight, but only on demand.

On the other hand, I want to be able to turn it off and be as DWIMmy as
possible, *but only on demand*. As a default, I'd like the middle
ground. Warn me that I did something strange when warnings are on
(which they will be), and then go on and try to do it. Hell, maybe
there's a warning level:

use strict types => 'trafficCop',
refs => 'SoupNazi',
subs => 'wimp';

Paul

unread,
Apr 17, 2003, 5:53:45 PM4/17/03
to Luke Palmer, will...@tni.com, Austin_...@yahoo.com, mlaz...@cognitivity.com, perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> > (A) I write ($b as Foo).foo;
> > (B) The compiler always punts until runtime.
> > (C) The compiler searches all known subclasses of Bar for foo.
> >
> > (A) is ugly, and results in a lot of useless code which makes the
> > useful code hard to read. It is also what most languages do.
> > I hope we can find a way to avoid it.
> >
> > (B) is not very efficient.
> >
> > (C) sucks. I'm embarrassed to even suggest it.
> >
> > Are there any other alternatives?
>
> Yeah. Don't write code like that! If you're going to use it like a
> Foo, don't declare it like a Bar. That's what typing is all about!

I agree that this is the stance you should take as a default, but
disagree that the situation is that simple. Try not to right code like
that, but sometimes the situation warrants fluidity and flexibility. If
that means I must abandon the type system altogether, the so be it, but
I'd rather use it when I can, and *particularly* in wierd cases like
that where you need all the help you can get to keep from shooting
yourself in the foot.

Then again, it could be argued that if you're doing wierdness like
that, your readability might benefit by weeding out the extra code
represented by the types....but that's arguable....

> > Actually, I think I favor (B). At runtime it asks "Can $b foo?".
>
> Yeah, great. Now we have Perl5 OO back. :-/

Not exactly, but hey, even if we do, I happen to *like* P5's OO system.
:)

Not that I don't think there's plenty of room for improvement. I just
prefer it to practically anything else I've used, if you lump all the
good with the bad and take it on balance.



> I think it's about time I finish up and post my type-is-interface
> doc, to get people thinking more clearly about what isa and can
> relationships are. Or to be ignored like other long well-thought-out
> docs on here. (IIRC, Austin just posted something nice recently...)
>
> Luke

Go for it. I'm all eyes. :)

Austin Hastings

unread,
Apr 17, 2003, 6:04:08 PM4/17/03
to John Williams, perl6-l...@perl.org

--- John Williams <will...@tni.com> wrote:

Agreed.

> (B) is not very efficient.

Agreed.

> (C) sucks. I'm embarrassed to even suggest it.

I don't agree. For you to talk about it implies that you know it
exists, or that you made a typo. There's no reason for the compiler not
to look around for subclasses of Bar to see if there's some valid use
you could be intending. If *NOT*, a warning would be appropriate:

Warning: Invoked method foo on object of class Bar, but neither Bar nor
any children have a foo method.

If there *IS* such a method down there someplace, then the compiler can
happily assume that you know what you're doing, and emit code for
rudimentary checking (search below Bar) instead of the full-up (search
every conceivable place) checking done when no data is available.

> Are there any other alternatives?

Sure. Luke's got a start.

> > Alternatively, we could go with the "typed" idea I mentioned
> > earlier, and say
> >
> > my Foo $x = (my Object $z = Foo.new).typed(Foo);
> >
> > I like this better than the "obvious" .Foo trait, because when
> dealing with
> > multiply typed vars, it's easier:
> >
> > my $x is Slicer is Dicer is Grinder;
> > my $j = $x;
> > $x = $j.Slicer.Dicer.Grinder; # Doubtful
> > $x = $j.typed(Slicer, Dicer, Grinder);
>
> That (or using properties: $j but typed(Slicer,Dicer,Mixer)) looks
> more like Mixin classes to me.

How would you handle it with C<as>?

$x = $j as Slicer as Dicer as Grinder; #Yikes!

Better would be

$x = $j as $x; # C<as> can take an object and extract type info.

Or perhaps we could come up with another punctuator: C<dammit>

$x = $j dammit;

AKA: C<!>

$x = $j!;

>
> ~ John Williams

=Austin

Paul

unread,
Apr 17, 2003, 6:08:50 PM4/17/03
to Luke Palmer, will...@tni.com, perl6-l...@perl.org
> If you have a container of Bars, don't call it a container of
> Objects, call it a container of Bars. Perl 6 will allow you to
> do this:
>
> my Bar @array;

But sometimes it greatly simplifies a piece of code if it can broaden
it's assumptions. Maybe a sub that isn't a method knows that it can
work on any shape with 4 sides, but the code you've been told to
maintain wasn't written with a Quadrilateral class. You just have Shape
and it's children, Square and Rectangle and Trapezoid and Triangle and
Circle and Ellipse.

sub foo (Shape $obj) {
my %valid = { Square => 1, Rectangle => 1, Trapezoid => 1 };
return unless %valid{ref $obj};
not_do_other_stuff();
}

my Square $s = Square.new;
foo($s);

Are you going to dissallow that? Then you doom me to rewrite a lot of
legacy code. True, it probably needs to be done anyway, but if my PHB
doesn't want that, I may catch the heat for it.... and yes, I know I
could just call it a Scalar, but I'd rather not have to blow this up to
a megapost for an example.

> When you have a container of Objects, there's no guarantee that
> nobody put a Cat in there. That's why you have to typecast.

There is if I'm allowed to make my container Canine. Then Dog is ok and
Wolf is ok (wolves aren't dogs, but canis lupus is part of the genus),
but Cat is definitely not ok, and not I don't have to check it
explicitly. Why is that bad?

> And Perl will allow you to guarantee that nobody put a Cat in there.
> (Or, under my proposal, it will guarantee that nobody put a Cat that
> doesn't think it's a Bar in there.)
>
> Luke

Ok,
my Cat $cat is Dog;
would get it in, but that's ok, right?
Because the *value* is a Canine, even though for some reason you want
to be able to get it high on catnip and have it climb trees....

Paul

unread,
Apr 17, 2003, 6:24:18 PM4/17/03
to Austin_...@yahoo.com, John Williams, perl6-l...@perl.org

--- Austin Hastings <austin_...@yahoo.com> wrote:
> > > my $x is Slicer is Dicer is Grinder;
> > > my $j = $x;
> > > $x = $j.Slicer.Dicer.Grinder; # Doubtful
> > > $x = $j.typed(Slicer, Dicer, Grinder);
> >
> > That (or using properties: $j but typed(Slicer,Dicer,Mixer)) looks
> > more like Mixin classes to me.
>
> How would you handle it with C<as>?
>
> $x = $j as Slicer as Dicer as Grinder; #Yikes!

Is kinda icky....



> Better would be
>
> $x = $j as $x; # C<as> can take an object and extract type info.

Now *that*'s cool. I could definitely see uses for that....



> Or perhaps we could come up with another punctuator: C<dammit>
>
> $x = $j dammit;

Oh, COOL! Please, could we, huh? huh? huh????
I'd LOVE to actually see that in a language.
Yes, because it's a good idea and a very valid syntax,
but even moreso because I want C<dammit> as an out-of-the-box operator!
Talk about advocacy! lol!!! =o]

> AKA: C<!>
>
> $x = $j!;

Nah -- that's a factorial. :)

Seriously, though, I really do think this is a great idea.
And though I *really* would _LOVE_ to see C<dammit> as a keyword (lol),
how about:

$x = $j unconditionally; # Huffman shouldn't complain ....
# can't be terribly common.

or maybe

$x = $j as whatever; # just do it :)

or

$x <- $j ; # we don't have one of those, do we?

or

assign $x from $j; # CoBOL, here we come!

Luke Palmer

unread,
Apr 17, 2003, 6:37:56 PM4/17/03
to Hod...@writeme.com, will...@tni.com, perl6-l...@perl.org
> > If you have a container of Bars, don't call it a container of
> > Objects, call it a container of Bars. Perl 6 will allow you to
> > do this:
> >
> > my Bar @array;
>
> But sometimes it greatly simplifies a piece of code if it can broaden
> it's assumptions. Maybe a sub that isn't a method knows that it can
> work on any shape with 4 sides, but the code you've been told to
> maintain wasn't written with a Quadrilateral class. You just have Shape
> and it's children, Square and Rectangle and Trapezoid and Triangle and
> Circle and Ellipse.
>
> sub foo (Shape $obj) {
> my %valid = { Square => 1, Rectangle => 1, Trapezoid => 1 };
> return unless %valid{ref $obj};
> not_do_other_stuff();
> }
>
> my Square $s = Square.new;
> foo($s);

Thank you! This perfectly demonstrates the type-is-interface idea!

sub foobs (Quadrilateral $obj) { ... }

And then, if your code wasn't written with a Quadrilateral class, it'd
work anyway! Because Square I<behaves> like a Quadrilateral, even
though it didn't say it was one.

Just hope nobody writes code like the C<foo> above, which explicitly
checks type names. Then you're screwed, and it's not the compiler's
fault.

> > When you have a container of Objects, there's no guarantee that
> > nobody put a Cat in there. That's why you have to typecast.
>
> There is if I'm allowed to make my container Canine. Then Dog is ok and
> Wolf is ok (wolves aren't dogs, but canis lupus is part of the genus),
> but Cat is definitely not ok, and not I don't have to check it
> explicitly. Why is that bad?

Huh? You don't have to check it explicitly. Cat doesn't support the
bark() method, so it can't be used as a Dog. And the type system will
see that. End of story.

Luke

John Williams

unread,
Apr 17, 2003, 6:41:57 PM4/17/03
to Hod...@writeme.com, Austin_...@yahoo.com, perl6-l...@perl.org
On Thu, 17 Apr 2003, Paul wrote:
> > How would you handle it with C<as>?
> >
> > $x = $j as Slicer as Dicer as Grinder; #Yikes!
>
> Is kinda icky....

Well, since they are both specifying classes, I would expect is and as to
have the same syntax, so either of


$j as Slicer as Dicer as Grinder;

$j as (Slicer, Dicer, Grinder);
(as long as those work for is too.)


> > Or perhaps we could come up with another punctuator: C<dammit>
> >
> > $x = $j dammit;
>
> Oh, COOL! Please, could we, huh? huh? huh????

sub postfix:dammit ($a) returns Scalar { return $a as Scalar; }
or
sub postfix:dammit ($a) { return $a but dynamic; }


~ John Williams

Austin Hastings

unread,
Apr 17, 2003, 6:47:23 PM4/17/03
to Hod...@writeme.com, perl6-l...@perl.org

--- Paul <ydb...@yahoo.com> wrote:
> > If you have a container of Bars, don't call it a container of
> > Objects, call it a container of Bars. Perl 6 will allow you to
> > do this:
> >
> > my Bar @array;
>
> But sometimes it greatly simplifies a piece of code if it can broaden
> it's assumptions. Maybe a sub that isn't a method knows that it can
> work on any shape with 4 sides, but the code you've been told to
> maintain wasn't written with a Quadrilateral class. You just have
> Shape
> and it's children, Square and Rectangle and Trapezoid and Triangle
> and
> Circle and Ellipse.
>
> sub foo (Shape $obj) {
> my %valid = { Square => 1, Rectangle => 1, Trapezoid => 1 };
> return unless %valid{ref $obj};
> not_do_other_stuff();
> }
>
> my Square $s = Square.new;
> foo($s);

I don't see anything wrong with what you've written so far. I don't
think anyone has a problem with a widening conversion, since that is
usually easy to check at compile time. (And even when it's not, it's
still easy to check.)

> Are you going to dissallow that? Then you doom me to rewrite a lot of
> legacy code. True, it probably needs to be done anyway, but if my PHB
> doesn't want that, I may catch the heat for it.... and yes, I know I
> could just call it a Scalar, but I'd rather not have to blow this up
> to a megapost for an example.

Actually, a collection of nasty OO code is probably a good thing to
have when talking about this kind of stuff. Preferably the real-world
bits, corner-cases and all.

> > When you have a container of Objects, there's no guarantee that
> > nobody put a Cat in there. That's why you have to typecast.
>
> There is if I'm allowed to make my container Canine. Then Dog is ok
> and Wolf is ok (wolves aren't dogs, but canis lupus is part of the
> genus), but Cat is definitely not ok, and not I don't have to check
> it explicitly. Why is that bad?
>
> > And Perl will allow you to guarantee that nobody put a Cat in
> > there. (Or, under my proposal, it will guarantee that nobody put a
> > Cat that doesn't think it's a Bar in there.)
>

> Ok,
> my Cat $cat is Dog;
> would get it in, but that's ok, right?

Sure. If you say C<my Canine @pound;> then (I think we all agree) you
should be able to store Dog, Wolf, and Lon Chaney, Jr.

If your Cat $cat is Dog, you're associating the Dog-methods with it, as
I understand it, and promising that it will respond to them correctly.

=Austin


Brent Dax

unread,
Apr 17, 2003, 7:08:12 PM4/17/03
to Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
Michael Lazzaro:
# In other words, what's this shorthand for:
#
# my $x;
#
# does it mean
#
# my untyped $x;
# my scalar $x;
# my Scalar $x;

I would argue that it's

my Object $x;

This has actually been bugging me for a long time: isn't Scalar a
container that holds an Object of some sort? If so, wouldn't saying

my Scalar $x;

Be equivalent to saying

my $x is Scalar of Scalar;

?

--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)

>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism

Brent Dax

unread,
Apr 17, 2003, 7:11:46 PM4/17/03
to Luke Palmer, perl6-l...@perl.org
Luke Palmer:
# foo($x as Dicer);

Shades of C#...

(C# has two different casting operators, the C-style "(type)value" and
the new "value as type". IIRC, the first returns null if it can't
complete the cast, while the second throws an exception.)

Austin Hastings

unread,
Apr 17, 2003, 6:59:16 PM4/17/03
to Luke Palmer, Hod...@writeme.com, will...@tni.com, perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:

Right. Good.

> Just hope nobody writes code like the C<foo> above, which explicitly
> checks type names. Then you're screwed, and it's not the compiler's
> fault.

I think that's wrong. Despite the fact that $obj is required (in the
sig) as a Quadrilateral, there are no Quadrilaterals. Hence, C<ref
$obj> (or more likely: C<typeof $obj>) will return Square or Rectangle
or Trapezoid or Parallelogram, as desired.

=Austin

Luke Palmer

unread,
Apr 17, 2003, 7:05:08 PM4/17/03
to bren...@cpan.org, mlaz...@cognitivity.com, da...@whipp.name, perl6-l...@perl.org
> Michael Lazzaro:
> # In other words, what's this shorthand for:
> #
> # my $x;
> #
> # does it mean
> #
> # my untyped $x;
> # my scalar $x;
> # my Scalar $x;
>
> I would argue that it's
>
> my Object $x;
>
> This has actually been bugging me for a long time: isn't Scalar a
> container that holds an Object of some sort? If so, wouldn't saying
>
> my Scalar $x;
>
> Be equivalent to saying
>
> my $x is Scalar of Scalar;
>
> ?

Yeah.

I think we're all realizing that Scalar is more than just a container.
Maybe that's not what it's called---but the standard, default type,
whatever it is. It's the thingy that polymorphically behaves as a
Str, Num, any kind of Object, etc.

Or maybe we're just not thinking right, and it I<is> just a container
that does all this. But I think whatever this thing is, it's not
Object. Object is the universal base class, with very few methods
that everyone has. Maybe it's name is too dangerous to utter, but it
lies behind everything that doesn't know otherwise. :)

Luke

Dave Whipp

unread,
Apr 17, 2003, 7:46:28 PM4/17/03
to perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> I think we're all realizing that Scalar is more than just a
> container.

I'm not sure I'm realising this. That I'm realising is that there's
a difference between "is" and "of". I think we're arguing the same
thing though: we are realising that the thing that people have been
calling "Scalar" isn't the same thing that "Scalar" thinks it is.

> Maybe that's not what it's called---but the standard, default type,
> whatever it is. It's the thingy that polymorphically behaves as a
> Str, Num, any kind of Object, etc.

Maybe its called "Anything":

my $x;
my $x is Scalar of Anything;

"Anything" includes Arrays and Hashes: these are containers, and you
can store containers in Scalers -- usually as a reference. Once could
also define Anything as the junction of all types known by the
execution engine == perhaps "AnyType" would be more accurate.

> Or maybe we're just not thinking right, and it I<is> just a
> container that does all this.

I hope that Scalar is just a container, and the default $var "is
Scalar" ... but it's not "of Scalar". I think I'll try to stop
repeating myself now.

Dave.

Damian Conway

unread,
Apr 17, 2003, 8:24:23 PM4/17/03
to perl6-l...@perl.org
Luke Palmer wrote:

> Huh? You don't have to check it explicitly. Cat doesn't support the
> bark() method, so it can't be used as a Dog. And the type system will
> see that. End of story.

There are, however, problems with an interface approach. For example:

class Dog {
method breathe() {...}
method feed() {...}
method grow() {...}
method bark() {...}
method reproduce() {...}
method die() {...}
}

class Oak {
method breathe() {...}
method feed() {...}
method grow() {...}
method bark() {...}
method reproduce() {...}
method die() {...}
}


my Oak $tree = Dog.new();
my Dog $spot = Oak.new();

:-(

Damian

Michael Lazzaro

unread,
Apr 17, 2003, 8:31:38 PM4/17/03
to Luke Palmer, bren...@cpan.org, da...@whipp.name, perl6-l...@perl.org

On Thursday, April 17, 2003, at 04:05 PM, Luke Palmer wrote:
> Brent Dax:

Yep. It feels like we're just spinning our wheels, at this point. A
lot of our suppositions are getting increasingly remote, based on our
central premise (above) which may or may not be valid.

I think we need the design team to weigh in here, and verify what parts
of our hand-waving are and aren't totally off-base. Or at least weigh
in and say that they don't know, but the general directions they're
leaning.

IMO, I'm not thinking coercions like we've been talking about are
really a critical thing at this point, since they lean pretty heavily
on A12 stuff, but the edge cases of moving things between
typed-and-untyped variables is looking pretty darn important, since
they tie in with the whole var-vs-val-types thing.

:-/

MikeL

Michael Lazzaro

unread,
Apr 17, 2003, 8:33:59 PM4/17/03
to perl6-l...@perl.org

On Thursday, April 17, 2003, at 05:31 PM, Michael Lazzaro wrote:
<frantic pleas for help>

Doh! I press send on that last method, and lo-and-behold a message
from Damian shows up.

Sorry, Damian. We seem to have made an awful mess on the carpet while
you were gone...

MikeL

Michael Lazzaro

unread,
Apr 17, 2003, 8:37:02 PM4/17/03
to Michael Lazzaro, perl6-l...@perl.org

On Thursday, April 17, 2003, at 05:33 PM, Michael Lazzaro wrote:

> Doh! I press send on that last method

^^^^^^^

Sigh. I mean, 'message', not 'method'. I hab a bih ub a cold raht
now, so I type "ssage" as "thod". ;-)

MikeL

Paul

unread,
Apr 17, 2003, 8:44:16 PM4/17/03
to Luke Palmer, Hod...@writeme.com, will...@tni.com, perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> > > If you have a container of Bars, don't call it a container of
> > > Objects, call it a container of Bars. Perl 6 will allow you to
> > > do this:
> > >
> > > my Bar @array;
> >
> > But sometimes it greatly simplifies a piece of code if it can
> > broaden it's assumptions. Maybe a sub that isn't a method knows
> > that it can work on any shape with 4 sides, but the code you've
> > been told to maintain wasn't written with a Quadrilateral class.
> > You just have Shape and it's children, Square and Rectangle and
> > Trapezoid and Triangle and Circle and Ellipse.
> >
> > sub foo (Shape $obj) {
> > my %valid = { Square => 1, Rectangle => 1, Trapezoid => 1 };
> > return unless %valid{ref $obj};
> > not_do_other_stuff();
> > }
> >
> > my Square $s = Square.new;
> > foo($s);
>
> Thank you! This perfectly demonstrates the type-is-interface idea!
>
> sub foobs (Quadrilateral $obj) { ... }
>
> And then, if your code wasn't written with a Quadrilateral class,
> it'd work anyway! Because Square I<behaves> like a Quadrilateral,
> even though it didn't say it was one.

Sounds great! When do I get to see this document? :)
I suspect it may just be the solution we need....

> Just hope nobody writes code like the C<foo> above, which explicitly
> checks type names. Then you're screwed, and it's not the compiler's
> fault.

lol -- yeah, I knew that hardcoding was bad when I wrote it, but didn't
want to have to wade through extra syntax that muddied the waters. :)



> > > When you have a container of Objects, there's no guarantee that
> > > nobody put a Cat in there. That's why you have to typecast.
> >
> > There is if I'm allowed to make my container Canine. Then Dog
> > is ok and Wolf is ok (wolves aren't dogs, but canis lupus is

> > part of the genus), but Cat is definitely not ok, and no[w](sp)


> > I don't have to check it explicitly. Why is that bad?

[spelling correction above^]


> Huh? You don't have to check it explicitly. Cat doesn't support the
> bark() method, so it can't be used as a Dog. And the type system
> will see that. End of story.

Is it?
If you need the bark method, then yes.
But could you enforce some pseudo inheritance with traits?

my Cat $critter is Dog;

The variable explicitly stated as accepting a Cat value, but has also
been explicitly stated to be a Dog container. That's either a compile
time error, or an explicit exception that should tell the compiler to
mark this one as allowing Cat values, but to inherit from Dog as well.

Personally I'd say it should blow up....
But then what about

my Dog @pound is Array of Canine;

That explicitly declares @pound as an array of type Canine which is
going to hold Dog values. Again, does that blow up?

Geez, will I ever need this? lol....

Paul

unread,
Apr 17, 2003, 8:48:14 PM4/17/03
to John Williams, Hod...@writeme.com, Austin_...@yahoo.com, perl6-l...@perl.org

> > > Or perhaps we could come up with another punctuator: C<dammit>
> > >
> > > $x = $j dammit;
> >
> > Oh, COOL! Please, could we, huh? huh? huh????
>
> sub postfix:dammit ($a) returns Scalar { return $a as Scalar; }
> or
> sub postfix:dammit ($a) { return $a but dynamic; }

Yeah, but it isn't really all that cool unless it comes in the standard
distribution. We could always have written a dammit() function (and to
be truthful, I have, several times...) but it's different if it's a
built-in operator. :)

Paul

unread,
Apr 17, 2003, 8:54:20 PM4/17/03
to Austin_...@yahoo.com, Hod...@writeme.com, perl6-l...@perl.org

--- Austin Hastings <austin_...@yahoo.com> wrote:
> --- Paul <ydb...@yahoo.com> wrote:
> > > If you have a container of Bars, don't call it a container of
> > > Objects, call it a container of Bars. Perl 6 will allow you to
> > > do this:
> > >
> > > my Bar @array;
> >
> > But sometimes it greatly simplifies a piece of code if it can
> > broaden it's assumptions. Maybe a sub that isn't a method knows
> > that it can work on any shape with 4 sides, but the code you've
> > been told to maintain wasn't written with a Quadrilateral class.
> > You just have Shape and it's children, Square and Rectangle and
> > Trapezoid and Triangle and Circle and Ellipse.
> >
> > sub foo (Shape $obj) {
> > my %valid = { Square => 1, Rectangle => 1, Trapezoid => 1 };
> > return unless %valid{ref $obj};
> > not_do_other_stuff();
> > }
> >
> > my Square $s = Square.new;
> > foo($s);
>
> I don't see anything wrong with what you've written so far. I don't
> think anyone has a problem with a widening conversion, since that is
> usually easy to check at compile time. (And even when it's not, it's
> still easy to check.)

Well, I wouldn't say there was *nothing* wrong with it.
The hardcode sux, but it was a quick example, and I didn't want to
sidetrack the discussion, lol....

> > Are you going to dissallow that? Then you doom me to rewrite
> > a lot of legacy code. True, it probably needs to be done
> > anyway, but if my PHB doesn't want that, I may catch the
> > heat for it.... and yes, I know I could just call it a Scalar,
> > but I'd rather not have to blow this up to a megapost for an
> > example.
>
> Actually, a collection of nasty OO code is probably a good thing to
> have when talking about this kind of stuff. Preferably the real-world
> bits, corner-cases and all.

Yeah, but then you'd see what kind of cryptocontext BS I actually write
on a daily basis, and you'd lose all respect for me, and wouldn't call
me in the morning.... ;o]

> > > When you have a container of Objects, there's no guarantee that
> > > nobody put a Cat in there. That's why you have to typecast.
> >
> > There is if I'm allowed to make my container Canine. Then Dog is ok
> > and Wolf is ok (wolves aren't dogs, but canis lupus is part of the
> > genus), but Cat is definitely not ok, and not I don't have to check
> > it explicitly. Why is that bad?
> >
> > > And Perl will allow you to guarantee that nobody put a Cat in
> > > there. (Or, under my proposal, it will guarantee that nobody put
> > > a Cat that doesn't think it's a Bar in there.)
> >
> > Ok,
> > my Cat $cat is Dog;
> > would get it in, but that's ok, right?
>
> Sure. If you say C<my Canine @pound;> then (I think we all agree) you
> should be able to store Dog, Wolf, and Lon Chaney, Jr.
>
> If your Cat $cat is Dog, you're associating the Dog-methods with it,
> as I understand it, and promising that it will respond to them
> correctly.
>
> =Austin

And if it doesn't it will blow up at run time, as well it should,
because you lied. Exactly.

Wow, I think I'm starting to get the hang of this. :)

Paul

unread,
Apr 17, 2003, 9:00:42 PM4/17/03
to Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Brent Dax <bren...@cpan.org> wrote:
> Michael Lazzaro:
> # In other words, what's this shorthand for:
> #
> # my $x;
> #
> # does it mean
> #
> # my untyped $x;
> # my scalar $x;
> # my Scalar $x;
>
> I would argue that it's
>
> my Object $x;
>
> This has actually been bugging me for a long time: isn't Scalar a
> container that holds an Object of some sort?

Depends on what you mean.

my Scalar $x = 1;

Is that an implicit instantiation of an Int, or just an assignment to a
Scalar of a literal that doesn't get typed until a context is required?

> If so, wouldn't saying
>
> my Scalar $x;
>
> Be equivalent to saying
>
> my $x is Scalar of Scalar;
>
> ?

Yes... and also like

my Scalar $x is Scalar of Scalar; # ?

and my favorite:

my $x;

Paul

unread,
Apr 17, 2003, 9:04:26 PM4/17/03
to Brent Dax, Luke Palmer, perl6-l...@perl.org

--- Brent Dax <bren...@cpan.org> wrote:
> Luke Palmer:
> # foo($x as Dicer);
>
> Shades of C#...
>
> (C# has two different casting operators, the C-style "(type)value"
> and the new "value as type". IIRC, the first returns null if it
> can't complete the cast, while the second throws an exception.)

Hmm.... damned handy to have the possible differentiation, though I
think I'd be as happy with a pragma that decides, possibly in a lexical
scope.

my Foo $f = Bar.new as Foo; # assigned undef on fail

or

use strict types;
my Foo $f = Bar.new as Foo; # throws an exception on fail

Dave Whipp

unread,
Apr 17, 2003, 9:36:06 PM4/17/03
to Hod...@writeme.com, Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Paul <ydb...@yahoo.com> wrote:
> Depends on what you mean.
>
> my Scalar $x = 1;
>
> Is that an implicit instantiation of an Int, or just an
> assignment to a Scalar of a literal that doesn't get typed
> until a context is required?

Semantic error: literal '1' is numeric or string, not scalar. There's
no auto-dereferencing of Scalars (unlike arrays and hashes).

Instead try

my Scalar $x = Scalar.new(1);
or
my Scalar $x = Scalar.new;
$x.STORE(1);

Dave.

Paul

unread,
Apr 17, 2003, 9:48:56 PM4/17/03
to Dave Whipp, perl6-l...@perl.org

--- Dave Whipp <dave_...@yahoo.com> wrote:
> --- Paul <ydb...@yahoo.com> wrote:
> > More importantly, just besause your example doesn't require
> > inheritance doesn't mean an Int isn't "isa" Scalar.
>
> Ignoring the implementation for a moment, if Int were implemented in
> Perl6, then it would, itself, be a container:

Agreed -- and thus capable of being a declared type of a $var that can
hold an appropriate value, and of rejecting via compiler checks any
inappropriate value at compile time, ot via run-time checking at run
time.

> class Int { has char @digits is private; ... }

Is char a type?

> However, an Int is not a Scalar, because if it were then you would be
> able to store Ints, Strs and Foos in it (otherwise you'd be violating
> Liskov). An Int (in the above definition) can only contain an array
> of chars. It may have some rules that allow it to give you objects of
> other types (if you ask it nicely).

If that's the way you choose to phrase it, or implement it.
It is *possible* to subclass something and *remove* functionality,
though it's a bit wierd. More likely, though, Scalar Scalar is
implemented with "has-a" elements for Str and Int and Object, and just
populates them from any assignment as appropriate, and when another is
requested does in implicit typecast. So

my $x = 1;
print "$x";

would call $x.toString, which would likely delegate to the internal Int
object's .toString. All this has been said before, and I understand it,
but we still need to work out more detail. If

my $x = Foo.new;

then it would store in the Object "slot"....
but this is all way too kludgy, I would think.

So maybe Scalar is just an Object that defaults to runtime delegation.
Then it doesn't need inheritance and doesn't have to kludge sub-units.

class Scalar is Object {
method AUTOLOAD ($me) {
# code to check context required and
# delegate to the appropriate class
}
}

Now a Scalar can accept any arbitrary type and behave correctly,
because it's doing run-time checking. If you don't want the slowdown of
runtime checks, declare type correctly and it won't have to, because
the compiler will have already delegated to the right class.

> So an Int is not a Scalar: its a container, that can be used as a
> value, that can be stored in a Scalar: and a Scalar has some rules
> that allow it to manipulate Ints behind the scenes, to give you other
> types (if you ask it nicely).

My only gripe with your statement is that *anything* can be a Scalar.
I assume, however, that you were talking about inheritance, and I don't
argue the point.

However, it is *not* "a container, that can be used as a value, that
can be stored in a Scalar". It is a Type of value which can be
instantiated into a container; it's a subtle difference, but it's
there. And Int isn't a container, it's a promise we make to the
compiler *about* a container, that the only values we put into it will
be of that type.

"An Int" or "a Scalar" are terms that refer to the VALUES, and when use
about a container, refer to the TYPE VALUE THAT CONTAINER
EXPECTS/ALLOWS.

I think that we may need to change our phrasing.

my Scalar $x;

doesn't mean that $x is a Scalar, it means we promise to put Scalars in
it.

my $x is Scalar;

If I understand it right, refers to the container rather than the
values it is to hold? Then that's a silly thing to say, isn't it? Just
say

my $x;

Now, it becomes useful when you want to designate complex types.
Someone shoot me if I stray too far here....

my Dog @array;

says the same as

my @array of Dog;

right?

I begin to fail to see where "is" will be needed. It's all so
complicated. It's getting dark....Help me, I've fallen and I can't get
up.....

Paul

unread,
Apr 17, 2003, 9:52:49 PM4/17/03
to Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Dave Whipp <dave_...@yahoo.com> wrote:
> --- Paul <ydb...@yahoo.com> wrote:
> > my Scalar $x = 1;
> >
> > Is that an implicit instantiation of an Int, or just an
> > assignment to a Scalar of a literal that doesn't get typed
> > until a context is required?
>
> Semantic error: literal '1' is numeric or string, not scalar. There's
> no auto-dereferencing of Scalars (unlike arrays and hashes).
>
> Instead try
>
> my Scalar $x = Scalar.new(1);
> or
> my Scalar $x = Scalar.new;
> $x.STORE(1);

Are you saying I *can't* say

my Scalar $x = 1; # ?!?!?

Ok, I think I disagree, but maybe that's the point of typing.

I could say

my $x = 1;

but since I explicitly typed the declaration to promise that only
Scalars would be stored in $x, maybe it requires that all values stored
in $x be explicitly typed as Scalar, so that I'd have to say

my Scalar $x = 1 as Scalar;

But I think that's bogus.

Damian Conway

unread,
Apr 17, 2003, 9:55:42 PM4/17/03
to perl6-l...@perl.org
>> my Oak $tree = Dog.new();
>> my Dog $spot = Oak.new();
>
>
> Why is that a problem?

Because the bark() method of a tree has *nothing* to do with the bark() method
of a dog. And is most unlikely to be interchangeable with it. They just happen
to be *named* with the same word.

Appearance (i.e. interface) doesn't make a one think substitutable for
another; genetics (i.e. inheritance) does.

Not that I'm saying Perl 6 shouldn't support interface polymorphism. It
should. But its only an alternative to, not a replacement for, inheritance.

Damian

Damian Conway

unread,
Apr 17, 2003, 10:13:48 PM4/17/03
to perl6-l...@perl.org
I mistyped:

> Appearance (i.e. interface) doesn't make a one think substitutable for
> another; genetics (i.e. inheritance) does.

Should have been:

Appearance (i.e. interface) doesn't make a one thing substitutable for


another; genetics (i.e. inheritance) does.

(though what I originally wrote was true too, I guess ;-)

Damian

Brent Dax

unread,
Apr 17, 2003, 10:42:12 PM4/17/03
to Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
Paul:
# Are you saying I *can't* say
#
# my Scalar $x = 1; # ?!?!?
#
# Ok, I think I disagree, but maybe that's the point of typing.

You may be missing the point. What I'm suggesting is that Scalar is
*only* a variable type, *not* a value type. So these two lines are very
similar:

my Scalar $x;
my Array $y;

In this system, a Scalar is a variable type whose value is an Object by
default. A Scalar doesn't contain a Scalar--it contains an Object.

In fact, a reference would probably just be a Scalar/Array/Hash/Code
used as a value. So what the above really means is "a Scalar containing
a Scalar", i.e. a reference to a scalar.

I'd probably structure the inheritance tree like this:

Object
Variable
Scalar
(tied scalars)
Array
(tied arrays)
Hash
(tied hashes)
Code
(code subtypes)
(tied codes (?))
Int
Num
Str
(etc.)
int #Or maybe a subclass of Int
num #As above
str #As above
(etc.) #As above
Pair
IO
File
Directory
Socket
(etc.)
List
Lazy
Range
(etc.)
Eager
(user types)

Note the lack of a Ref--Scalar, Array, Hash and Code are all subclasses
of Object, so they can be put anywhere an Object can be put.

Luke Palmer

unread,
Apr 18, 2003, 12:00:44 AM4/18/03
to dam...@conway.org, perl6-l...@perl.org

I certainly saw and considered this while pondering my proposal. My
fear is that since:

sub foo(Oak $tree) {...}

Is so easy and intuitive to write, that people will write that way and
write things unportably---creating the loathed typecasts and pedantic
strictness everywhere of the big J&C.[1]

I can see a place for inheritance compatibility, but I see it as
rather less common than interface compatibility... if we're trying to
abide by RFC 28, interface seems to fit somewhat better into the
Perl Way: Be Flexible and Do What I Mean.

I considered this notation:

sub foo($tree can Oak) {...}

Which seemed to be my favorite if inheritance were the default. OTOH,
there's:

sub foo($tree isa Oak) {...}

If interface is the default. I don't like that notation as much.
Whichever way we do it, both need to be supported declaratively, so
you can tell the type checker what to do on sub calls and things.

What I'm quite certain we I<don't> want at this point is to do it like
C++ and Java. We've all seen what kind of code that produces, and
while that's fine code in some people's eyes, it is clearly not Perl.
I'm not sure anybody wants it to be.

Type information should be helpful, catch bugs, make things go faster,
but not be maddeningly restrictive.

I've used C++'s name compatibility to my advantage before, at times
when interface compatibility wouldn't have worked. Empty classes, for
instance, would all be considered equivalent (and I use several
different Empty classes per program, usually).

Maybe what we need is somewhere to describe the compatibility other
than in the variable declaration. Like in the class, for instance:

class Lock is nonassimilatable {...} # :-P

So nothing could masquerade as a Lock by implementing its interface.
Or, the inverse:

class Lock is unique {...}

In that it wouldn't masquerade as anything else (except its actual
ancestors). This approach seems to be better than doing it at the
variable declaration level, in the few cases I can conger up in my
mind.

I'm struggling to find good examples of where the distinction would
matter---particularly where inheritance would be preferred. As of
now, however, I maintain that interface compatibility should be
default, as it's more Perlish.

Please, we need examples to flesh this out. Anyone?

Luke

[1] And although Java and C++ can be quite concise and accurate, it
requires too much thought to design your software that way. It would
be a beautiful world if everyone could think so clearly about design
as Stroustrup or Sutter or McKean... but average Joe-programmer
doesn't know that much about design. And he's the one most of the
language is for.[2]

[2] But we also want to encourage the good designers of the world, so
a loose, too-forgiving system is the left extreme. We need to extend
into up and down to find the right, er, top balance, I presume.

Luke Palmer

unread,
Apr 18, 2003, 1:04:06 AM4/18/03
to Austin_...@yahoo.com, dam...@conway.org, perl6-l...@perl.org
> > -----Original Message-----
> > From: Luke Palmer [mailto:fibo...@babylonia.flatirons.org]
> >
> > I'm struggling to find good examples of where the distinction would
> > matter---particularly where inheritance would be preferred. As of
> > now, however, I maintain that interface compatibility should be
> > default, as it's more Perlish.
> >
> > Please, we need examples to flesh this out. Anyone?
>
> Fundamentally, inheritance is used to implement Laziness. "Do what that
> other thing did, even unto the implementation details, with this one little
> change."
>
> class ShortQ isa Array {
> BEGIN {
> &.push.wrap(&.check_length);
> &.unshift.wrap(&.check_length);
> }
>
> method check_length {
> die "ShortQ would overflow (length = $.length)"
> unless $.length < .max_len;
> }
>
> has int $.max_len;
>
> method new(?$.max_len = 8) { SUPER::new; }
> }

Er, yeah. That's inheritance. But I'm talking about type checking.
When would you I<not> want to accept a type based on its interface,
only on its ancestry.

> > [2] But we also want to encourage the good designers of the world, so
> > a loose, too-forgiving system is the left extreme. We need to extend
> > into up and down to find the right, er, top balance, I presume.
>

> We've had *this* discussion before, under a slightly different guise. You're
> not quite there. What we want is a language where the bad programmers can
> get by, the great programmers can really shine, and everyone can learn from
> reading their code.

I don't remember the discussion. But yes, I wrote that first
footnote and realized that's not actually what we're going for. I
just wrote the second one to prevent people from thinking that I think
we're thinking of making a language where nobody does any thinking :)

Luke

... I think.

Austin Hastings

unread,
Apr 17, 2003, 8:55:56 PM4/17/03
to Damian Conway, perl6-l...@perl.org

Why is that a problem?

If you ask me, that strikes right at the strength of Luke's proposal: the
interface defines the type. You said that Dog had these methods, and Perl6
would say "If you want to live in a Dog-container, you have to have the
shape." Well, Oak has that shape.

You can take the argument down a little, and say "Well, you have to have
these methods with these sigs." And it does. Or "You have to have these
methods with these signatures and this return." And it can. But eventually,
you're going to have to suck it up, and admit that for all practical
purposes, there's no difference between an Oak (or a Dogwood, arf arf!) and
an Otterhound.

=Austin

Austin Hastings

unread,
Apr 17, 2003, 11:31:37 PM4/17/03
to Damian Conway, perl6-l...@perl.org

> From: Damian Conway [mailto:dam...@conway.org]

> >> my Oak $tree = Dog.new();
> >> my Dog $spot = Oak.new();
> >
> >
> > Why is that a problem?
>
> Because the bark() method of a tree has *nothing* to do with the
> bark() method of a dog. And is most unlikely to be interchangeable with
it.
> They just happen to be *named* with the same word.

Right. To me, that's a strong feature of Luke's scheme: You don't have to
"inherit" something to be able to do it.

Under the "you must inherit" scheme, we're essentially saying "We know more
than you about what you need." To me, that's questionable.

Under the interface scheme, we're saying "You know more than we do about
what you need." That's questionable, too :-) but it's more Perlish.

> Appearance (i.e. interface) doesn't make a one thing substitutable for


> another; genetics (i.e. inheritance) does.

There's no way that my mom's 8-track player and my computer's CD drive are
related to each other, and yet they have the same interface: insert, skip,
eject.

> Not that I'm saying Perl 6 shouldn't support interface polymorphism. It
> should. But its only an alternative to, not a replacement for,
> inheritance.

So when's A12 coming out? :-)

=Austin

Austin Hastings

unread,
Apr 18, 2003, 12:33:03 AM4/18/03
to Luke Palmer, dam...@conway.org, perl6-l...@perl.org

> -----Original Message-----
> From: Luke Palmer [mailto:fibo...@babylonia.flatirons.org]
>

> I'm struggling to find good examples of where the distinction would
> matter---particularly where inheritance would be preferred. As of
> now, however, I maintain that interface compatibility should be
> default, as it's more Perlish.
>
> Please, we need examples to flesh this out. Anyone?

Fundamentally, inheritance is used to implement Laziness. "Do what that


other thing did, even unto the implementation details, with this one little
change."

class ShortQ isa Array {
BEGIN {
&.push.wrap(&.check_length);
&.unshift.wrap(&.check_length);
}

method check_length {
die "ShortQ would overflow (length = $.length)"
unless $.length < .max_len;
}

has int $.max_len;

method new(?$.max_len = 8) { SUPER::new; }
}

> [2] But we also want to encourage the good designers of the world, so


> a loose, too-forgiving system is the left extreme. We need to extend
> into up and down to find the right, er, top balance, I presume.

We've had *this* discussion before, under a slightly different guise. You're


not quite there. What we want is a language where the bad programmers can
get by, the great programmers can really shine, and everyone can learn from
reading their code.

=Austin

Austin Hastings

unread,
Apr 18, 2003, 1:02:26 AM4/18/03
to Brent Dax, perl6-l...@perl.org

> -----Original Message-----
> From: Brent Dax [mailto:bren...@cpan.org]
> Paul:
> # Are you saying I *can't* say
> #
> # my Scalar $x = 1; # ?!?!?
> #
> # Ok, I think I disagree, but maybe that's the point of typing.
>
> You may be missing the point. What I'm suggesting is that Scalar is
> *only* a variable type, *not* a value type. So these two lines are very
> similar:
>
> my Scalar $x;
> my Array $y;

I think you and Paul are pretty close (his other message, not this one).

Let's recall the origin of species: In the dark ages of Perl, a $var was a
"scalar", and a %var was a "hash" and an @var was an "array". All the sigils
were indicative of "storage behavior" or (now) "variable type".

my $x is Scalar;
my @a is Array;
my %h is Hash;

Because "scalar" (read: singular) values were malleable, we could say:

$x = 1;
print $x;

and get a string as output where a number went in. Moreover, we can even do
the same thing with floats and what passes for boolean values. We can't do
it completely for references (Try: $x = 0; print $$x; See if it
segfaults... )

> In this system, a Scalar is a variable type whose value is an Object by
> default. A Scalar doesn't contain a Scalar--it contains an Object.

I think a Scalar is a variable type whose value is "singular". (Even a
single Junction, argh.)

> In fact, a reference would probably just be a Scalar/Array/Hash/Code
> used as a value. So what the above really means is "a Scalar containing
> a Scalar", i.e. a reference to a scalar.

Yeah, probably. Put that aside for a bit.

So Object == Reference.

But you left out "Lvalue" -- the compiler will probably generate constants
as rvalue scalars. <-|

So:

my @a is Array of Dog;
my @h is Array of Hash of Array of Dog;
my $s is Array of Dog;
sub PetStore returns Dog;

Per S6, the (final) C<of> and C<returns> keywords announce what may go in or
out. The rest is implementation details (aka variable traits). Predictably,
certain things "just won't work". C<my @a is Scalar;> shouldn't work. You
probably meant C<my @a returns Scalar;> which is not the most useful piece
of information. (Alternative: my @a returns Hash -- you're specifying
internal structure with Scalar/Hash, but not data type.)

The trouble seems to come from two things:

1- Without a specifier, $x is a "Scalar".
2- Scalars can do a whole lot of things polymorphically.

But if we keep in mind that C<my Scalar $a;> "does not mean what you think
it means", we should be okay. (Someone, maybe Dks, suggested that it meant
"my $a is Scalar returns ScalarReference", essentially. I think that's
right.

However, I think that the "triple threat" example:

my Scalar $s is Scalar returns|of Scalar;

is just wrong. Recall that C<returns> and C<of> are synonymous, and
s/Scalar/Array/:

"my Array @a is Array of Array;" =~ m :each /(Array)/;

The lexical variable @a is an Array($2) of Arrays($3) and if you deference
it, you'll find an Array($1).

The vartype ($1) means that you're going to wind up with a potential
auto-reference: $item = @a[1][2];

So what happens when we s/Array/Scalar/ again?

my Scalar $s is Scalar of Scalar;

Well, the eventual value type will be Scalar, which is kind of meaningless
(Scalar is an implementation detail, not an data type), so we're going to
get an auto-reference at the end.

First, however, when we access (is Scalar) the value, we're saying that
"It's just a scalar", but we knew that from the sigil. But this scalar is a
Scalar OF SCALARs, which means (I guess) that $s contains an auto-reference
to another variable, also a scalar. And that other variable, we know, will
give us a Scalar (auto-reference) when we ask for something.

my Scalar $s is Scalar of Scalar;

Consider, in 'C':

typedef union {
float s_float;
int s_int;
Str *s_str;
Code *s_code;
/* etc */
} Scalar;

000
Perl: my $s;
'C' : Scalar s;

010
Perl: my $s is Scalar; # Redundant with '$' in $s.
'C' : Scalar s;

100, 001
Perl: my Scalar $s; # Returns a Scalar, which is to say a ref
Perl: my $s of Scalar;
'C' : Scalar * s;

110
Perl: my Scalar $s is Scalar; # First Scalar means ref, second means $
'C' : Scalar * s;

101
Perl: my Scalar $s of Scalar; # Should be warning, I guess. It's redundant,
# unless you meant that $s was a ScalarScalar - a ref to a ref.
'C' : Scalar * s; /* And a warning */
'C' : Scalar **s; /* Unless it's a ScalarScalar */

011
Perl: my $s is Scalar of Scalar; # Redundant, plus a Ref
'C' : Scalar * s;

111
Perl: my Scalar $s is Scalar of Scalar; # Degenerates to 101
'C' : Scalar * s; /* And a warning */
'C' : Scalar **s; /* Unless it's a ScalarScalar */

=Austin

Dan Sugalski

unread,
Apr 18, 2003, 10:05:56 AM4/18/03
to Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 4:08 PM -0700 4/17/03, Brent Dax wrote:
>Michael Lazzaro:
># In other words, what's this shorthand for:
>#
># my $x;
>#
># does it mean
>#
># my untyped $x;
># my scalar $x;
># my Scalar $x;
>
>I would argue that it's
>
> my Object $x;
>
>This has actually been bugging me for a long time: isn't Scalar a
>container that holds an Object of some sort?

No.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Dan Sugalski

unread,
Apr 18, 2003, 10:14:33 AM4/18/03
to perl6-l...@perl.org
At 10:24 AM +1000 4/18/03, Damian Conway wrote:
>Luke Palmer wrote:
>
>>Huh? You don't have to check it explicitly. Cat doesn't support the
>>bark() method, so it can't be used as a Dog. And the type system will
>>see that. End of story.
>
>There are, however, problems with an interface approach.

Depends on what you're checking, I suppose. There are other ways to
determine compatibility (such as with real
interfaces/mixins/protocols) though it's tough to do right when
inspecting single method calls.

Dan Sugalski

unread,
Apr 18, 2003, 10:29:44 AM4/18/03
to Brent Dax, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 7:42 PM -0700 4/17/03, Brent Dax wrote:
>I'd probably structure the inheritance tree like this:

This line, I think, embodies all the fundamental problems cropping up.

There *is* no tree. (There is a spoon, however it's being used in
defense of The City, so it's not available and thus not relevant)
What there are are a number of behavior and data sets, which can be
mixed and matched as necessary. Objects have a set of these, scalars
another, and hashes still others. Trying to unify everything is, in
practical terms, impractical.

Paul

unread,
Apr 18, 2003, 10:47:45 AM4/18/03
to Austin_...@yahoo.com, Brent Dax, perl6-l...@perl.org

--- Austin Hastings <ahas...@worldnet.att.net> wrote:
> > From: Brent Dax [mailto:bren...@cpan.org]
> > Paul:
> > # Are you saying I *can't* say
> > #
> > # my Scalar $x = 1; # ?!?!?
> > #
> > # Ok, I think I disagree, but maybe that's the point of typing.
> >
> > You may be missing the point. What I'm suggesting is that Scalar
> > is *only* a variable type, *not* a value type. So these two lines
> > are very similar:
> >
> > my Scalar $x;
> > my Array $y;
>
> I think you and Paul are pretty close (his other message, not this
> one).

lol.... agreed. :)

> Let's recall the origin of species: In the dark ages of Perl,
> a $var was a "scalar", and a %var was a "hash" and an @var was
> an "array". All the sigils were indicative of "storage behavior"
> or (now) "variable type".
>
> my $x is Scalar;
> my @a is Array;
> my %h is Hash;

And that's what we need to keep in mind. $x just means "there's only
one thing here", though we need to be able to predict it's behavior.

> Because "scalar" (read: singular) values were malleable,
> we could say:
>
> $x = 1;
> print $x;
>
> and get a string as output where a number went in. Moreover,
> we can even do the same thing with floats and what passes for
> boolean values. We can't do it completely for references
> (Try: $x = 0; print $$x; See if it segfaults... )

Well, mine didn't, but it didn't do anything useful, either. :)

> > In this system, a Scalar is a variable type whose value
> > is an Object by default. A Scalar doesn't contain a
> > Scalar--it contains an Object.
>
> I think a Scalar is a variable type whose value is "singular".
> (Even a single Junction, argh.)

Exactly, though I'm not sure what that gains us yet....

> > In fact, a reference would probably just be a
> > Scalar/Array/Hash/Code used as a value. So what the above
> > really means is "a Scalar containing a Scalar", i.e. a
> > reference to a scalar.
>
> Yeah, probably. Put that aside for a bit.

ok....but that *does* apply to the point. One is the variable, one is
the value. Putting it aside, now....

> > [snipped block of types]


> > Note the lack of a Ref--Scalar, Array, Hash and Code are all
> > subclasses of Object, so they can be put anywhere an Object
> > can be put.
>
> So Object == Reference.

hmm... I think I follow that.

> But you left out "Lvalue" -- the compiler will probably generate
> constants as rvalue scalars. <-|

Was that "<-|" something you typed, or an artifact of transmission?

> So:
>
> my @a is Array of Dog;
> my @h is Array of Hash of Array of Dog;
> my $s is Array of Dog;
> sub PetStore returns Dog;
>
> Per S6, the (final) C<of> and C<returns> keywords announce what
> may go in or out. The rest is implementation details (aka variable
> traits).

Thanks -- I knew that, but this section makes a good refresher, which I
was needing.

> Predictably, certain things "just won't work". C<my @a is Scalar;>
> shouldn't work.

ok --
my @a of Scalar; # redundant
is just redundant, since Scalar is the default anyway, but it's ok.
my @a is Scalar; # contradictory
really doesn't make sense, because @a means Array, not Scalar. Yes?

> You probably meant C<my @a returns Scalar;> which is not the most
> useful piece of information.

lol -- redundant. :)

> (Alternative: my @a returns Hash -- you're specifying
> internal structure with Scalar/Hash, but not data type.)

Which means that you could say
my %h = @a[0];
or
my $y = @a[0]{$z};

So far so good.



> The trouble seems to come from two things:
>
> 1- Without a specifier, $x is a "Scalar".
> 2- Scalars can do a whole lot of things polymorphically.

Agreed.



> But if we keep in mind that C<my Scalar $a;> "does not mean
> what you think it means", we should be okay. (Someone, maybe
> Dks, suggested that it meant
> "my $a is Scalar returns ScalarReference", essentially.
> I think that's right.

I could see that... basically by typing it you're saying "this is going
to hold another variable of this type" rather than the more obvious
"this is going to hold something of the type it's sigil already *said*
it will hold".

Which means you could say

my $y = "foo";
my Scalar $x = $y; # \$y not needed?
print $$x; # "foo";

and by extrapolation,

my Array $aref;
$aref[0] = "bar";

and maybe even

$x = $aref; # again, not \$aref ?
print $$x[0]; # prints "bar" ?



> However, I think that the "triple threat" example:
>
> my Scalar $s is Scalar returns|of Scalar;
>
> is just wrong.

LOL!!! It was meant to be. :)
At least, I *hoped* the redundancy would be a no-no!

> Recall that C<returns> and C<of> are synonymous, and
> s/Scalar/Array/:
>
> "my Array @a is Array of Array;" =~ m :each /(Array)/;
>
> The lexical variable @a is an Array($2) of Arrays($3) and if you
> deference it, you'll find an Array($1).

Ok, I just fell off.
Lemme see if I can catch up again.

I *can* in fact say

my @a is Array; # redundant with @ sigil?
my @a of Array; # means @a is 2-dimensional?
my Array @a; # means each element holds an Array ref?
# (in effect, @a is 2D?)
so
my Array @a of Array; # means it's 3D?
So that I'm saying with the @ that this is an array-type container,
with the of that each bottom-level element returns an array reference,
and with the Array predeclarator that the type of each top-level
element is Array? And since each "bottom-level" element is an array
ref, there's actually another level we can reach?

I read that as making the "is Array" completely redundant on arrays,
and completely contradictory on hashes and Scalars. That means

my $s is Scalar;

is also pointless and redundant, but that's not what "is" is for, is
it? :)

The "is" operator declares something *other* than the obvious type.

my $spot is Dog;

says that the variable $spot *IS* a Dog object; the container itself is
intended for Dog values, and can't accomodate other, inappropriate
kinds of data. Multiple "is"ops in a chain are just a junction, so that

my $spot is Pet is Dog;

is equivelent to saying

my $spot is Pet|Dog;

I think I'm getting there. There are still some significant issues I'm
missing, but it's clearing up again. :)

> The vartype ($1) means that you're going to wind up with a potential
> auto-reference: $item = @a[1][2];

Like I said above:
my Scalar $x = $y; # doesn't need \$y!



> So what happens when we s/Array/Scalar/ again?
>
> my Scalar $s is Scalar of Scalar;
>
> Well, the eventual value type will be Scalar, which is kind of
> meaningless (Scalar is an implementation detail, not an data type),
> so we're going to get an auto-reference at the end.

[stumbling]
Um, you mean that since it would be pointless to *say* that the $var
was a Scalar, it'll do something useful and make it auto-ref? :)

> First, however, when we access (is Scalar) the value, we're saying
> that "It's just a scalar", but we knew that from the sigil. But this
> scalar is a Scalar OF SCALARs, which means (I guess) that $s contains
> an auto-reference to another variable, also a scalar. And that other
> variable, we know, will give us a Scalar (auto-reference) when we ask
> for something.

So....

my $x = "foo";
my Scalar $rrs of Scalar = $x;
print $$$rrs; # prints "foo"?

Ok, if I got *THAT* right, I may really be getting it.
If you're right about the auto-ref'ing, lol....

> my Scalar $s is Scalar of Scalar;
>
> Consider, in 'C':
>
> typedef union {
> float s_float;
> int s_int;
> Str *s_str;
> Code *s_code;
> /* etc */
> } Scalar;

Ok, I can do this. :)

> 000
> Perl: my $s;
> 'C' : Scalar s;

Clear.



> 010
> Perl: my $s is Scalar; # Redundant with '$' in $s.
> 'C' : Scalar s;

Agreed. But if

typedef {
char attr[SIZE];
/* etc */
} Dog;

then

Perl: my $spot is Dog;
'C': Dog spot;

Yes? The redundancy is only because we've declared what the $ sigil
already said.



> 100, 001
> Perl: my Scalar $s; # Returns a Scalar, which is to say a ref
> Perl: my $s of Scalar;
> 'C' : Scalar * s;

Alright. Auto-ref ~~ pointer to :)



> 110
> Perl: my Scalar $s is Scalar; # First Scalar means ref,

# second means $
> 'C' : Scalar * s;

Agreed.

> 101
> Perl: my Scalar $s of Scalar; # Should be warning, I guess.

# It's redundant, unless you meant
# that $s was a ScalarScalar -
# a ref to a ref.


> 'C' : Scalar * s; /* And a warning */
> 'C' : Scalar **s; /* Unless it's a ScalarScalar */

Agreed. But if we're going to assume auto-referencing, I think it
should carry through to subsequent layers. It's consistent, and
possibly useful, and if it isn't what you meant, it *might* just
correct itself contextually.

> 011
> Perl: my $s is Scalar of Scalar; # Redundant, plus a Ref
> 'C' : Scalar * s;

Yes.



> 111
> Perl: my Scalar $s is Scalar of Scalar; # Degenerates to 101
> 'C' : Scalar * s; /* And a warning */
> 'C' : Scalar **s; /* Unless it's a ScalarScalar */

You're a smart man.
Thanks -- I feel much better now, lol....

Paul

unread,
Apr 18, 2003, 10:50:53 AM4/18/03
to Dan Sugalski, Brent Dax, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Dan Sugalski <d...@sidhe.org> wrote:
> At 7:42 PM -0700 4/17/03, Brent Dax wrote:
> >I'd probably structure the inheritance tree like this:
>
> This line, I think, embodies all the fundamental problems cropping
> up.

Mm?



> There *is* no tree. (There is a spoon, however it's being used in
> defense of The City, so it's not available and thus not relevant)

lol....

> What there are are a number of behavior and data sets, which can be
> mixed and matched as necessary. Objects have a set of these, scalars
> another, and hashes still others. Trying to unify everything is, in
> practical terms, impractical.

Ok -- so

my $spot is Pet is Dog;

Just invokes ("inherits from"?) the definitions of Pet and Dog?
Or did I just skip threads? :)

Dan Sugalski

unread,
Apr 18, 2003, 11:41:13 AM4/18/03
to Hod...@writeme.com, Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 7:50 AM -0700 4/18/03, Paul wrote:
>--- Dan Sugalski <d...@sidhe.org> wrote:
>> At 7:42 PM -0700 4/17/03, Brent Dax wrote:
>> >I'd probably structure the inheritance tree like this:
>>
>> This line, I think, embodies all the fundamental problems cropping
>> up.
>
>Mm?

Everyone wants to treat this all as a big unified object/type tree.
It isn't. No tree, no base class, no unification.

> > What there are are a number of behavior and data sets, which can be
>> mixed and matched as necessary. Objects have a set of these, scalars
>> another, and hashes still others. Trying to unify everything is, in
>> practical terms, impractical.
>
>Ok -- so
>
> my $spot is Pet is Dog;
>
>Just invokes ("inherits from"?) the definitions of Pet and Dog?

Maybe (well, I doubt it), though you'd be creating a new type on the
fly that way, and I think it's probably not the right way to do it.

>Or did I just skip threads? :)

I have no idea if you skipped threads--I've been skipping most of the
fairly impressive volume of mail on this.

Brent Dax

unread,
Apr 18, 2003, 12:07:46 PM4/18/03
to Dan Sugalski, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
Dan Sugalski:
# At 7:42 PM -0700 4/17/03, Brent Dax wrote:
# >I'd probably structure the inheritance tree like this:
#
# This line, I think, embodies all the fundamental problems cropping up.
#
# There *is* no tree.
...
# What there are are a number of behavior and data sets, which can be
# mixed and matched as necessary. Objects have a set of these, scalars
# another, and hashes still others. Trying to unify everything is, in
# practical terms, impractical.

I know they won't be unified at the implementation level, because PMCs
have a different inheritance tree than Perl-level objects. But why
can't we make it *look* like they do at the Perl level?

(reordered)
# (There is a spoon, however it's being used in
# defense of The City, so it's not available and thus not relevant)

Perhaps you just need to free your mind to see what I'm talking about?
(OK, that was lame. No more Matrix references for Brent.)

Dan Sugalski

unread,
Apr 18, 2003, 11:56:29 AM4/18/03
to Brent Dax, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 9:07 AM -0700 4/18/03, Brent Dax wrote:
>Dan Sugalski:
># At 7:42 PM -0700 4/17/03, Brent Dax wrote:
># >I'd probably structure the inheritance tree like this:
>#
># This line, I think, embodies all the fundamental problems cropping up.
>#
># There *is* no tree.
>...
># What there are are a number of behavior and data sets, which can be
># mixed and matched as necessary. Objects have a set of these, scalars
># another, and hashes still others. Trying to unify everything is, in
># practical terms, impractical.
>
>I know they won't be unified at the implementation level, because PMCs
>have a different inheritance tree than Perl-level objects. But why
>can't we make it *look* like they do at the Perl level?

Why should we make them look unified at the perl level? They aren't
unified, either in implementation or conception, so why take the
hammer and saw to them to try and wedge them into some "nice" unified
framework.

A hammer isn't a rutabaga which isn't the masculine third person
singular pluperfect variant of the verb "to frob". Seems actively
counterproductive to try and make them all the same thing.

Brent Dax

unread,
Apr 18, 2003, 12:19:54 PM4/18/03
to Dan Sugalski, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
Dan Sugalski:
# Why should we make them look unified at the perl level? They aren't
# unified, either in implementation or conception, so why take the
# hammer and saw to them to try and wedge them into some "nice" unified
# framework.

They *are* unified in conception. An Int or Str is conceptually no
different from a Chair--they're all Things (Objects) you can put
somewhere and do stuff with.

# A hammer isn't a rutabaga

Both a hammer and a rutabaga are Things (or Objects).

# which isn't the masculine third person
# singular pluperfect variant of the verb "to frob".

And all three are some sort of GrammaticalConstruct.

# Seems actively
# counterproductive to try and make them all the same thing.

Even if it buys us conceptual simplicity?

Paul

unread,
Apr 18, 2003, 12:12:05 PM4/18/03
to Dan Sugalski, Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Dan Sugalski <d...@sidhe.org> wrote:
> At 7:50 AM -0700 4/18/03, Paul wrote:
> >--- Dan Sugalski <d...@sidhe.org> wrote:
> >> At 7:42 PM -0700 4/17/03, Brent Dax wrote:
> >> >I'd probably structure the inheritance tree like this:
> >>
> >> This line, I think, embodies all the fundamental problems
> >> cropping up.
> >
> >Mm?
>
> Everyone wants to treat this all as a big unified object/type tree.
> It isn't. No tree, no base class, no unification.

Simpler is better. I just want to make sure I *get* it. :)

> >> What there are are a number of behavior and data sets, which can
> >> be mixed and matched as necessary. Objects have a set of these,
> >> scalars another, and hashes still others. Trying to unify
> >> everything is, in practical terms, impractical.
> >
> >Ok -- so
> >
> > my $spot is Pet is Dog;
> >
> >Just invokes ("inherits from"?) the definitions of Pet and Dog?
>
> Maybe (well, I doubt it), though you'd be creating a new type on the
> fly that way, and I think it's probably not the right way to do it.

Ok, that's good info.
I'd rather do it the right way (thought I'd rather avoid it entirely as
often as possible).
What would the right way be?

> >Or did I just skip threads? :)
>
> I have no idea if you skipped threads--I've been skipping most of the
> fairly impressive volume of mail on this.

lol -- you're apparently not the only one. We've issued several please
for clarification from the "design team", though I expect they have
enough to do already, lol.... Likewise, a lot of this will probably be
cleared up with later apocolypsi, but we're hoping that hashing through
it will help them clarify where the hot spots are.

Or at least, *I* am. :)

Paul

unread,
Apr 18, 2003, 12:20:05 PM4/18/03
to Dan Sugalski, Brent Dax, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org

--- Dan Sugalski <d...@sidhe.org> wrote:
> At 9:07 AM -0700 4/18/03, Brent Dax wrote:
> >Dan Sugalski:
> ># At 7:42 PM -0700 4/17/03, Brent Dax wrote:
> ># >I'd probably structure the inheritance tree like this:
> >#
> ># This line, I think, embodies all the fundamental problems cropping
> ># up.

> >#
> ># There *is* no tree.
> >...
> ># What there are are a number of behavior and data sets, which can
> ># be mixed and matched as necessary. Objects have a set of these,
> ># scalars another, and hashes still others. Trying to unify
> ># everything is, in practical terms, impractical.

> >
> > I know they won't be unified at the implementation level, because
> > PMCs have a different inheritance tree than Perl-level objects.
> > But why can't we make it *look* like they do at the Perl level?
>
> Why should we make them look unified at the perl level? They aren't
> unified, either in implementation or conception, so why take the
> hammer and saw to them to try and wedge them into some "nice" unified
> framework.

Only because it might make the language more intuitive and easier to
learn. Personally, however, I'm less interested in trying to shoehorn
the language into a pretty box than I am in trying to formulate a
congitive box that fits the design of the language. That requires that
I at least know how the pieces will behave in a given circumstance.

> A hammer isn't a rutabaga which isn't the masculine third person
> singular pluperfect variant of the verb "to frob". Seems actively
> counterproductive to try and make them all the same thing.

Unequivocably agreed. But they *do* all get built up from the same
figurative molecules, and a lot of them use the same DNA. Others are
things that are only used by things with that DNA, even if they don't
got none themselves. :)

Please don't *make* anything do anything that is counterproductive to
the language design. Likewise, please don't let my SCREAMINGLY
HORRENDOUS IMPATIENCE (lol) alter the course of the design team. I'd
rather wait another six years and have the language done *right* than
get a crappy knock-off in six months -- that way lies madness, and the
realm of the Evil Empire from which emanates the sound of crashing
windows.....

I just want to contribute. :)

Dan Sugalski

unread,
Apr 18, 2003, 12:25:37 PM4/18/03
to Brent Dax, Hod...@writeme.com, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 9:19 AM -0700 4/18/03, Brent Dax wrote:
>Dan Sugalski:

># Seems actively


># counterproductive to try and make them all the same thing.
>
>Even if it buys us conceptual simplicity?

Especially if it buys you conceptual simplicity, since it's a fake simplicity.

When the only analogy you have is a hammer, all you leave in your
wake is a broken mess. "Objects" aren't the only, best, or universal
analogy.

John Williams

unread,
Apr 18, 2003, 12:32:32 PM4/18/03
to Dan Sugalski, perl6-l...@perl.org
On Fri, 18 Apr 2003, Dan Sugalski wrote:
> >This has actually been bugging me for a long time: isn't Scalar a
> >container that holds an Object of some sort?
>
> No.

OK, I give up. What's a Scalar?

Dan Sugalski

unread,
Apr 18, 2003, 12:35:41 PM4/18/03
to Hod...@writeme.com, Brent Dax, Michael Lazzaro, Dave Whipp, perl6-l...@perl.org
At 9:12 AM -0700 4/18/03, Paul wrote:
>--- Dan Sugalski <d...@sidhe.org> wrote:
>> At 7:50 AM -0700 4/18/03, Paul wrote:
>> >--- Dan Sugalski <d...@sidhe.org> wrote:
>> >> At 7:42 PM -0700 4/17/03, Brent Dax wrote:
>> >> >I'd probably structure the inheritance tree like this:
>> >>
>> >> This line, I think, embodies all the fundamental problems
>> >> cropping up.
>> >
>> >Mm?
>>
>> Everyone wants to treat this all as a big unified object/type tree.
>> It isn't. No tree, no base class, no unification.
>
>Simpler is better.

Nonsense. If you believed that you'd be living on a diet of plain
gruel and water, in an apartment with white walls, almost no
furniture, and working on a VT100 terminal. I'd lay good odds that
you aren't.

> > >Or did I just skip threads? :)
>>
>> I have no idea if you skipped threads--I've been skipping most of the
>> fairly impressive volume of mail on this.
>
>lol -- you're apparently not the only one. We've issued several please
>for clarification from the "design team", though I expect they have
>enough to do already,

Erm... I *am* part of the design team. And, since Simon is absent,
apparently the cantankerous voice of reality as well.

Dan Sugalski

unread,
Apr 18, 2003, 12:37:42 PM4/18/03
to John Williams, perl6-l...@perl.org

It's just a scalar. It can hold any single thing. No caps, no forced
behaviour requirements, no Vast Encompassing Ideology. It's just a
single thing.

Michael Lazzaro

unread,
Apr 18, 2003, 12:53:34 PM4/18/03
to perl6-l...@perl.org

I propose we take a brief breather on this thread; I think we're
getting _way_ ahead of things, especially with all the A12 theorizing,
and splitting off into a bunch of other arguments.

I'm working on a summary post of what we KNOW, or at least are darn
sure of, re: scalars, typing, etc. Give me an hour or so, please.

MikeL

It is loading more messages.
0 new messages