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

I read this multiple times and I still have no idea what you are trying to explain with all that code.

Could you please elaborate?

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

  • Comment on Re^3: Aren't there code refs as well as function refs?

Replies are listed 'Best First'.
Re^4: Aren't there code refs as well as function refs?
by harangzsolt33 (Deacon) on Mar 04, 2023 at 15:13 UTC
    Okay, I wrote a function called DrawPattern() which reads a string and calls PrintPattern() for each character read. This PrintPattern() function is responsible for printing the characters. The way it works is this: For each even numbered character, it prints N number of spaces, and for each odd numbered characters, it prints N number of '#' signs. So, this function has to know whether we're on even or odd numbered character. And it not only has to know that but it also flips it each time. So, it modifies the state. The function DrawPattern() has a state, which is stored in the $MODE variable. I show three different solutions to accomplish this.

    So, the main issue is how do we modify the state? 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. So, now, in order to make these variables available to each function, you decide to call each function with 30 or so arguments. Your code will get really messy, and you'll start wondering if it had been a better idea to just leave the giant sub as one piece of code.

    A third solution would be to have code refs which are kind of like inline code in C language. You make a declaration at the top of the program #define WHATEVER is going to be replaced with "if (x > 63) { ... }" and from that point on, every time you mention "WHATEVER," it will be replaced with "if (x > 63) { ... }" before compilation begins. It's a very neat feature in C language, but as far as I know, Perl doesn't have that feature. What Perl has is called the eval() function, so we could do something like that.

    We could create a function called WHATEVER() that doesn't do anything but simply returns a block of text. Then you do eval(WHATEVER()); and it gets executed. The trick here is that even though you are writing WHATEVER()'s code, you can make references within WHATEVER() to the caller's private variables, and when you execute it using eval(), it will run like it's part of the parent function. So, even though you have sliced the code up into smaller functions, you can still reference the parent's variables. You don't have to pass every variable as an argument.

    (The problem is when you put this into a loop, there is a considerable loss of performance when you run eval() over and over again. Using a function call is slower than having one giant sub, but using a function call PLUS eval() together makes things really slow. So, it should not be used inside a loop.)

    sub DrawPattern3 { my ($PATTERN, $LENGTH, $MODE, $c) = GetPattern($_[0]); for (my $i = 0; $i < $LENGTH; $i++) { $c = ord(substr($PATTERN, $i, 1)); eval(WHATEVER()); } } sub WHATEVER { return "if (\$c == 64) { \$MODE = print \"\\n\"; next; }" . " print chr(\$MODE = \$MODE & 1 ? 32 : 35) x \$c; "; }
      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... } }
        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.