Generating an anonymous reference to an OO method

M

Matthew Pounsett

Is there a way to get an anonymous reference to an OO method that can then be executed? I'm trying to create a reference to the new() method in one of the Digest:: modules, depending on which digest type has been selected, so that I don't have to keep having the same big if() block every time I create a new digest. My first stab at what I'm trying to attempt looked like this:

----
use Digest::MD5;

$digest = \&Digest::MD5::new;
$foo = &$digest();
$foo->add( "blahblahblah" );
print $foo->hexdigest;
 
R

Randal L. Schwartz

Matthew> Is there a way to get an anonymous reference to an OO method
Matthew> that can then be executed?

Just create a closure:


my $maker = do {
my $class = "Digest::MD5"; # or however you want to determine this
sub { return $class->new->add(@_) };
};

## later...

print $maker->("blahblah")->hexdigest;


print "Just another Perl hacker,"; # the original
 
R

Rainer Weikusat

Matthew Pounsett said:
Is there a way to get an anonymous reference to an OO method that can then be executed? I'm trying to create a reference to the new() method in one of the Digest:: modules, depending on which digest type has been selected, so that I don't have to keep having the same big if() block every time I create a new digest. My first stab at what I'm trying to attempt looked like this:

----
use Digest::MD5;

$digest = \&Digest::MD5::new;
$foo = &$digest();
$foo->add( "blahblahblah" );
print $foo->hexdigest;

For completeness: You still need to pass the class name as first
argument to the contstructor (or an object as first argument to an
'ordinary' method). Creating a closure which calls the desired
constructor in the proper way is IMO a better idea.
 
R

Rainer Weikusat

Matthew> Is there a way to get an anonymous reference to an OO method
Matthew> that can then be executed?

Just create a closure:


my $maker = do {
my $class = "Digest::MD5"; # or however you want to determine this
sub { return $class->new->add(@_) };
};

Provided that $class never changes, an alternative with some possibly
desirable technical properties (such as not tying up the scalar $class
in order to determine a value which never changes during invocation)
would be (not actually compiled):

eval("sub { return $class->new->add(".'@_); }');

This should create an anonymous subroutine which invokes the desired
operation without needing $class or its value when being called.
 
T

Ted Zlatanov

RW> Provided that $class never changes, an alternative with some possibly
RW> desirable technical properties (such as not tying up the scalar $class
RW> in order to determine a value which never changes during invocation)
RW> would be (not actually compiled):

RW> eval("sub { return $class->new->add(".'@_); }');

RW> This should create an anonymous subroutine which invokes the desired
RW> operation without needing $class or its value when being called.

That is deeply nasty. Why do you want to avoid a closure on $class?
The code is simpler with a closure, you don't have to create code
dynamically (so compile-time checks can work properly)...

Ted
 
R

Randal L. Schwartz

Rainer> Provided that $class never changes, an alternative with some possibly
Rainer> desirable technical properties (such as not tying up the scalar $class
Rainer> in order to determine a value which never changes during invocation)
Rainer> would be (not actually compiled):

Rainer> eval("sub { return $class->new->add(".'@_); }');

If $class never changes, just hardwire it. DON'T USE EVAL-STRING.
DON'T USE EVAL-STRING.

my $maker = sub { return Digest::MD5->new->add(@_) };

And not sure if I covered this already, but DON'T USE EVAL-STRING.

If you don't know why I'm saying this so strongly, then it applies
doubly to you. :)

print "Just another Perl hacker,"; # the original
 
R

Rainer Weikusat

Rainer> Provided that $class never changes, an alternative with some possibly
Rainer> desirable technical properties (such as not tying up the scalar $class
Rainer> in order to determine a value which never changes during invocation)
Rainer> would be (not actually compiled):

Rainer> eval("sub { return $class->new->add(".'@_); }');

If $class never changes, just hardwire it.

