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

Perl 6's &bless is (seriously) broken

7 views
Skip to first unread message

Stevan Little

unread,
Jan 19, 2006, 3:45:53 PM1/19/06
to perl6-language@perl.org List
Hello,

I am forking this off the "Perl 6 OO and bless" thread since that
seems to have gotten bogged down in what it all means to Perl 5
interoperability. This was not really my intent with the original
thread, but I think it is still a fruitful discussion so I will re-
make my original point here with more detail.

First I need to establish a few things on which my argument rests.

So, S02 says that Perl 6 is an OO engine. Which means that a hash is
not a literal "thing" but an instance of the class ^Hash. This means
that a hash now has methods which can be called on it, and inherits
from ^Object.

Because @Larry does not want the OO-ness of the language to get in
the way of doing ones job, all the methods of ^Hash are either
transformed into pseudo-built-in-functions using macros (see the Hash/
delete/UnaryForm part of S29), or would be aliased as multi-subs
which dispatch using MMD.

Take this (very simplified) pseduo-code for &exists:

method Hash::exists (^Hash %h: Any $label) return Bool {
%h{$label} ?? bool::true !! bool::false
}

And lets assume that a macro has been written to make it callable in
the built-in function style which will transform this:

exists %h{'foo'}

Into this:

%h.exists('foo');

Now, what happens when we bless a hash.

class Foo {
method new ($class: %params) {
$class.bless(%params);
}
method bar ($self:) { ... }
}

The result of Foo.new is an instance of ^Foo. In Perl 5, the hash
would be tagged with the package name it was blessed into, but it
would still be a hash reference, only now you could also call methods
on it. This *won't* work the same in Perl 6 though. This is because,
what is blessed is not a literal "hash", but an instance of ^Hash. If
we follow the Perl 5 logic, then we can now call methods on this
blessed hash, but we cannot use the hash built-in functions since
they are just macro transformations into method calls. Take this code
example:

my $foo = Foo.new({ one => 1, two => 2 });
exists $foo{'one'}; # this will not work

The reason this the above code will not work is because "exists $foo
{'one'}" will be transformed by the macro to "$foo.exists('one')",
which will fail since no &Foo::exists exists. Even if we tried to do
this (and assuming the macro would DWIM):

Hash::exists $foo{'one'};

This would fail anyway since Hash::exists is expecting a ^Hash
instance as it's invocant arg, and not a ^Foo instance, so it would
fail on the parameter/argument type check.

I think this is a deep problem with how &bless works, how the
container types work, and maybe even how our MMD system works. I
think we need to have a well reasoned solution to this which is
devoid of any magic hand waving.

Thanks,

Stevan

Chromatic

unread,
Jan 19, 2006, 4:16:32 PM1/19/06
to perl6-l...@perl.org, Rob Kinyon
On Thursday 19 January 2006 13:10, Rob Kinyon wrote:

> &bless was a brilliant idea for Perl5. It's wrong for Perl6.

Perhaps you meant to write "Tagging a reference with a package name worked for
Perl 5. It's wrong for Perl 6."

Certainly I can agree with that.

Yet this whole discussion feels like the argument that there should be no
system() operator in Perl 6 because the system() operator in Perl 5 returns
the wrong value.

-- c

Juerd

unread,
Jan 19, 2006, 4:18:35 PM1/19/06
to perl6-l...@perl.org
Rob Kinyon skribis 2006-01-19 16:10 (-0500):
> There are no references in Perl6.

When you said that one can't use OO in Perl 5, I had something to say
because it's a recurring subject.

I have to admit, though, that I've never seen this statement, or
anything implying it. It's entirely new to me.

Is your Perl the same as that of other people on this list? :)

> In fact, the only think you have in Perl6 is objects, so why do we
> need to take something that isn't an object (which doesn't exist)

