Dynamic Code
Suppose you’re writing a computer program. Now suppose you’re writing a specific function within your program, which you want to test every now and then to see how it’s coming out, so you’re able to detect mistakes early on and fix them quickly. What if, to access the functionality that will require that function, you’re forced to wait for a certain amount of time (what if the function/procedure has to wait for a socket to be established, a connection to be handled, a big file to be read…) before you can test it, every single time?
A few months ago, when I was writing the ugly and bloated version of my irc bot (this one here), every functionality I implemented was being tested right away. And since I wasn’t allowing my code to change while the program executed (or, at least, not in memory), I had to quit the bot, run it again, wait for it to connect to the irc server and join the channel I told it to, then run the command that would require the sub routine I was coding. And that’s when I didn’t have to authenticate to do so (typing “/msg nubdj0s auth [password]“).
Back to you. Suppose you could make parts of your program (the parts you’re writing at the moment) editable in a way which would make them be executed right after you changed them, without the need for restarting the program completely (thus loading it in memory again, with the new code). It just so happens that in Perl we can do it.
The magic function of the day is eval(). As you may know, eval() let’s you evaluate (surprised?) Perl code at run time. So all you have to do is store whatever new code you’re writing in a text file, then, instead of including the new code directly in your program, write a simple sub to read that file and eval() each line. Here’s an example:
We’re writing a complex program, which includes a complex sub routine that we want to test many times as we develop it. Such a sub routine must print “Hi! ” followed by a number, 30 times, and such a number must be equivalent to the amount of times we’ve printed “Hi! ” so far (yup, we’re counting). Since the complexity is overwhelming, here’s the code to accomplish that (remember I said we’re writing a subroutine to do this, because in reality our code wouldn’t be so ridiculously simple and useless):
use warnings;
use strict; # we need these because this is complex stuff.
# some perl code...
sub awesome
{
print "Hi! $_\n" for (1..30);
}
# more perl code...
awesome();
And like I said, we want to be able to change awesome() however we want at runtime, and we want our program to load it every time. What we do then is write a text file containing the sub’s code:
dynamiccode.txt
print "Hi! $_\n" for (1..30);
And then, instead of including the sub directly, we write instead a sub that reads the file and eval()s each line, like so:
sub getcode
{
open my $code, shift or return;
eval while ;
close $code;
}
Note that eval() evaluates the expression within $_, since we don’t give it anything explicitly. Now, we can execute our dynamic code like so:
getCode("dynamiccode.txt");
And, sure enough, we would count to 30. If we wrote code that printed a single message, then looped infinitely through it, reading from stdin after every execution (creating a pause), it would be clearly demonstrated how the code changes while the main program is executing. So:
someperlcode.txt
print "\nHi!";
dynamic.pl
use warnings;
use strict;
sub getcode
{
open my $code, shift or return;
eval while ;
close $code;
}
print "\n\n\t Testing dynamically loaded code. \n\n";
&& getcode("someperlcode.txt") while 1;
Sure enough, if you let it print out “Hi!” a few times, then edit someperlcode.txt to change the message while the script runs, you’ll see the change in the output. If we wanted to modify variables declared within dynamic.pl from someperlcode.txt, you very well could, by modifying their declaration with “our”:
someperlcode.txt
print "\nbye!", $var++, "\n";
dynamic.pl
use warnings;
use strict;
our $var = 0;
sub getcode
{
open my $code, shift or return;
eval while ;
close $code;
}
print "\n\n\t Testing dynamically loaded code. \n\n";
&& getcode("someperlcode.txt") while 1;
And there you have it.

No trackbacks yet.