If it never changes AFTER its value was determined, obviously ...
DON'T USE EVAL-STRING.
DON'T USE EVAL-STRING.

.... then you can effectively hardwire it by using eval to run the Perl
compiler to create suitable subroutine at runtime.
my $maker = sub { return Digest::MD5->new->add(@_) };

And not sure if I covered this already, but DON'T USE EVAL-STRING.

If you don't know why I'm saying this so strongly, then it applies
doubly to you. :)

I really don't know why you think that running the Perl compiler from
within Perl-code in order to create new compiled code should be
avoided. I'll happily learn the reason for that, though.
 
U

Uri Guttman

RW> I really don't know why you think that running the Perl compiler from
RW> within Perl-code in order to create new compiled code should be
RW> avoided. I'll happily learn the reason for that, though.

you have shown a massive unwillingness to learn from anyone here. why
should that change now? eval string is nasty and evil for many reasons,
most of them pretty obvious too. the first one is it is rarely needed as
you can almost always do things without it. of course that won't satisfy
you. i won't bring up the other reasons as i will leave them as an
exercise for you. see if you can actually second guess your own thought
processes and see why your view is very wrong about string eval. this
will be amusing to see your head go pop! :)

uri
 
R

Randal L. Schwartz

Rainer> ... then you can effectively hardwire it by using eval to run the Perl
Rainer> compiler to create suitable subroutine at runtime.

You can just as easily do this:

{
my $class = "determine class somehow";
*maker = sub { return $class->new->add(@_) };
}

my $object = maker(@values); # uses $class->new, baked in.

See... you *still* don't need to invoke the compiler at runtime.

Rainer> I really don't know why you think that running the Perl compiler from
Rainer> within Perl-code in order to create new compiled code should be
Rainer> avoided. I'll happily learn the reason for that, though.

Keep reading. I'm not going to repeat things that have been said
repeatedly in the literature for at least a dozen years.

You do *not* need to use the compiler at runtime for anything where a
closure will work, and a closure is preferred.

print "Just another Perl hacker,"; # the original
 
R

Rainer Weikusat

Uri Guttman said:
RW> I really don't know why you think that running the Perl compiler from
RW> within Perl-code in order to create new compiled code should be
RW> avoided. I'll happily learn the reason for that, though.

you have shown a massive unwillingness to learn from anyone here.

I have (and do) show 'a massive unwillingness' to accept anything from
anyone without complete information (IOW not "I know something you
don't know") and a sensible reason for it.
why should that change now? eval string is nasty and evil for many reasons,
most of them pretty obvious too.

"I know something you don't know" (and I'm not going to tell it to
you, either).
the first one is it is rarely needed as you can almost always do
things without it.

eval with a string argument can be used to create compiled code at run
time. Insofar you have a specific reason why you think something's
wrong with that (and this specific reason happens to make sense), I
will, as I wrote, happily listen to it and accept it.

As for you usual idle boasting and insults,
of course that won't satisfy you. i won't bring up the other reasons
as i will leave them as an exercise for you. see if you can actually
second guess your own thought processes and see why your view is
very wrong about string eval. this will be amusing to see your head
go pop! :)

you are free to stick them somewhere where the sun doesn't shine.
 
R

Rainer Weikusat

Rainer> ... then you can effectively hardwire it by using eval to run the Perl
Rainer> compiler to create suitable subroutine at runtime.

You can just as easily do this:

{
my $class = "determine class somehow";
*maker = sub { return $class->new->add(@_) };
}

my $object = maker(@values); # uses $class->new, baked in.

See... you *still* don't need to invoke the compiler at runtime.

