Mailing List Archive

Re: "Line Noise" considered offensive
> From: Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>
>
>
>Hmm. I think there's a (possibly intentional?) semantic split occurring here.
>I think we need to make a clear distinction between 'type' and 'class'. I
>realize that's anathema in the pure OO paradigm, but Perl's not pure OO, and I
>think that these concepts are (mostly) orthogonal in Perl. 'Type' is an
>attribute that's defined in Perl's internals, while 'class' is at the
>programmer's disposal. 'Type' is used to determine how to allocate a value,
>and what intrinsic operations can be performed on that value. 'Class' is used
>to determine where to find a function associated with that value.

I agree with Charles on this one. In Perl we have to distinguish between
class (I usually call it "subtype") and implementation type. We cannot say
"an object is an object is an object". We have to know that the object was
implemented as an AV or an HV or some other Perl-internal type.

As an example, my XS typemaps check appropriate combinations of
SvROK/is_object/SvTYPE and don't worry about subtype. This ought to be
enough to help avoid accidents.

Dean
Re: "Line Noise" considered offensive [ In reply to ]
: > From: Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>
: >
: >
: >Hmm. I think there's a (possibly intentional?) semantic split occurring here.
: >I think we need to make a clear distinction between 'type' and 'class'. I
: >realize that's anathema in the pure OO paradigm, but Perl's not pure OO, and I
: >think that these concepts are (mostly) orthogonal in Perl. 'Type' is an
: >attribute that's defined in Perl's internals, while 'class' is at the
: >programmer's disposal. 'Type' is used to determine how to allocate a value,
: >and what intrinsic operations can be performed on that value. 'Class' is used
: >to determine where to find a function associated with that value.
:
: I agree with Charles on this one. In Perl we have to distinguish between
: class (I usually call it "subtype") and implementation type. We cannot say
: "an object is an object is an object". We have to know that the object was
: implemented as an AV or an HV or some other Perl-internal type.

Yes, this distinction is crucial. But it militates against ^NAME.
Think about this a moment. If we define a file object as a blessed
PVIO, then YOU CAN'T DERIVE FROM THAT AND ADD ANY ADDITIONAL
ATTRIBUTES. Sorry for shouting, but this has suddenly started to seem
important. At least with \*NAME, you can conceivably use the hash or
array to attach more data.

Next thing you know, someone is going to propose that filehandle operators
recognize blessed hashes and look for the "HANDLE" value...

But it seems like a filehandle is really an object which has a virtual
method by which you can look up the PVIO. Right now these methods are
all internal.

Larry
Re: "Line Noise" considered offensive [ In reply to ]
Larry Wall writes:
| : > From: Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>
| : >
| : >
| : >Hmm. I think there's a (possibly intentional?) semantic split occurring here.
| : >I think we need to make a clear distinction between 'type' and 'class'. I
| : >realize that's anathema in the pure OO paradigm, but Perl's not pure OO, and I
| : >think that these concepts are (mostly) orthogonal in Perl. 'Type' is an
| : >attribute that's defined in Perl's internals, while 'class' is at the
| : >programmer's disposal. 'Type' is used to determine how to allocate a value,
| : >and what intrinsic operations can be performed on that value. 'Class' is used
| : >to determine where to find a function associated with that value.
| :
| : I agree with Charles on this one. In Perl we have to distinguish between
| : class (I usually call it "subtype") and implementation type. We cannot say
| : "an object is an object is an object". We have to know that the object was
| : implemented as an AV or an HV or some other Perl-internal type.
|
| Yes, this distinction is crucial. But it militates against ^NAME.
| Think about this a moment. If we define a file object as a blessed
| PVIO, then YOU CAN'T DERIVE FROM THAT AND ADD ANY ADDITIONAL
| ATTRIBUTES. Sorry for shouting, but this has suddenly started to seem
| important. At least with \*NAME, you can conceivably use the hash or
| array to attach more data.

Hmm, good point. Essentially, it applies to any type of object other than a
blessed hash in any context. Of course, there's the xpv_pv and xmg_magic of
the PVIO, but they're accessible only from C. OTOH, the intrinsic I/O
operators can't use any additional attributes one might add; if they're
necessary, then it'll be necessary to use a tied handle, and the associated
object can be a hash reference.

| Next thing you know, someone is going to propose that filehandle operators
| recognize blessed hashes and look for the "HANDLE" value...

Not me; it has nearly the same flaws in type-checking as a reference to a
typeglob. If I were feeling whimsical, I might propose that a HV* live in
xpv_any, though, in order to allow for any intrinsic attributes which might
be added later. :-)

