Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Coderefs in objects: tricky questions

Reply
Thread Tools

Coderefs in objects: tricky questions

 
 
peterkayatwork@yahoo.com
Guest
Posts: n/a
 
      09-26-2005
I have an object (using standard AUTOLOAD from perltoot) that I want to
pass a coderef to and be able to run the coderef from.

If I do this:
new {
.... # standard object creation from perltoot
$self->{Sub}=sub { return $self->Real(@_) };
return $self;
};

sub Real
{
my $self=shift;
my $arg=shift;
return "[$arg]\n";
}


then I can call it via:
print &{$object->Sub}("Hi");

and get
[Hi]

Few questions:
1. Is this a Bad Way To Do It?
2.
This doesn't work:
$self->{Sub}=\&{$self->Real};

Why not?

The error I get is:

Use of inherited AUTOLOAD for non-method Object::Hi() is deprecated at
Object.t line 22.

Really terribly helpful, isn't it? I can do stuff in Perl, but having
a super-duper handle on WTF the AUTOLOAD stuff is doing with coderefs
is a bit beyond me

If anyone has a good answer for why this is happening, I'd love it. If
anyone has a good suggestion for which FM to read, I'll do so.

3. Is there a way to set $self->{Sub} without using 'sub'?

Thanks,

--Peter
peterkayatwork (at) yahoo.com

 
Reply With Quote
 
 
 
 
xhoster@gmail.com
Guest
Posts: n/a
 
      09-26-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> I have an object (using standard AUTOLOAD from perltoot) that I want to
> pass a coderef to and be able to run the coderef from.
>
> If I do this:
> new {


You need "sub new {". Please post real code.

> ... # standard object creation from perltoot
> $self->{Sub}=sub { return $self->Real(@_) };
> return $self;
> };


You said you wanted to pass the coderef into the object, but here
you are hard coding it, rather than getting it out of new()'s argument
list!


>
> sub Real
> {
> my $self=shift;
> my $arg=shift;
> return "[$arg]\n";
> }
>
> then I can call it via:
> print &{$object->Sub}("Hi");


>
> and get
> [Hi]


Really? I get:

Can't locate object method "Sub" via package "foo" at object.pl line 23.

I can't tell if forgot to define the method Sub, or if you forgot to put
curlies around your dereference of $object using the key 'Sub'.
Again, post real code.


>
> Few questions:
> 1. Is this a Bad Way To Do It?


Yes. Not passing a coderef into an object is a bad way to pass a coderef
into an object. Not posting real code is a bad way to get help on your
code. And piercing the object encapsulation by directly dereferencing the
object from outside the package (which it looks like you may be doing) is
usually a bad way to do OO.

> 2.
> This doesn't work:
> $self->{Sub}=\&{$self->Real};
>
> Why not?


I think it is invoking $self->Real, and then trying to do \&{} on the
results of that invocation.


> 3. Is there a way to set $self->{Sub} without using 'sub'?


$self->{Sub}=$coderef;


Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
 
 
 
peterkayatwork@yahoo.com
Guest
Posts: n/a
 
      09-26-2005
(E-Mail Removed) wrote:
> Please post real code.


################################################## ####
# Parent.pm
#!/usr/bin/perl

package Parent;
use strict;
use warnings;

use Carp;

our $AUTOLOAD;

my %fields = (
Name => undef,
Sub => undef,
);

sub new
{
my $class=shift;
my $self={
_permitted => \%fields,
%fields,
};
bless ($self, $class);
return $self;
}

# Automatically create methods for everything defined in %fields above:
sub AUTOLOAD {
my $self = shift;
my $type = ref($self)
or croak "$self is not an object - cannot AUTOLOAD";

my $name = $AUTOLOAD;
$name =~ s/.*://; # strip fully-qualified portion

unless (exists $self->{_permitted}->{$name} ) {
croak "Can't access `$name' field in class $type";
}

if (@_) {
return $self->{$name} = shift;
} else {
return $self->{$name};
}
}

1;

################################################## ####
# Object.pm
#!/usr/bin/perl

package Object;
use strict;
use warnings;

use Parent;
our @ISA=qw(Parent);