The whole point of this exercise is to avoid the runtime overhead of
keeping the $class scalar around and determining its value each time
the closure is invoked: Perl supports dynamic code generation, albeit
in a somewhat more contorted way than, say, Lisp, because Perl isn't
directly capable of modifying Perl-code at runtime, it can just
evaluate strings containing Perl-code. Consequently, in a situation
like the one above, it is possible to compile a dynamically created
subroutine which just performs the intended operation instead of using
a more general subroutine which could also perform other operations
but without this feature ever being used.
Rainer> I really don't know why you think that running the Perl compiler from
Rainer> within Perl-code in order to create new compiled code should be
Rainer> avoided. I'll happily learn the reason for that, though.

Keep reading. I'm not going to repeat things that have been said
repeatedly in the literature for at least a dozen years.

You do *not* need to use the compiler at runtime for anything where a
closure will work, and a closure is preferred.

Considering the output of this little program:

---------------
#!/usr/bin/perl

use Benchmark;
use Devel::peek;

sub make_closure($)
{
my $v = $_[0];
return sub { return $v + 1; };
}

sub make_sub($)
{
return eval "sub { return $_[0] + 1; }";
}

*cl = make_closure(3);
*su = make_sub(3);

print STDERR ("The closure\n");
DumpWithOP(\&cl);

print STDERR ("\nThe sub\n");
DumpWithOP(\&su);

print("\n");

timethese(-10, {
cl => sub { cl(); },
su => sub { su(); }});
---------------

the ordinary (but dynamically created) subroutine looks perferrable,
at least for anything which is kept around for a long time and/or much
more often executed than created. So, why should a closure be
preferred?

NB: "Stupid guy whose head will explode trying to follow MY superior
intellect" doesn't quite cut it since stupidity is pretty much a
precondition for arrogance.
 
R

Rainer Weikusat

[...]

Rainer> I really don't know why you think that running the Perl compiler from
Rainer> within Perl-code in order to create new compiled code should be
Rainer> avoided. I'll happily learn the reason for that, though.

Keep reading. I'm not going to repeat things that have been said
repeatedly in the literature for at least a dozen years.

Out of curiosity, I've now also done a very cursory 'literature
search': The Camel-book, considering its usual 'no bullshit' approach
to technology', contains nothing applicable to this particular way of
using eval. Something which is easily available on the web,

http://docstore.mik.ua/orelly/perl/advprog

has a quite enthusiastic chapter on eval,

http://docstore.mik.ua/orelly/perl/advprog/ch05_01.htm

containing the following statement:

For me, Perl's run-time evaluation capability is one of the
biggest reasons for using the language. I use run-time
evaluation for creating little snippets of code on the fly,
which then execute at typical Perl speeds (i.e., fast!), for
writing sophisticated interpreters for little languages. The
eval function is the gateway to this power.

Lastly, I also found this:

No. Do not resort to eval-string if other means are
available. You're firing up the compiler (slower than almost
any other solution), and exposing yourself to hard to debug
and hard to secure practices.
http://www.perlmonks.org/?node_id=405165

While this statement is arguably true (Imagine that it even provides a
reason and not just a commandment!) it is also not really applicable
when using the compiler to compile some frequently executed piece of
code in order to reduce the time needed to execute it: Doing a very
unscientific experiment (meaning, "just ran it once"), the eval is
indeed about an order of magnitude slower than the closure-creation
but this will amortize itself (insofar total CPU time used is
concerned) if the completely compiled function is called more than
about 213 times. Also, there are of course situations where one
instance of 'doing something' with a relatively high latency in order
to have a lower latency when 'doing something' in future is a sensible
tradeoff.