| But it seems like a filehandle is really an object which has a virtual
| method by which you can look up the PVIO. Right now these methods are
| all internal.

And that's half the problem, the other half being that even if this method were
available from Perl, it'd make for an expensive runtime check with each use,
unless we have a way to mark that object as having the method around.

My initial reaction is that special behaviors are best handled by tying to a
handle, in a manner analogous to the way that, say, a hash is extended by tying
so that it really reflects the contents of a dbm file. It certainly merits
pondering more, though; the attributes of I/O handles desirable at a low level
and at a high level are more complex than those for most intrinsic types.

Regards,
Charles Bailey bailey@genetics.upenn.edu
Re: "Line Noise" considered offensive [ In reply to ]
> I agree with Charles on this one. In Perl we have to distinguish between
> class (I usually call it "subtype") and implementation type. We cannot say
> "an object is an object is an object". We have to know that the object was
> implemented as an AV or an HV or some other Perl-internal type.

This is important. When you write code that switches on the
type, you say

SWITCH: for (ref $obj) {
/HASH/ && do { ... };
/CODE/ && do { ... };
/GLOB/ && do { ... };
}

Which ref($fh) sometimes returning GLOB and sometimes FileHandle, it's
confusing enough, but just add in things like Sockets and Pipes
as derived class from FileHandle, and it's getting a pain.

Do you think there should be a UNIVERSAL::isa() function
so that $obj->isa("thngiehtingie") would quickly and efficiently
report whether $obj was derived from class "thingie"?

--tom
Re: "Line Noise" considered offensive [ In reply to ]
> I agree with Charles on this one. In Perl we have to distinguish between
> class (I usually call it "subtype") and implementation type. We cannot say
> "an object is an object is an object". We have to know that the object was
> implemented as an AV or an HV or some other Perl-internal type.

This is important. When you write code that switches on the
type, you say

SWITCH: for (ref $obj) {
/HASH/ && do { ... };
/CODE/ && do { ... };
/GLOB/ && do { ... };
}

Which ref($fh) sometimes returning GLOB and sometimes FileHandle, it's
confusing enough, but just add in things like Sockets and Pipes
as derived class from FileHandle, and it's getting a pain.

Do you think there should be a UNIVERSAL::isa() function
so that $obj->isa("thngiehtingie") would quickly and efficiently
report whether $obj was derived from class "thingie"?

--tom
Re: "Line Noise" considered offensive [ In reply to ]
> I agree with Charles on this one. In Perl we have to distinguish between
> class (I usually call it "subtype") and implementation type. We cannot say
> "an object is an object is an object". We have to know that the object was
> implemented as an AV or an HV or some other Perl-internal type.

This is important. When you write code that switches on the
type, you say

SWITCH: for (ref $obj) {
/HASH/ && do { ... };
/CODE/ && do { ... };
/GLOB/ && do { ... };
}

Which ref($fh) sometimes returning GLOB and sometimes FileHandle, it's
confusing enough, but just add in things like Sockets and Pipes
as derived class from FileHandle, and it's getting a pain.

Do you think there should be a UNIVERSAL::isa() function
so that $obj->isa("thngiehtingie") would quickly and efficiently
report whether $obj was derived from class "thingie"?

--tom
Re: "Line Noise" considered offensive [ In reply to ]
> I agree with Charles on this one. In Perl we have to distinguish between
> class (I usually call it "subtype") and implementation type. We cannot say
> "an object is an object is an object". We have to know that the object was
> implemented as an AV or an HV or some other Perl-internal type.

This is important. When you write code that switches on the
type, you say

SWITCH: for (ref $obj) {
/HASH/ && do { ... };
/CODE/ && do { ... };
/GLOB/ && do { ... };
}

Which ref($fh) sometimes returning GLOB and sometimes FileHandle, it's
confusing enough, but just add in things like Sockets and Pipes
as derived class from FileHandle, and it's getting a pain.

Do you think there should be a UNIVERSAL::isa() function
so that $obj->isa("thngiehtingie") would quickly and efficiently
report whether $obj was derived from class "thingie"?

--tom
Re: "Line Noise" considered offensive [ In reply to ]
> I agree with Charles on this one. In Perl we have to distinguish between
> class (I usually call it "subtype") and implementation type. We cannot say
> "an object is an object is an object". We have to know that the object was
> implemented as an AV or an HV or some other Perl-internal type.

This is important. When you write code that switches on the
type, you say

SWITCH: for (ref $obj) {
/HASH/ && do { ... };
/CODE/ && do { ... };
/GLOB/ && do { ... };
}