Could you live with @foo being an array, and @foo in scalar context
returning a reference to that array? And with arrays being interfaces to
underlying Arrays, which are objects, which makes arrays non-objects
that can be used *as* objects?

Perl still has non-object types. They may represent objects internally,
but they work differently from what we've historically been calling
objects. Especially in assignment, the differences are huge, because an
object is considered a reference, while "real" scalars, arrays and
hashes evaluate to (a list of) their values, or a useful representation
(like the number of elements) when used in non-OO fashion.

> &bless was a brilliant idea for Perl5. It's wrong for Perl6.

I think it's needed to be able to convert Perl 5 code
semi-automatically.

But you have probably thought about this more than I, so I'll ask you:
what's the alternative?


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Juerd

unread,
Jan 19, 2006, 4:10:24 PM1/19/06
to perl6-l...@perl.org
Stevan Little skribis 2006-01-19 15:45 (-0500):

> class Foo {
> method new ($class: %params) {
> $class.bless(%params);

Wouldn't that be %params.bless($class), or more directly,
%params.blessed = $class?

> This *won't* work the same in Perl 6 though. This is because,
> what is blessed is not a literal "hash", but an instance of ^Hash.

The mistake here is that Foo doesn't "does Hash", I think.

Sure, in Perl 5, you could have different kinds of references as
instances of the same class. But I don't recall ever having encountered
that.

Rob Kinyon

unread,
Jan 19, 2006, 4:10:23 PM1/19/06
to Stevan Little, perl6-language@perl.org List
To further extend Steve's argument (which I wholeheartedly agree
with), I wanted to point out one thing: &bless has nothing to do with
OO programming as conceived of in Perl6. It does one thing and only
one thing:
- tag a reference with a package name.

This is used in a few places:
- to determine what package the 'meth' function lives in when the
syntax $foo->meth( @parms ) is encountered
- to determine what ref() should return

There are no references in Perl6. In fact, the only think you have in


Perl6 is objects, so why do we need to take something that isn't an

object (which doesn't exist) and do anything to it, let alone tag it
with a package name? Packages don't have anything to do with the class
system. If you want to change the behavior of something at runtime,
you can do so through .meta, roles, mixins, traits, and the like.

&bless was a brilliant idea for Perl5. It's wrong for Perl6.

Rob

Juerd

unread,
Jan 19, 2006, 4:21:01 PM1/19/06
to perl6-l...@perl.org
Juerd skribis 2006-01-19 22:18 (+0100):

> Could you live with @foo being an array, and @foo in scalar context
> returning a reference to that array? And with arrays being interfaces to
> underlying Arrays, which are objects, which makes arrays non-objects
> that can be used *as* objects?

This turns "everything is an object" into "everything can be used with
OO syntax", which I think is more true.

Alternatively and simultaneously, "everything represents an object".

Stevan Little

unread,
Jan 19, 2006, 4:51:47 PM1/19/06
to Rob Kinyon, perl6-language@perl.org List

On Jan 19, 2006, at 4:10 PM, Rob Kinyon wrote:
> Packages don't have anything to do with the class
> system.

Actually ^Class.isa(^Package) ;)

Stevan

Stevan Little

unread,
Jan 19, 2006, 4:59:17 PM1/19/06
to Juerd, perl6-l...@perl.org
Juerd,

On Jan 19, 2006, at 4:10 PM, Juerd wrote:
> Stevan Little skribis 2006-01-19 15:45 (-0500):
>> class Foo {
>> method new ($class: %params) {
>> $class.bless(%params);
>
> Wouldn't that be %params.bless($class), or more directly,
> %params.blessed = $class?

Nope, according to S12:

As in Perl 5, a constructor is any routine that calls bless. Unlike
in Perl 5, you call it as a method on the class, passing the
candidate
as the first argument.

It then does on to give this code example:

$object = $class.bless({k1 => $v1, k2 => $v2, ...});

In fact all example using &bless us it as a method of the $class.

>> This *won't* work the same in Perl 6 though. This is because,
>> what is blessed is not a literal "hash", but an instance of ^Hash.
>
> The mistake here is that Foo doesn't "does Hash", I think.

But we cannot automagically inject a role into a class, for a number
of reasons.

1) thats just plain evil
2) what if the role conflicts with other roles being does-ed by Foo?
Debugging hell there.
3) What if Foo wants to have a .keys, .value, .exists, etc? Do they
shadow the Hash version? What if Foo.keys is implemented using
Hash.keys? Many issues abound here.

