Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re^2: More Macro work...out to export a definition to next-outer level?

by perl-diddler (Hermit)
on Sep 30, 2010 at 08:42 UTC ( #862764=note: print w/ replies, xml ) Need Help??


in reply to Re: More Macro work...out to export a definition to next-outer level?
in thread More Macro work...out to export a definition to next-outer level?

Sorry, you just lost me -- you used a magic spell above my level. ;-)

In my previous example: #!/usr/bin/perl -w #use strict; use feature ':5.10'; BEGIN { sub instance_vars { my $pck=caller; foreach(@_) { eval "sub ${pck}::$_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }" } } } package MyPackage; *instance_vars=\&main::package_vars; { instance_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(2); printf "two=%d, three=%d\n",$p->two, $p->three; </code> I didn't have any reference to use or import.

To invoke the code, I called a sub 'instance_vars', that was in a begin block. The reason the package statements are / were in the way they are is that the macros definitions are at the top of the file in 'main'.

The way you are doing it may be the only way to do it, but it isn't close to as simple as the case for the 'instance' vars.

You say that the above isn't satisfactory for 'singletons'. Why not? Aren't they global variables to each package that are initialized only once on the initial passthrough when the package is first read, and then retain their value as global variables in each package (or accessible via package::var) from without the package?

The part where you put the classname.pm in the INC var likely prevents future 'use' statements from actually trying to find the file, I'd guess, and the 'use' statement does the same as: "package::import( qw(one two three) )"? It's workable, but I don't understand why something simple like I used for instance variables doesn't work.

If putting a BEGIN block around a sub definition is useless, then how does this 'instance' var code work? It puts a sub definition in a BEGIN block which is then called in the code below. Also, the class_vars code *works* (with strict turned off, with warnings -- i.e. the variables being set in 'MyPackage' retain their values -- they aren't local but are treated as package variables, so I don't see how you can the subs don't work

I think you are showing me an alternate way of doing what I'm doing, but I don't think it's answering my question -- which may have no good answer, i.e. the way you are doing it may be the only way -- I don't know.

The 'sub' in main gets declared as a global as all named subs are, so in a BEGIN block or not, I think it is having the desired effect. The problem is adding an 'our' statement that is taken as a declarator for the rest of the block that the caller is in (not just in within the eval -- which is works for, but is ended when the eval ends and goes out of scope.


Comment on Re^2: More Macro work...out to export a definition to next-outer level?
Re^3: More Macro work...out to export a definition to next-outer level?
by perl-diddler (Hermit) on Sep 30, 2010 at 12:13 UTC
    That's lame! I edited the above, even previewed it, and resubmitted it with an inserted 'code' tag (it was missing one before the code, as you can see, it already had one after the code ;-/ ). But only the above version was stored and it seems I can't update it. Oh poo! Anyway, hopefully this version will stay with the code tag intact!
    #!/usr/bin/perl -w #use strict; use feature ':5.10'; BEGIN { sub instance_vars { my $pck=caller; foreach(@_) { eval "sub ${pck}::$_ { my \$p = shift; \$p->{$_} = \$_[0] if \@_; \$p->{$_}; }" } } } package MyPackage; *instance_vars=\&main::instance_vars; { instance_vars( qw(one two three) ); sub new { my $package=shift; my $parms=$_[0]; my $this={}; foreach(%$parms) { $this->{$_}=$parms->{$_}; } bless $this, $package; } } package MyPackagetwo; { our @ISA = qw (MyPackage); } package main; my $p=new MyPackagetwo({three => 3,}); $p->two(2); printf "two=%d, three=%d\n",$p->two, $p->three;
Re^3: More Macro work...out to export a definition to next-outer level?
by ikegami (Pope) on Sep 30, 2010 at 14:58 UTC

    You say that the above isn't satisfactory for 'singletons'.

    Because you're using two screens of fragile and complicated code to replace two lines of code.

    To invoke the code, I called a sub 'instance_vars', that was in a begin block.

    No, it's not in a BEGIN block. The sub's definition is in a BEGIN block, but I already indicates how that's useless.

    Aren't they global variables to each package that are initialized only once

    No, they're initialised by the constructor, any number of times.

    and then retain their value as global variables in each package (or accessible via package::var) from without the package?

    That may be, but you access them via method calls.

    I think you are showing me an alternate way of doing what I'm doing, but I don't think it's answering my question

    I did. Like I said, you called it too late. You only call class_vars after you try to compile the code that uses them. All I did was made a change to call it earlier.

      I think there's a confusion in terms. I'm using class var to mean global to the whole class and each instance of the class. My other routine is an instance_var which declares variables for each instance. For my globals, I'm trying to use the package variables referenced by 'our', that are global to the package. AFAIK, they are globals that come into creation when the package does, and if there is code defining them in the package, with an initializer, it gets executed once when that package loads.

      There shouldn't be multiple initializations

      As far as how I access them: I call them through method calls, meaning I call them through a blessed pointer which I throw away with the shift; Then I store or/and return the global variable passed in from the 'foreach' in '$_' (e.g. one two three), namely the global package variables byte those names.

      Does this clear anything up?

        I think there's a confusion in terms. I'm using class var to mean global to the whole class and each instance of the class.

        The confusion is yours. You've been saying the above, but you haven't been doing the above. Like I said, your instance constructor populates the globals instead of the instance.

        If there's only ever one instance, what you have a singleton, and you've made a mess of things.
        If there can be multiple instances, your code is broken.

        There shouldn't be multiple initializations

        Then they should be initialised outside of any function.

        Does this clear anything up?

        No. I understood fine all along.

        I think there's a confusion in terms. I'm using class var to mean global to the whole class and each instance of the class.

        The confusion is yours. You've been saying the above, but you haven't been doing the above. Like I said, your instance constructor populates the class attributes instead of the instance attributes.

        There shouldn't be multiple initializations

        Then they should be initialised outside of any function.

        Does this clear anything up?

        No. I understood fine all along.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2014-12-27 23:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (177 votes), past polls