Which ref($fh) sometimes returning GLOB and sometimes FileHandle, it's
confusing enough, but just add in things like Sockets and Pipes
as derived class from FileHandle, and it's getting a pain.

Do you think there should be a UNIVERSAL::isa() function
so that $obj->isa("thngiehtingie") would quickly and efficiently
report whether $obj was derived from class "thingie"?

--tom
Re: "Line Noise" considered offensive [ In reply to ]
: In <3376.814099659@alumni.cs.colorado.edu>
: On Thu, 19 Oct 1995 04:47:39 -0600
: <tchrist@cs.colorado.edu> writes:
: >
: > ...
: >
: >Do you think there should be a UNIVERSAL::isa() function
: >so that $obj->isa("thngiehtingie") would quickly and efficiently
: >report whether $obj was derived from class "thingie"?
:
: Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

Perhaps every class should have an implicit method of its own name that
returns true. That way you'd get caching.

if ($obj->THINGIE) { ... }

and, of course THINGIE->THINGIE would always be true. Perhaps someday
it might even return metaclass info if given arguments:

@attrnames = $obj->THINGIE("attr");

But I don't want to think too hard about that right now.

Anyway, arg checks might look like this:

my $self = shift;
$self->IO::Handle;

resulting in

Can't locate object method "IO::Handle" via package "FOO" at foo line 22.

It might have odd interactions with AUTOLOAD though.

Larry
Re: "Line Noise" considered offensive [ In reply to ]
> >Do you think there should be a UNIVERSAL::isa() function
> >so that $obj->isa("thngiehtingie") would quickly and efficiently
> >report whether $obj was derived from class "thingie"?
>
> Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)
>
> I am sure that a lot of other people, epspecially Tk, would also
> agree.

When I asked this question on CLP a while ago, somebody (I forgot who,
sorry), posted a Perl solution on which I based the included code.
While this does roll through ISAs, it also caches what it finds, so it
shouldn't be too much of a hog. I don't know if a language-level solution
is de rigueur or not.

If it isn't deemed too grotty, I could post it.

-Eric


# Free Stuff. - Eric.Arnold@Sun.com

package ISA_TEST;


# Usage:
# @classes = $obj->isa;
# $boolean = $obj->isa( classname );
# $boolean = $obj->isa( HASH ); # or ARRAY, etc.

sub isa {
my $this = shift;
my $which_class = shift;
my $class_me = ref $this;

if ( wantarray )
{
return classof( $this );
}

return 1 if $Classes{$class_me, $which_class};
return undef if $Classes{$class_me, $class_me}; # already been looked at
classof( $class_me );
return 1 if $Classes{$class_me, $which_class};
return undef;
}




# This is sorta a private function, since "isa()" will call this for you.
# You only need to use it when you aren't operating on an object ("isa()"
# requires an object).
#
# Usage:
# @classes = ISA_TEST::classof( classname )
# @classes = $obj->classof;