> Sure, in Perl 5, you could have different kinds of references as
> instances of the same class. But I don't recall ever having
> encountered
> that.

bless([] => 'Foo');
bless({} => 'Foo');
bless(\*Foo => 'Foo');
bless(\(my $var) => 'Foo');

It silly, but you could do it. However this is not really related to
my point. The issue I am describing looks more like this in perl 5:

package Hash;
sub new { ... }
sub keys { ... }
sub values { ... }
sub exists { ... }

package Foo;

sub new {
my ($class, $hash) = @_;
($hash->isa(Hash)) || die "hash needs to be an instance of Hash";
bless($hash, $class);
}

Why would you ever want to do such a think in Perl 5? So why would
that be how &bless works in Perl 6?

Stevan

Stevan Little

unread,
Jan 19, 2006, 5:06:26 PM1/19/06
to Juerd, perl6-l...@perl.org
Juerd,

On Jan 19, 2006, at 4:21 PM, Juerd wrote:
> Juerd skribis 2006-01-19 22:18 (+0100):
>> Could you live with @foo being an array, and @foo in scalar context
>> returning a reference to that array? And with arrays being
>> interfaces to
>> underlying Arrays, which are objects, which makes arrays non-objects
>> that can be used *as* objects?
>
> This turns "everything is an object" into "everything can be used with
> OO syntax", which I think is more true
>

> Alternatively and simultaneously, "everything represents an object".

Well, if "everything is NOT an object", then the synopsis need to
reflect this. I was under the impression that everything was an
object, some of that "object-ness" is more hidden in some than
others, but it does not mean they are not still objects.

My point though was not to debate OO theory, but to reconcile a
problem in the Synopsis and it's description/usage of &bless.
Currently it is broken, and we need to fix it.

One fix, yes, is to say "arrays and hashes are not objects, they are
literals as in perl 5". Personally I am not sure that is a good
approach, and seems to contradict more of the Synopsis then it agrees
with.

Stevan

Juerd

unread,
Jan 19, 2006, 5:07:49 PM1/19/06
to perl6-l...@perl.org
Stevan Little skribis 2006-01-19 16:59 (-0500):

> But we cannot automagically inject a role into a class, for a number
> of reasons.
> 1) thats just plain evil

But then, so is bless, so the two can play along.

> 2) what if the role conflicts with other roles being does-ed by Foo?
> Debugging hell there.

Very good point.

> 3) What if Foo wants to have a .keys, .value, .exists, etc? Do they
> shadow the Hash version? What if Foo.keys is implemented using
> Hash.keys? Many issues abound here.

Even better point.

> >Sure, in Perl 5, you could have different kinds of references as
> >instances of the same class. But I don't recall ever having
> >encountered
> >that.
> bless([] => 'Foo');
> bless({} => 'Foo');
> bless(\*Foo => 'Foo');
> bless(\(my $var) => 'Foo');

Okay, now I did encounter it...

Jonathan Scott Duff

unread,
Jan 19, 2006, 5:19:22 PM1/19/06
to Juerd, perl6-l...@perl.org
On Thu, Jan 19, 2006 at 11:07:49PM +0100, Juerd wrote:
> Stevan Little skribis 2006-01-19 16:59 (-0500):
> > 2) what if the role conflicts with other roles being does-ed by Foo?
> > Debugging hell there.
>
> Very good point.

