Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: Perl templating/macro creating using 'BEGIN'...

by Corion (Patriarch)
on Sep 27, 2010 at 17:04 UTC ( [id://862248]=note: print w/replies, xml ) Need Help??


in reply to Perl templating/macro creating using 'BEGIN'...

BEGIN { sub main_package_vars { foreach(@_) { eval "sub $_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }" } } }

Why do you put this in a BEGIN block? It serves no purpose, at least when Perl looks at it.

Also, why are you using string-eval, when the plain eval works just as well. Also see Class::Accessor.

sub main_package_vars { foreach my $name (@_) { no strict 'refs'; *{ $name } = sub { my $p = shift; $p->{$name} = $_[0] if @_; $p->{$name}; }" } }

In this next snippet from MyPackage, I don't understand why you use string-eval, and also why you try to execute the same statement twice:

BEGIN { eval "*package_vars2 = \*main::main_package_vars"; *package_vars3 = \*main::main_package_vars; }

The subroutine package_vars3 does not exist:

package_vars3( qw(one two three) );

What problem are you trying to solve? Do you want to have a hash using which you get/set variables?

Maybe an object based on a plain hash using AUTOLOAD is already enough? If you want control over what keys get stored, again, see Class::Accessor.</c>

Replies are listed 'Best First'.
Re^2: Perl templating/macro creating using 'BEGIN'...
by perl-diddler (Chaplain) on Sep 27, 2010 at 17:39 UTC
    The first 'main_package_vars' is in a BEGIN block because it is a duplicate of the one below it. I want to move the BEGIN block out of the package declaration and into the 'main' block.

    Then I want to use the package_vars definition in 'main'. I.e. I started with a BEGIN block only in a package like this (which works, but doesn't work if I remove the BEGIN block as you seem(?) to be suggesting).

    #!/usr/bin/perl -w use strict; use feature ':5.10'; package MyPackage; { BEGIN { sub package_vars { foreach(@_) { eval "sub $_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }" } } } package_vars( qw(one two three) ); sub new { my $package=shift; my $parms=$_[0]; my $this={}; foreach(%$parms) { $this->{$_}=$parms->{$_}; } bless $this, $package; } } package main; my $p=new MyPackage({three => 3,}); $p->two(1); printf "two=%d, three=%d\n",$p->two, $p->three;
    Now I try moving the BEGIN block out of the package and into main (thus 'main_package_vars'), and import it's functionality into the local package.

    That's the problem I'm trying to solve. How to have my subroutine definition for 'package_vars' in 'main', and use it from a package, like in this (which doesn't work because package_vars, isn't being 'called' in MyPackage, now that it's been moved to main).

    #!/usr/bin/perl -w use strict; use feature ':5.10'; BEGIN { sub package_vars { foreach(@_) { eval "sub $_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }" } } } package MyPackage; *package_vars=\&main::package_vars; { package_vars( qw(one two three) ); sub new { my $package=shift; my $parms=$_[0]; my $this={}; foreach(%$parms) { $this->{$_}=$parms->{$_}; } bless $this, $package; } } package main; my $p=new MyPackage({three => 3,}); $p->two(1); printf "two=%d, three=%d\n",$p->two, $p->three;
    The first version I posted had samples of the routine package_vars in each location where I could try changing the line that says 'package_vars3( qw(one two three));' to a line without the '3', and, call the original working version, vs. attempts at trying some way to call the version of 'package_vars' that was moved to main.

    Is that more clear?

      Some of the steps you take are somewhat clear, but I'm really wondering about the goal you're trying to reach by these steps. To me, it really seems as if you're trying to duplicate the functionality of Class::Accessor. The usage of Class::Accessor would be:

      package MyPackage; use parent qw(Class::Accessor); __PACKAGE__->mk_accessors(qw(two three)); package main; use strict; my $f = MyPackage->new({three => 3}); $f->two(1); printf "two=%d, three=%d\n",$f->two, $f->three;

      This seems to be your use case, so why reinvent the wheel?

Re^2: Perl templating/macro creating using 'BEGIN'...
by perl-diddler (Chaplain) on Sep 27, 2010 at 17:57 UTC
    Also, why are you using string-eval, when the plain eval works just as well.
    Because it didn't work when I tried it. Perhaps your perl works differently?
    #!/usr/bin/perl -w use strict; use feature ':5.10'; package MyPackage; { BEGIN { sub package_vars { foreach(@_) { eval sub $_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }; } } } package_vars( qw(one two three) ); sub new { my $package=shift; my $parms=$_[0]; my $this={}; foreach(%$parms) { $this->{$_}=$parms->{$_}; } bless $this, $package; } } package main; my $p=new MyPackage({three => 3,}); $p->two(1); printf "two=%d, three=%d\n",$p->two, $p->three;
    I got: Illegal declaration of anonymous subroutine at pck0.pl line 10. What do you get?

      Sorry - you don't even need "plain eval". Just assigning the anonymous subroutine to the glob is all that's needed and creates a named subroutine from the anonymous subroutine.

        Sorry - you don't even need "plain eval". Just assigning the anonymous subroutine to the glob is all that's needed and creates a named subroutine from the anonymous subroutine.
        What glob? (and what anonymous subroutine?)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://862248]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-04-25 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found