sub classof {
warn "classof: returning array when not wantarray" unless wantarray;
my $class_me = shift;
my %class;
my @result;
my @class;
if ( ref $class_me )
{
my $ref = "$class_me";
$ref =~ s/^.*=//;
$ref =~ s/\(.*//;
#print "ref=$ref\n";
push @class, $ref;
$class_me = ref $class_me;
}
push @class, $class_me;
while( $class = shift @class ) {
push @result, $class unless $class{$class}++;
unshift @class, @{"${class}::ISA"};
$Classes{$class_me,$class}++;
}
return @result;
}


1;
# comment this out to run the tests:
__END__

package Pkg_A;
@ISA = qw( ISA_TEST );

sub new {
my $self = {};
$self->{ "Pkg_A::self" } = $self;
$self->{ "some_Pkg_A_key" } = "some_Pkg_A_value";
return bless $self;
}

sub DESTROY{ print "Pkg_A DESTROY\n"; }

sub print {
my $self = shift;
print "Pkg_A print: \n";
for $k ( keys %$self ){
print "\t$k = $self->{$k}\n"; }
}



package Pkg_B; @ISA = qw(Pkg_A);

sub new {
#my $self = Pkg_A::new; # not good enough: must create a new ref
# so that something will exist that will
# eventually go out of scope, triggering
# DESTROY
my $self = {};
%$self = (
"Pkg_B::self" => $self,
%{ &Pkg_A::new },
"some_Pkg_B_key" => "some_Pkg_B_value",
);
return bless $self;
}
sub DESTROY{ print "Pkg_B DESTROY\n"; }



package Pkg_C; @ISA = qw(Pkg_B);

sub new {
my $self = {};
my $obj = Pkg_B::new;
%$self = %$obj;
$self->{ "Pkg_C::self" } = $self;
$self->{ "some_Pkg_C_key" } = "some_Pkg_C_value";
return bless $self;
}
sub DESTROY{ print "Pkg_C DESTROY\n"; }

package main;

$myc = Pkg_C->new;
$myc->print;
print "ending\n";

@r = ISA_TEST::isa(Pkg_C);
print "ISA_TEST::isa(Pkg_C) = @r\n";

print "\$myc = '$myc'\n";

@r = $myc->isa;
print "\$myc->isa = @r\n";

for $what ( qw( Pkg_A Pkg_D HASH ARRAY ) )
{
print "myc->( $what ) = ", $myc->isa($what) ? true : false , "\n";
}
Re: "Line Noise" considered offensive [ In reply to ]
In <3376.814099659@alumni.cs.colorado.edu>
On Thu, 19 Oct 1995 04:47:39 -0600
<tchrist@cs.colorado.edu> writes:
>
> ...
>
>Do you think there should be a UNIVERSAL::isa() function
>so that $obj->isa("thngiehtingie") would quickly and efficiently
>report whether $obj was derived from class "thingie"?

Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

I am sure that a lot of other people, epspecially Tk, would also
agree.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
In <3376.814099659@alumni.cs.colorado.edu>
On Thu, 19 Oct 1995 04:47:39 -0600
<tchrist@cs.colorado.edu> writes:
>
> ...
>
>Do you think there should be a UNIVERSAL::isa() function
>so that $obj->isa("thngiehtingie") would quickly and efficiently
>report whether $obj was derived from class "thingie"?

Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

I am sure that a lot of other people, epspecially Tk, would also
agree.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
In <3376.814099659@alumni.cs.colorado.edu>
On Thu, 19 Oct 1995 04:47:39 -0600
<tchrist@cs.colorado.edu> writes:
>
> ...
>
>Do you think there should be a UNIVERSAL::isa() function
>so that $obj->isa("thngiehtingie") would quickly and efficiently
>report whether $obj was derived from class "thingie"?

Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

I am sure that a lot of other people, epspecially Tk, would also
agree.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
In <3376.814099659@alumni.cs.colorado.edu>
On Thu, 19 Oct 1995 04:47:39 -0600
<tchrist@cs.colorado.edu> writes:
>
> ...
>
>Do you think there should be a UNIVERSAL::isa() function
>so that $obj->isa("thngiehtingie") would quickly and efficiently
>report whether $obj was derived from class "thingie"?

Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

I am sure that a lot of other people, epspecially Tk, would also
agree.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
> - Sarathy.
> gsar@engin.umich.edu
>

--
Kenneth Albanowski (kjahds@kjahds.com, CIS: 70705,126)
Re: "Line Noise" considered offensive [ In reply to ]
In <3376.814099659@alumni.cs.colorado.edu>
On Thu, 19 Oct 1995 04:47:39 -0600
<tchrist@cs.colorado.edu> writes:
>
> ...
>
>Do you think there should be a UNIVERSAL::isa() function
>so that $obj->isa("thngiehtingie") would quickly and efficiently
>report whether $obj was derived from class "thingie"?

Yes. It should work for both ->isa(HASH) and ->isa(SomeClassName)

I am sure that a lot of other people, epspecially Tk, would also
agree.

Regards,
Graham.

--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
In <9510191630.AA26877@scalpel.netlabs.com>
On Thu, 19 Oct 95 09:30:27 -0700
Larry Wall <lwall@scalpel.netlabs.com> writes:

>Perhaps every class should have an implicit method of its own name that
>returns true. That way you'd get caching.
>
> if ($obj->THINGIE) { ... }
>
>and, of course THINGIE->THINGIE would always be true. Perhaps someday
>it might even return metaclass info if given arguments:
>
> @attrnames = $obj->THINGIE("attr");
>
>But I don't want to think too hard about that right now.
>
>Anyway, arg checks might look like this:
>
> my $self = shift;
> $self->IO::Handle;
>
>resulting in
>
> Can't locate object method "IO::Handle" via package "FOO" at foo line 22.

The error message is usually just what you don't want - because you never
need to use it on $self.

The residual use in Tk is things like :

while ($widget->parent->IsMenu) # is containing widget derived from Menu ?
{
$widget = $widget->parent; # still cascaded up we go ...
}

This is implemented by what Tk does when you declare something to be a widget
class. It defines

sub IsTHINGY {1}

and

sub Tk::IsTHINGY {0}

(Tk is near enough to UNIVERSAL for places where this is used).

The 'obvious' extension to perl as a whole is that

package THINGY;

Implicity does:

sub THINGY {1} # Larry's suggestion
sub UNIVERSAL::THINGY {0} # Avoid the above message


>
>It might have odd interactions with AUTOLOAD though.

Tk's scheme seems to co-exist with its use of AUTOLOAD.



>
>Larry
Re: "Line Noise" considered offensive [ In reply to ]
In <9510191730.AA05823@pluto>
On Thu, 19 Oct 95 18:30:10 BST
Nick Ing <Nick.Ing-Simmons@tiuk.ti.com> writes:
>In <9510191630.AA26877@scalpel.netlabs.com>
>On Thu, 19 Oct 95 09:30:27 -0700
>Larry Wall <lwall@scalpel.netlabs.com> writes:
>
>>Perhaps every class should have an implicit method of its own name that
>>returns true. That way you'd get caching.
>>
>> if ($obj->THINGIE) { ... }
>>
>>and, of course THINGIE->THINGIE would always be true. Perhaps someday
>>it might even return metaclass info if given arguments:
>>
>> @attrnames = $obj->THINGIE("attr");
>>
>>But I don't want to think too hard about that right now.
>>
>>Anyway, arg checks might look like this:
>>
>> my $self = shift;
>> $self->IO::Handle;
>>
>>resulting in
>>
>> Can't locate object method "IO::Handle" via package "FOO" at foo line 22.
>
>The error message is usually just what you don't want - because you never
>need to use it on $self.
>
>The residual use in Tk is things like :
>
>while ($widget->parent->IsMenu) # is containing widget derived from Menu ?
> {
> $widget = $widget->parent; # still cascaded up we go ...
> }
>
>This is implemented by what Tk does when you declare something to be a widget
>class. It defines
>
>sub IsTHINGY {1}
>
>and
>
>sub Tk::IsTHINGY {0}
>
>(Tk is near enough to UNIVERSAL for places where this is used).
>
>The 'obvious' extension to perl as a whole is that
>
>package THINGY;
>
>Implicity does:
>
>sub THINGY {1} # Larry's suggestion
>sub UNIVERSAL::THINGY {0} # Avoid the above message

This method will only work for packages which do not have :: in their name
or some changes as to locating methods in UNIVERSAL would need modifying

for example

sub IO::Handle {1} # Larry's suggestion
sub UNIVERSAL::IO::Handle {0} # Avoid the above message

$xyz->IO::Handle; # will work if $xyz is a IO::Handle but if it is not
# it fails the same as before.

With this in mind I think the isa needs to be a builtin part of perl
and not done as a method.

Regards,
Graham.



--
Graham Barr <bodg@tiuk.ti.com>
Texas Instruments Ltd.
Re: "Line Noise" considered offensive [ In reply to ]
: for example
:
: sub IO::Handle {1} # Larry's suggestion
: sub UNIVERSAL::IO::Handle {0} # Avoid the above message
:
: $xyz->IO::Handle; # will work if $xyz is a IO::Handle but if it is not
: # it fails the same as before.
:
: With this in mind I think the isa needs to be a builtin part of perl
: and not done as a method.

Mmm, you're right. Urque. Furthermore, IO::Handle could give a false
positive on $obj->Handle if $obj is IO::Handle but not a Handle.

Larry
Re: Extra information in \*HANDLE [ In reply to ]
According to Larry Wall:

> If we define a file object as a blessed PVIO, then YOU CAN'T DERIVE
> FROM THAT AND ADD ANY ADDITIONAL ATTRIBUTES. Sorry for shouting,
> but this has suddenly started to seem important. At least with
> \*NAME, you can conceivably use the hash or array to attach more
> data.

No, I'm sorry; that dog won't hunt.

First, no one has tried to define a file object as a _blessed_ PVIO.
Rather, everyone has observed that PVIOs are I/O handles; that's the
old way. Also, people have suggested that blessed objects of any
basic data type be used as I/O handles too, though the use of magic;
that's the proposed new way. Neither the old way nor the proposed new
way connects PVIO-ness with blessedness. And the new way already
allows for arbitrary attributes without requiring that they be
packaged in a glob.

(It just so happens that PVIOs are automatically blessed, but that's not
what makes them I/O handles; it's just a convention that makes access
functions simpler.)

> But it seems like a filehandle is really an object which has a virtual
> method by which you can look up the PVIO. Right now these methods are
> all internal.

My proposal for user-defined I/O classes eliminates any actual _need_
for PVIOs. However, in practice, they would almost always be there.
--
Chip Salzenberg, aka <chs@nando.net>
"Hey, it's the Miss Alternate Universe Pageant!"
-- Crow T. Robot, MST3K: "Stranded In Space"