in reply to Re^4: Aren't there code refs as well as function refs?
in thread Aren't there code refs as well as function refs?

Wow, I think you are reinventing wheels but at high rotation. :)

> Imagine that we have a very large sub that does a lot of things and spans hundreds of lines of code. To make that easier to read, you could try to break it up into individual functions. The problem occurs when this large function also has a lot of variables which all need to be seen by the individual sub functions.

Are you aware of the concept of closure variables° in functional programming or instance-variables in OOP?

If yes did you consider using them here?

> A third solution would be to have code refs which are kind of like inline code in C language

These are not code-refs but preprocessor macros.

Actually Perl supports them, but I never saw them used. It might also depend on the existence of an installed C preprocssor.

Another better portable approach are source-filters.

But as I said above, I think there are already better solutions for that. Preprocessor macros are dangerous.

Anyway I'm still unsure in which way all of this was related to the OPs question.

Cheers Rolf
(addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
Wikisyntax for the Monastery

update
°) example

sub huge_function { my $many, $variables, ...; # do something # do something else }

---->

{ my $many, $variables, ...; # accessible inside all closed over s +ubs here sub previously_huge_function { # set $many ... do_something(); do_something_else(); } sub do_something { my $internal_var; # access $many... } sub do_something_else { my $internal_var; # access $many... } }
  • Comment on Re^5: Aren't there code refs as well as function refs? (Update: refactoring very large sub with many variables)
  • Select or Download Code

Replies are listed 'Best First'.
Re^6: Aren't there code refs as well as function refs? (Update: refactoring very large sub with many variables)
by harangzsolt33 (Deacon) on Mar 05, 2023 at 02:57 UTC
    Wow! Wow! I didn't know you could put multiple subs inside a bracket and share variables that way. :-O

    I am stunned!

    Hmm, that means I should have done a lot of things differently. lol

    Well, I guess, folks, just ignore my comments in this post.

      > I didn't know you could put multiple subs inside a bracket and share variables that way

      You don't need the brackets to share variables. But they are limiting the scope the same way like your giant function did before. I tried to guaranty a pain free refactoring.

      FWIW you can also nest multiple layers of brackets. See Coping with Scoping for more.

      The other approach is using OOP.

      kcott also mentioned passing a hash around, that's actually one criteria for needing OOP, because (most) objects are just blessed hashes which are passed inside $self.°

      so this could do too:

      $obj->some_method { my ($self,@args) = @_; print $self-{many}, $self->{variables}; }

      Cheers Rolf
      (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
      Wikisyntax for the Monastery

      °) one criteria of many, it depends on the concrete use case

        because (most) objects are just blessed hashes

        True. Although, as you pointed out, technically not always. As for the classes these objects are blessed with... You can bless a thing with a non-existant class, rewrite the class later on the fly and you are still good.

        use strict; use warnings; use Data::Dumper; # Turn stuff into blessed objects my $foo = 'THIS IS A SCALAR'; my $bar = [qw(THIS IS AN ARRAY)]; my $baz = {'This' => 'Is', 'A' => 'Hash'}; # Bless them with a class that doesn't technically exist yet (and have + Perl autovivify it for us) my $scalarobject = bless \$foo, 'This::Is::A::Dummy::Object'; my $arrayobject = bless $bar, 'This::Is::A::Dummy::Object'; my $hashobject = bless $baz, 'This::Is::A::Dummy::Object'; { # Force the This::Is::A::Dummy::Object class to have a print metho +d that stringifies its own object ;-) no strict 'refs'; *{'This::Is::A::Dummy::Object::stringify'} = sub{ my ($self) = @_; + print Dumper($self); }; } $scalarobject->stringify(); $arrayobject->stringify(); $hashobject->stringify();

        Result:

        $VAR1 = bless( do{\(my $o = 'THIS IS A SCALAR')}, 'This::Is::A::Dummy: +:Object' ); $VAR1 = bless( [ 'THIS', 'IS', 'AN', 'ARRAY' ], 'This::Is::A::Dummy::Object' ); $VAR1 = bless( { 'This' => 'Is', 'A' => 'Hash' }, 'This::Is::A::Dummy::Object' );

        I love that you can do stuff like this. Not usually for production code. Although, come to think of it, it might come in handy for that "rewrite my XML config parser" thing i have had on my todo list for a decade now...

        PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP

      You can do a lot with(1) functions in Perl. If you need a lot of similar one, you don't even have to write them. You can make Perl to do the work for you on startup(2):

      BEGIN { # Auto-magically generate a number of similar functions without ac +tually # writing them down one-by-one. This makes consistent changes much + easier, but # you need perl wizardry level +10 to understand how it works... # # Added wizardry points are gained by this module beeing a parent +class to # all other web modules, so this auto-generated functions are subc +lassed into # every child. my @stdFuncs = qw(prefilter postauthfilter postfilter defaultwebda +ta late_defaultwebdata task loginitem logoutitem sessionrefresh preconnect prerender + lateprerender cleanup authcheck logstart logend logdatadelivery logwebsocket logrequest +finished logstacktrace remotelog sitemap firewall fastredirect); # -- Deep magic begins here... for my $f (@stdFuncs){ #print STDERR "Function " . __PACKAGE__ . "::register_$f will +call add_$f\n"; no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitN +oStrict) *{__PACKAGE__ . "::register_$f"} = sub ($arg1, $arg2) { my $funcname = "add_$f"; confess("No function name specified") unless defined($ +funcname); $arg1->{server}->$funcname($arg1, $arg2); }; } # ... and ends here }

      And as you can see, $f from the for loop gets used in the declaration of the subs. In this case, its value actually gets "baked" into the $funcname string.

      (1) or "to" functions. Depends on your mood and how much compassion you have when you hear the code auditor scream in pain.

      (2) Preferably while wearing ear protectors.

      PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP