How to get "<$myclass_instance>" to work?


K

kj

I want to write a class whose instances are iterators that will
behave similarly to (readonly) file handles. I.e. I want to be
able to write:

my $thingie = Thingie->new( @args );
while ( <$thingie> ) {
# do stuff with $_
}

Can someone point me to a good example of a module in CPAN that
does this, for me to study? I'm looking specifically for a module
that achieves this functionality via standard Perl subclassing (as
opposed to tied variables, which I find too magic and mysterious).

TIA!

kj
 
Ad

Advertisements

X

xhoster

kj said:
I want to write a class whose instances are iterators that will
behave similarly to (readonly) file handles. I.e. I want to be
able to write:

my $thingie = Thingie->new( @args );
while ( <$thingie> ) {
# do stuff with $_
}

Can someone point me to a good example of a module in CPAN that
does this, for me to study? I'm looking specifically for a module
that achieves this functionality via standard Perl subclassing (as
opposed to tied variables, which I find too magic and mysterious).

Have you already looked at the Iterator section of perldoc overload?
It isn't exactly an example, but it should be pretty informative if
you haven't already read it.

Surprisingly, I can't find any installed modules that use this feature of
overload. Maybe I just can't formulate the grep correctly to find them.

fgrep --include=\*.pm -r -C 4 'overload' /tools/perl/ | fgrep '<>'

Xho
 
P

Paul Lalli

I want to write a class whose instances are iterators that will
behave similarly to (readonly) file handles. I.e. I want to be
able to write:

my $thingie = Thingie->new( @args );
while ( <$thingie> ) {
# do stuff with $_
}

Can someone point me to a good example of a module in CPAN that
does this, for me to study?

I don't know about a CPAN module explicitly, but it's pretty easy for
me to create an example. <> is one of the overloadable operators with
the 'overload' pragma:

package MyClass;
use strict;
use warnings;
use overload
'<>' => \&iter,
;

sub new {
my $class = shift;
my $ref = { count => -1, things => [ @_ ] };
bless $ref, $class;
}

sub iter {
my $obj = shift;
my $count = ++$obj->{count};
if ($count == @{$obj->{things}}){
$obj->{count} = -1;
return;
}
return $obj->{things}[$count];
}

1;

I'm looking specifically for a module
that achieves this functionality via standard Perl subclassing (as
opposed to tied variables, which I find too magic and mysterious).

You certainly could do it with tied variables. I think you'd want to
tie your object as a filehandle. But I agree, not much point in that
level of indirection in this case. Overloading the operator is
easier.

Here's a main file for you to test the above class on:

#!/usr/bin/perl
use strict;
use warnings;
use MyClass;

my $mc = MyClass->new(qw/foo bar baz/);

print "First\n";
while (my $thing = <$mc>) {
print "$thing\n";
}
print "Second\n";
while (my $thing = <$mc>) {
print "$thing\n";
}
__END__

(I iterated twice simply to prove that the overloaded <> operator
correctly returns undef when the list is exhausted, and resets the
counter correctly.)

Hope this helps,
Paul Lalli
 
K

kj

In said:
I don't know about a CPAN module explicitly, but it's pretty easy for
me to create an example. <> is one of the overloadable operators with
the 'overload' pragma:

<snip>

Thank you very much, and also to Xho. I hadn't even *thought* of
using overload.

kj
 
U

Uri Guttman

x> Surprisingly, I can't find any installed modules that use this feature of
x> overload. Maybe I just can't formulate the grep correctly to find them.

it isn't overload you want but tied. look at File::ReadBackwards for a
simple use of tying (or procedural).

uri
 
U

Uri Guttman

k> <snip>

k> Thank you very much, and also to Xho. I hadn't even *thought* of
k> using overload.

see my other post. tying is probably even easier than overloading. you
just need to create 2 methods that handle the tied interface (a
constructor and a readline). see File::ReadBackwards for a simple
working example.

uri
 
Ad

Advertisements

P

Paul Lalli

k> <snip>

k> Thank you very much, and also to Xho. I hadn't even *thought* of
k> using overload.

see my other post. tying is probably even easier than overloading. you
just need to create 2 methods that handle the tied interface (a
constructor and a readline).

.... uh-huh, and with using overload, you only need the normal
constructor you were going to have anyway, and ONE method to handle
the operator.

(plus, the OP very specifically said he didn't want to mess with
tying)

Paul Lalli
 
U

Uri Guttman

PL> ... uh-huh, and with using overload, you only need the normal
PL> constructor you were going to have anyway, and ONE method to handle
PL> the operator.

well, we are counting the same things, a single constuctor (which is a
class method) and a single operator or readline method. i added tie
support to File::ReadBackwards by putting in two typeglob assignments to
alias the open and readline methods to the names needed by tied
handles. not much work at all and i would say less than if i did
overloading as that needs a mapping structure.

oops, i just checked and it has 5 method aliases. i started with 2 but a
bug/feature report requested eof, close and tell (those also needed new
short methods).

PL> (plus, the OP very specifically said he didn't want to mess with
PL> tying)

that i didn't see. but as i think it is less work, tying should be on
the table. maybe he was scared by what he thought it needed.

uri
 
K

kj

... uh-huh, and with using overload, you only need the normal
constructor you were going to have anyway, and ONE method to handle
the operator.

Actually, as I just discovered, there's another problem with the
overload approach, and that is that the overloaded <> does not
transmit context information properly to the implementing routine.
There's mention of this in the docs. E.g. the following (incorrectly)
prints "0\n":

# in package 'main'
use overload '<>' => sub { print wantarray ? 1 : 0, "\n" };
my $x = bless +{};
my @x = <$x>;
__END__
0

(This may be have been fixed in more recent versions of overload
I'm using version 1.02).

kj
 
K

kj

In said:
that i didn't see. but as i think it is less work, tying should be on
the table. maybe he was scared by what he thought it needed.

No, actually, it's not the amount of work that scares, but rather
the fact that I've never gotten the hang of tied variables. For
me programming with them is always an exercise in trial and error;
I never quite know what to expect. Too much magic for my little
brain, I guess.

But I will study File::ReadBackwards. Thanks for the pointer.

kj
 
X

xhoster

kj said:
Actually, as I just discovered, there's another problem with the
overload approach, and that is that the overloaded <> does not
transmit context information properly to the implementing routine.
....

(This may be have been fixed in more recent versions of overload
I'm using version 1.02).

The bug warning is still there in the docs for the latest version, 1.06
(corresponding to perl-5.9.5)

Maybe it's time to dig into tie....

But I agree the other poster who suggested

while (defined ($_=$myclass_instance->next())) {

It is uglier than "while (<$mycalss_instance>)", especially the need
to include the define and extra parentheses, but it is less likely
to mislead the code reader into thinking it is a real file handle.

Xho
 
Ad

Advertisements

K

kj

In said:
But I agree the other poster who suggested
while (defined ($_=$myclass_instance->next())) {
It is uglier than "while (<$mycalss_instance>)", especially the need
to include the define and extra parentheses, but it is less likely
to mislead the code reader into thinking it is a real file handle.

The motivation here is not aesthetics, but rather polymorphism.
I want to be able to pass myclass instances to external methods/functions
that expect read handles.

kj
 
U

Uri Guttman

k> No, actually, it's not the amount of work that scares, but rather
k> the fact that I've never gotten the hang of tied variables. For
k> me programming with them is always an exercise in trial and error;
k> I never quite know what to expect. Too much magic for my little
k> brain, I guess.

then you shouldn't be a programmer. in fact programming should never be
trial and error as it is specifically meant to be deterministic by its
very nature. :)

having read overload.pm and seen it in use it is the same level of
complexity as tying but it does it from an operator point of view vs a
variable view. in many ways they are very similar. they both require
objects. i think overloading is more complex because you usually have to
deal with 2 possible operands and how they relate based on the
operator. with <> you only have 1 operand so it simplifies things a bit.

k> But I will study File::ReadBackwards. Thanks for the pointer.

and as i said, i didn't write one special line of code for tying as
such. the OO interface is just aliased to the required tied method
names. that is why tying is simpler IMO than overloading.

uri
 
W

Wayne M. Poe

Uri said:
k> In <[email protected]> Uri Guttman
it is less work, tying should be on >> the table. maybe he was
scared by what he thought it needed.

k> No, actually, it's not the amount of work that scares, but rather
k> the fact that I've never gotten the hang of tied variables. For
k> me programming with them is always an exercise in trial and error;
k> I never quite know what to expect. Too much magic for my little
k> brain, I guess.

then you shouldn't be a programmer. in fact programming should never
be trial and error as it is specifically meant to be deterministic by
its very nature. :)

And who are you to tell someone they shouldn't be programming? Coming
from someone who can't even use the stinking shift key.
having read overload.pm and seen it in use it is the same level of
complexity as tying but it does it from an operator point of view vs a
variable view.

Maybe from your point of view the complexity is the same, but I get the
feeling it's not from the OP's. He seemed to make that very clear yet
you keep on ignoring this.
in many ways they are very similar. they both require
objects. i think overloading is more complex because you usually have
to deal with 2 possible operands and how they relate based on the
operator. with <> you only have 1 operand so it simplifies things a
bit.

It all depends on one's background. If one is coming from a language
like C++ then overloading will feel more natural.
 
Ad

Advertisements

U

Uri Guttman

k> No, actually, it's not the amount of work that scares, but rather
k> the fact that I've never gotten the hang of tied variables. For
k> me programming with them is always an exercise in trial and error;
k> I never quite know what to expect. Too much magic for my little
k> brain, I guess.
WMP> And who are you to tell someone they shouldn't be programming? Coming
WMP> from someone who can't even use the stinking shift key.

my shift key smells so bad i don't dare TOUCH IT!

and i started coding on punch cards and in PL/I when code was case
insensitive and almost always upper case!

WMP> Maybe from your point of view the complexity is the same, but I get the
WMP> feeling it's not from the OP's. He seemed to make that very clear yet
WMP> you keep on ignoring this.

well, maybe i can change his point of view. it happens here all the time
(or at least should :).

WMP> It all depends on one's background. If one is coming from a language
WMP> like C++ then overloading will feel more natural.

and using c++ us unnatural to begin with! :)

to reiterate, trial and error is not a good programming technique.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top