Aren't role conflicts resolved at composition time (possibly by
failure)? That doesn't sound like debugging hell to me, but rather
clear indication of a problem and the location of that problem.

-Scott
--
Jonathan Scott Duff
du...@pobox.com

Juerd

unread,
Jan 19, 2006, 5:09:53 PM1/19/06
to perl6-l...@perl.org
Stevan Little skribis 2006-01-19 17:06 (-0500):

> >This turns "everything is an object" into "everything can be used with
> >OO syntax", which I think is more true
> >Alternatively and simultaneously, "everything represents an object".
> Well, if "everything is NOT an object", then the synopsis need to
> reflect this.

I was more thinking along the lines of "NOT everything is an object",
"but some things are".

Stevan Little

unread,
Jan 19, 2006, 5:21:11 PM1/19/06
to Juerd, perl6-l...@perl.org

On Jan 19, 2006, at 5:09 PM, Juerd wrote:
> Stevan Little skribis 2006-01-19 17:06 (-0500):
>>> This turns "everything is an object" into "everything can be used
>>> with
>>> OO syntax", which I think is more true
>>> Alternatively and simultaneously, "everything represents an object".
>> Well, if "everything is NOT an object", then the synopsis need to
>> reflect this.
>
> I was more thinking along the lines of "NOT everything is an object",
> "but some things are".

<sarcasm>
Hmm, maybe we can add an "Object context" then. It would allow an
something to be an object only when it is convienent for it to be so. ;)
</sarcasm>

Stevan

Stevan Little

unread,
Jan 19, 2006, 5:29:50 PM1/19/06
to du...@pobox.com, Juerd, perl6-l...@perl.org

Role conflicts are resolved when a role (or set of roles) is composed
into a class. In this case the (automatically generated) code would
look something like this:

method new ($class: %params) {
my $self = $class.bless(%params);
$self does Hash;
return $self;
}

Or it would have to detect it in the class definition itself, in
which case it would add a does Hash; to the class def somewhere.

The reason this would be debugging hell (IMO at least) is that *I*
never told it to does Hash, so as far as I knew there was no clashes
in the roles I composed. Sure if was educated in the finer points of
Perl 6 I would know what happened, but a random newbie would be half-
way to PHP by now.

Stevan

Rob Kinyon

unread,
Jan 19, 2006, 8:54:20 PM1/19/06
to Juerd, perl6-l...@perl.org
On 1/19/06, Juerd <ju...@convolution.nl> wrote:
> Rob Kinyon skribis 2006-01-19 16:10 (-0500):
> > There are no references in Perl6.
> I have to admit, though, that I've never seen this statement, or
> anything implying it. It's entirely new to me.
>
> Is your Perl the same as that of other people on this list? :)

There are no references in Perl6 in the way Perl5 conceives of references.

> Perl still has non-object types. They may represent objects internally,
> but they work differently from what we've historically been calling
> objects. Especially in assignment, the differences are huge, because an
> object is considered a reference, while "real" scalars, arrays and
> hashes evaluate to (a list of) their values, or a useful representation
> (like the number of elements) when used in non-OO fashion.

No. Objects are *NOT* considered references in most languages other
than Perl5. Even in C++, the least OO language that could be
considered OO, you can have non-reference objects.

I'd say "learn Ruby to know what OO is", but I happen to know you
already know a nearly-pure OO language - Javascript. Every single
'thing' in JS is an object - you can hang methods off of a string
literal or a number. Most objects in JS aren't references.

> > &bless was a brilliant idea for Perl5. It's wrong for Perl6.
>
> I think it's needed to be able to convert Perl 5 code
> semi-automatically.
>
> But you have probably thought about this more than I, so I'll ask you:
> what's the alternative?

Well, there's two scenarios - you either run your P5 code using Ponie
or you attempt to use Larry's "Wondrous Machine of Translation".