I feel like closing this posting with a German paragraph because I'd
like to use an absolutely untranslatable 'Daniel Duesentrieb' quote
in it (that's Gyro Gearloose in English)

"In des tumben Toren Hand ist jedes Werkzeug Tand" ist sicher
zutreffend. Allerdings nicht der Umkehrschluss das jeder, der ein
Werkzeug in die Hand nimmt, wohl ein tumber Tor sein muesse ...
 
M

Mart van de Wege

Rainer Weikusat said:
"Rainer" == Rainer Weikusat <[email protected]> writes:
[...]

Rainer> I really don't know why you think that running the Perl compiler from
Rainer> within Perl-code in order to create new compiled code should be
Rainer> avoided. I'll happily learn the reason for that, though.

Keep reading. I'm not going to repeat things that have been said
repeatedly in the literature for at least a dozen years.

Out of curiosity, I've now also done a very cursory 'literature
search': The Camel-book, considering its usual 'no bullshit' approach
to technology', contains nothing applicable to this particular way of
using eval. Something which is easily available on the web,

http://docstore.mik.ua/orelly/perl/advprog

has a quite enthusiastic chapter on eval,

Yes, and also a chapter on direct manipulation of the symbol table.

Unless you think that is also a good practice to use regularly, I think
you're missing the point.

Using string eval to dynamically load a class is an obsolescent
trick. If you want to do this, you're better off using Class::MOP or
Moose.

Mart
 
R

Rainer Weikusat

Mart van de Wege said:
Rainer Weikusat said:
[...]

Rainer> I really don't know why you think that running the Perl compiler from
Rainer> within Perl-code in order to create new compiled code should be
Rainer> avoided. I'll happily learn the reason for that, though.

Keep reading. I'm not going to repeat things that have been said
repeatedly in the literature for at least a dozen years.

Out of curiosity, I've now also done a very cursory 'literature
search': The Camel-book, considering its usual 'no bullshit' approach
to technology', contains nothing applicable to this particular way of
using eval. Something which is easily available on the web,

http://docstore.mik.ua/orelly/perl/advprog

has a quite enthusiastic chapter on eval,

Yes, and also a chapter on direct manipulation of the symbol table.

Another very useful thing, since it enable construction of state
machines without explicit state interpretation logic (and various
other useful features).

[...]
Using string eval to dynamically load a class is an obsolescent
trick.

Since I was writing about running the Perl compiler in order to create
compiled subroutines at runtime, could you perhaps enlighthen me what
the heck you are referring to?
 
R

Randal L. Schwartz

Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of
Rainer> using eval. Something which is easily available on the web,

Rainer> [REDACTED]

I really, really, really don't appreciate people posting URLs to pirated
copies of O'Reilly books.

If that doesn't end you up in a bunch of killfiles, I'm not sure what
does.

{Hrmph.}
 
U

Uri Guttman

Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of
Rainer> using eval. Something which is easily available on the web,

Rainer> [REDACTED]

RLS> I really, really, really don't appreciate people posting URLs to pirated
RLS> copies of O'Reilly books.

RLS> If that doesn't end you up in a bunch of killfiles, I'm not sure what
RLS> does.

RLS> {Hrmph.}

on top of that he takes what he reads as gospel and doesn't think about
the consequences. or allow actual other views to penetrate. not someone
who engenders the idea of good coding practices. but of course he will
defend his views to the death without ever listening to anything else.

uri
 
R

Rainer Weikusat

Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of
Rainer> using eval. Something which is easily available on the web,

Rainer> [REDACTED]

I really, really, really don't appreciate people posting URLs to pirated
copies of O'Reilly books.

I have no idea if this is 'a pirated copy' or a legal one (given the
age of the book, the latter is at least not completely
impossible). You referred to 'literature'. Consequently, I used Google
to search for 'perl eval string' and this is one of the results that
came back. It is pretty ridicolous to try to hold me personally
responsible that someone from Canada (AFAIK) but something on the web
which can be found by using a search engine.
If that doesn't end you up in a bunch of killfiles, I'm not sure what
does.

That someone completely unknown to me did something in some country
which you believe to be illegal? That's beyond pathetic. If you
consider this serious enough, get in touch with the aggrieved party
and tell them about the link so that they can take whatever action
they consider to be necessary or sensible.#
 
R

Rainer Weikusat

Uri Guttman said:
Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of> Rainer> using eval. Something which is easily available on the web,
Rainer> [REDACTED]
RLS> I really, really, really don't appreciate people posting URLs to pirated
RLS> copies of O'Reilly books.

RLS> If that doesn't end you up in a bunch of killfiles, I'm not sure what
RLS> does.

RLS> {Hrmph.}

on top of that he takes what he reads as gospel and doesn't think about
the consequences.

You posted an opinion. Without bothering to argue in favor of it. I
posted another opinion different from yours. This demonstrates that
there is no universal consensus on this topic, as opposed to what you
tried to suggest. I doesn't communicate anything about me.
or allow actual other views to penetrate. not someone
who engenders the idea of good coding practices.

For as long as you think that making derogatory summary statements
about others in public suits you more than trying to argue in favor of
your opinions, you cannot seriously expect to be taken seriously.
 
R

Rainer Weikusat

Tad McClellan said:
Rainer Weikusat said:
Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of
Rainer> using eval. Something which is easily available on the web,

Rainer> [REDACTED]

I really, really, really don't appreciate people posting URLs to pirated
copies of O'Reilly books.

I have no idea if this is 'a pirated copy' or a legal one (given the
age of the book, the latter is at least not completely
impossible). You referred to 'literature'. Consequently, I used Google
to search for 'perl eval string' and this is one of the results that
came back. It is pretty ridicolous to try to hold me personally
responsible that someone from Canada (AFAIK) but something on the web
which can be found by using a search engine.

It is perfectly sensible to hold you responsible for
driving traffic to illegal content by linking to it.

I have no way to determine the legal status of something returned by a
Google search and - using your logic - it must thus be perfectly
sensible to hold Google responsible for 'driving traffic to illegal
content' by linking to it. If this is actually an illegal copy, the
copyright holder needs to deal with that if he so desires. So, please
contact O'Reilly and suggest that they should type 'advanced perl
programming' into a Google search box and 'do something about
that'. That's their responsibility and neither mine nor yours.
 
R

Rainer Weikusat

Rainer Weikusat said:
Tad McClellan said:
Rainer Weikusat said:
(e-mail address removed) (Randal L. Schwartz) writes:

Rainer> Out of curiosity, I've now also done a very cursory 'literature
Rainer> search': The Camel-book, considering its usual 'no bullshit' approach
Rainer> to technology', contains nothing applicable to this particular way of
Rainer> using eval. Something which is easily available on the web,

Rainer> [REDACTED]

I really, really, really don't appreciate people posting URLs to pirated
copies of O'Reilly books.

I have no idea if this is 'a pirated copy' or a legal one (given the
age of the book, the latter is at least not completely
impossible). You referred to 'literature'. Consequently, I used Google
to search for 'perl eval string' and this is one of the results that
came back. It is pretty ridicolous to try to hold me personally
responsible that someone from Canada (AFAIK) but something on the web
which can be found by using a search engine.

It is perfectly sensible to hold you responsible for
driving traffic to illegal content by linking to it.

I have no way to determine the legal status of something returned by a
Google search and - using your logic - it must thus be perfectly
sensible to hold Google responsible for 'driving traffic to illegal
content' by linking to it.

Additional remark: According to

http://oreilly.com/store/complete.html

it isn't even possible to order the first edition of this book from
O'Reilly anymore, at least not online. Used copies sell for as little
as £1.57. Given that it is fourteen years old and thus, massively
outdated in many respects, that's not exactly surprising. This is a
resource which is mainly of historical/ cultural interest and I'd
wager a bet the the publisher considers the commercial value of this
text to be essentially zero. Which leads to the following nice
statement:

Yow! Legally-imposed CULTURE-reduction is CABBAGE-BRAINED!

NB: I have exactly no proof that the publisher is actually interested
in 'Legally-imposed CULTURE-reduction' but perhaps the gentlemen who
claimed to know that he is would be so kind to provide one.
 

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

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top