sub new
{
my $class = shift;
my $self = $class->SUPER::new();
my($element);
# Not needed yet:
# foreach $element (keys %fields) {
# $self->{_permitted}->{$element} = $fields{$element};
# }
# @{$self}{keys %fields} = values %fields;

# Give this derived object a default bit of code:
$self->{Sub}=sub { return $self->Real(@_) };
return $self;
}

sub Real
{
my $self=shift;
my $arg=shift;
return "[$arg]\n";
}


1;

################################################## ####
# Object.t
#!/usr/bin/perl
use strict;
use warnings;

use Test::More;

use Object;

my $object = new Object;

print &{$object->Sub}("Hi");

################################################## ####
# Command line:
> perl Object.t

[Hi]
>


################################################## ####
Is there a better/more appropriate way to post all the code?
--Peter
peterkay (at) yahoo.com

 
Reply With Quote
 
peterkayatwork@yahoo.com
Guest
Posts: n/a
 
      09-26-2005
(E-Mail Removed) wrote:
> ################################################## ####
> # Object.t
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> use Test::More;
>
> use Object;
>
> my $object = new Object;
>
> print &{$object->Sub}("Hi");


Sorry, this should have been:

is(&{$object->Sub}("Hi"), "[Hi]", "Can call coderef from
$object->Sub");

(with appropriate command line result)

It's a bit simplier then what I'm really doing, but illistrates the
situation

--Peter

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      09-26-2005
(E-Mail Removed) wrote in news:1127773260.746269.57950
@g14g2000cwa.googlegroups.com:

> (E-Mail Removed) wrote:
>> Please post real code.

....

> # Object.t
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> use Test::More;
>
> use Object;
>
> my $object = new Object;
>
> print &{$object->Sub}("Hi");
>
> ################################################## ####
> # Command line:
>> perl Object.t

> [Hi]
>>

>
> ################################################## ####
> Is there a better/more appropriate way to post all the code?


Code that works would be great.

D:\Home\asu1\UseNet\clpmisc> z
You tried to run a test without a plan! Gotta have a plan. at
C:/opt/Perl/lib/Test/More.pm line 362
# Looks like your test died before it could output anything.

After fixing that:

D:\Home\asu1\UseNet\clpmisc> z
1..1
not ok 1 - Can call coderef from Object=HASH(0x19178e->Sub
# Failed test (D:\Home\asu1\UseNet\clpmisc\z.pl at line 69)
# got: '[Hi]
# '
# expected: '[Hi]'
# Looks like you failed 1 test of 1.

So, we fix that by changing the test case to

is( &{$object->Sub}("Hi"),
"[Hi]\n",
"Can call coderef from $object->Sub"
);

D:\Home\asu1\UseNet\clpmisc> z
1..1
ok 1 - Can call coderef from Object=HASH(0x19178f4)->Sub

I did slightly modify your code to put everything in one script. The
modified version follows below.

I did follow the messages in this thread, but I am still not sure what
your actual question is.

#!/usr/bin/perl

package Parent;
use strict;
use warnings;

use Carp;

our $AUTOLOAD;

my %fields = (Name => undef, Sub => undef);

sub new {
my $class = shift;
my $self = {
_permitted => \%fields,
%fields,
};
bless $self, $class;
}

# Automatically create methods for everything defined in %fields above:
sub AUTOLOAD {
my $self = shift;
my $name = $AUTOLOAD;
$name =~ s/.*://;

unless (exists $self->{_permitted}->{$name} ) {
croak "Can't access `$name' field in class ".__PACKAGE__;
}

if (@_) {
return $self->{$name} = shift;
} else {
return $self->{$name};
}
}

package Object;

use strict;
use warnings;

use base 'Parent';

sub new {
my $class = shift;
my $self = $class->SUPER::new();

$self->{Sub} = sub { return $self->Real(@_) };
return $self;
}

sub Real {
my $self = shift;
my $arg = shift;
return "[$arg]\n";
}

package main;

use strict;
use warnings;

use Test::More tests => 1;

my $object = Object->new;

is( &{$object->Sub}("Hi"),
"[Hi]\n",
"Can call coderef from $object->Sub"
);

1;


--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html
 
Reply With Quote
 
xhoster@gmail.com
Guest
Posts: n/a
 
      09-26-2005
(E-Mail Removed) wrote:
> (E-Mail Removed) wrote:
> > Please post real code.

>
> ################################################## ####
> # Parent.pm
> #!/usr/bin/perl


Thanks, now I can run your code, and have slightly better idea of what you
are trying to do. (Although I still don't know *why* you are trying to do
it.)

However, when I replace your code

$self->{Sub}=sub { return $self->Real(@_) };

With the other code from your original message:

$self->{Sub}=\&{$self->Real};

I do not get the error you report in your original message.
I get:

Use of uninitialized value in concatenation (.) or string at Object.pm line
33. Undefined subroutine &main::[]
called at Object.t line 13.

So it looks like I was right before, $self->Real is being invoked,
returning "[]\n", which is interpreted as the name of a subroutine. If you
want to delay the execution of $self->Real, then you do have to use sub {}
to do it.


> ################################################## ####
> Is there a better/more appropriate way to post all the code?
> --Peter
> peterkay (at) yahoo.com


Well, I would have just put all the packages into one file. But the way
you did it was perfectly reasonable.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
peterkayatwork@yahoo.com
Guest
Posts: n/a
 
      09-28-2005
A. Sinan Unur wrote:
> I did follow the messages in this thread, but I am still not sure what
> your actual question is.


I guess the only question I have left is:

3. Is there a way to set $self->{Sub} without using 'sub'?

I want to pull this effect off:

> $self->{Sub} = sub { return $self->Real(@_) };


without using 'sub'. I'd love to know how to correctly set up the code
ref directly. But as was pointed out:

$self->{Sub}=\&{$self->Real};

seems to be trying to call $self->Real and then execute the return
string as code...

> use base 'Parent';


Where the h*ll is this documented?

--Peter
peterkayatwork (at) yahoo.com

 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      09-28-2005
(E-Mail Removed) wrote:
> A. Sinan Unur wrote:


> > use base 'Parent';

>
> Where the h*ll is this documented?


The profanity is unnecessary, and is unlikely to encourage anyone to
render your assistance. (No, I'm not saying I or anyone else will
refuse to help you if you use "hell" - with or without censoring - I'm
just saying it doesn't aid your cause at all).

The base pragma, like all modules and pragmas, is documented in the
associated perldoc:
perldoc base
or
http://perldoc.perl.org/base.html

Paul Lalli

 
Reply With Quote
 
Eric Schwartz
Guest
Posts: n/a
 
      09-28-2005
"Paul Lalli" <(E-Mail Removed)> writes:
> The base pragma, like all modules and pragmas, is documented in the
> associated perldoc:
> perldoc base
> or
> http://perldoc.perl.org/base.html


I think the real question was, "How should I have known I am supposed
to 'use base'? And that's a fair question. I looked in perltoot--
it's not even mentioned. In perlobj I see one mention, but it's very
much in passing, and unless you're reading carefully for references to
'use base', it's easy to miss. I see a nice explanation in perlboot,
but I don't know that I had even heard of that one until I was
searching for further references in perltoot.

'perldoc base' is only useful if you knew you needed 'use base' in the
first place, and wanted to know more. Otherwise, it's just lost in a
sea of very similar looking documentation.

-=Eric
 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      09-28-2005
Eric Schwartz wrote:
> "Paul Lalli" <(E-Mail Removed)> writes:
> > The base pragma, like all modules and pragmas, is documented in the
> > associated perldoc:
> > perldoc base
> > or
> > http://perldoc.perl.org/base.html

>
> I think the real question was, "How should I have known I am supposed
> to 'use base'? And that's a fair question.


Eh. Maybe. I could see the OP's question being taken either way.
Either "Why isn't it documented that I should use this?" or "I am
completely unable to locate the documentation for this pragma."

Ambiguity strikes again.

Paul Lalli

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
some tricky questions birensubudhi@gmail.com C Programming 31 07-02-2007 10:04 AM
a tricky if else(maybe not tricky but impossible) nirkheys@gmail.com C Programming 9 04-25-2006 06:13 PM
Do you have tipps for tricky questions? George MCAD 3 05-24-2005 03:40 AM
Re: Questions....questions....questions Patrick Michael A+ Certification 0 06-16-2004 04:53 PM



Advertisments