Me, I choose the former. Now, I don't worry about how objects are
mediated between languages - Ponie and Parrot have to do that for me.
And, before you start worrying, this is a feature that was planned
into Parrot from Day 1. Ruby and Python and Perl6 all have to
interoperate, including inheritance from each others' classes. Perl5
<-> Perl6 will be no different.

But, if you must use the WMoT, then I suspect the following will happen:
1) The WMoT notices your use of &bless and marks that package as a
class and that method as a constructor.
2) It creates a Perl6 class for your use, noting the accesses into
the Perl5 reference that you used and calling those attributes.
3) It then creates your BUILD() method, putting all the non-bless
components of your new() into it.

That's it. No &bless in Perl6 needed.

Rob

Juerd

unread,
Jan 20, 2006, 2:44:04 AM1/20/06
to perl6-l...@perl.org
Rob Kinyon skribis 2006-01-19 20:54 (-0500):

> > > There are no references in Perl6.
> > Is your Perl the same as that of other people on this list? :)
> There are no references in Perl6 in the way Perl5 conceives of references.

There are references in Perl 6.

Do note that @foo evaluates to a reference to itself in scalar context,
which isn't some magical auto-referencing thing. Likewise, a reference
to an array is dereferenced when used as an array. This is automatic,
but still not quite magical.

References, their terminology, and their semantics still very much exist.

> I'd say "learn Ruby to know what OO is", but I happen to know you
> already know a nearly-pure OO language - Javascript.

Somehow that makes me think you don't happen to know that I already know
Ruby too. :)

> Every single 'thing' in JS is an object - you can hang methods off of
> a string literal or a number. Most objects in JS aren't references.

They are what one would call a reference if the language were Perl. I'm
very strictly limiting my jargon to Perl's, unless explicitly stated
otherwise.

For example, PHP's references are not references, but more like
pointers and/or symbolic references, depending on which you choose to
call "references" in PHP.

Note, by the way, that JS has "primitive" strings, and Strings, only the
latter being objects. Fortunately for us, though, a string is
automatically promoted to a String when the string is USED AS an object.

> > > &bless was a brilliant idea for Perl5. It's wrong for Perl6.
> > I think it's needed to be able to convert Perl 5 code
> > semi-automatically. But you have probably thought about this more
> > than I, so I'll ask you: what's the alternative?
> Well, there's two scenarios - you either run your P5 code using Ponie
> or you attempt to use Larry's "Wondrous Machine of Translation".

How would the latter work, if there's no bless?

> But, if you must use the WMoT, then I suspect the following will happen:
> 1) The WMoT notices your use of &bless and marks that package as a
> class and that method as a constructor.
> 2) It creates a Perl6 class for your use, noting the accesses into
> the Perl5 reference that you used and calling those attributes.
> 3) It then creates your BUILD() method, putting all the non-bless
> components of your new() into it.

Doesn't solve the problems as mentioned in this thread, like overlapping
methods.

Rob Kinyon

unread,
Jan 20, 2006, 10:07:08 AM1/20/06
to Juerd, perl6-l...@perl.org
On 1/20/06, Juerd <ju...@convolution.nl> wrote:
> Note, by the way, that JS has "primitive" strings, and Strings, only the
> latter being objects. Fortunately for us, though, a string is
> automatically promoted to a String when the string is USED AS an object.

In other words, according to userland, everything is an object.

> > But, if you must use the WMoT, then I suspect the following will happen:
> > 1) The WMoT notices your use of &bless and marks that package as a
> > class and that method as a constructor.
> > 2) It creates a Perl6 class for your use, noting the accesses into
> > the Perl5 reference that you used and calling those attributes.
> > 3) It then creates your BUILD() method, putting all the non-bless
> > components of your new() into it.
>
> Doesn't solve the problems as mentioned in this thread, like overlapping
> methods.

Yeah it does because all $repr's are p6opaque with direct access being
converted into attribute access. No method overlap.

Rob

0 new messages