For when a first initial is all you can remember
I saw the movie Inception over the weekend and after reading What a Programmer Sees When He Watches Inception, in which Marke Hallowell compared the dreams-within-dreams concept from the movie to a recursive function, I think I too see parallels between the movie and computer programming. I think a parallel exists between dreams-within-dreams and programs-within-programs.
As you’re watching the movie, especially in the later sequences, you are watching it on four and even five levels. The events that occur on each level have consequences for those levels below it. When the dreaming is over, the lower levels get to return the favor, having consequences on the levels above them by how they changed the dreamers themselves. To follow the movie you need to have an understanding of what is going on at each level.
Similarly in metaprogramming, you need an awareness of what level you are operating on at any given time as well as some knowledge of when and how to mix in elements from other levels. As an example, let’s take one of the simplest possible programs and see what happens when we add more levels through metaprogramming. The example is in SQL PL:
BEGIN CALL DBMS_OUTPUT.PUT_LINE('Hello world!'); END
The output of the program is as you would expect:
Rewriting it into a metaprogram, we can add a second level:
BEGIN EXECUTE IMMEDIATE 'BEGIN CALL DBMS_OUTPUT.PUT_LINE(''Hello world!''); END'; END
Notice that we needed to turn the single-quotes that surround the message into double single-quotes once we embed our original program into a string. Now let’s have the outer world of the meta-program affect the inner world of the program by having it provide part of the message:
BEGIN DECLARE MSG VARCHAR(128) DEFAULT 'world!'; EXECUTE IMMEDIATE 'BEGIN CALL DBMS_OUTPUT.PUT_LINE(''Hello ' || MSG || '''); END'; END
What if we add a third level, or dream-within-a-dream? I have used such techniques to implement a generalized version of the ANY_OF function I described in my post on default parameters, so such meta-metaprogramming techniques can have their use. Let’s see what it does to our Hello World program:
BEGIN EXECUTE IMMEDIATE 'BEGIN DECLARE MSG VARCHAR(128) DEFAULT ''world!''; EXECUTE IMMEDIATE ''BEGIN CALL DBMS_OUTPUT.PUT_LINE(''''Hello '' || MSG || ''''''); END''; END'; END
The conversion was actually pretty straightforward. Just as we double every single-quote when going from program to metaprogram, we double every single-quote again to go from metaprogram to meta-metaprogram, so one single-quote in the original program becomes four single-quotes in the meta-metaprogram. Let’s make the above program a little more interesting by injecting something from the outer world down deep into the innermost world:
BEGIN DECLARE OUTERMSG VARCHAR(128) DEFAULT 'world!'; EXECUTE IMMEDIATE 'BEGIN DECLARE MSG VARCHAR(128) DEFAULT ''' || OUTERMSG || '''; EXECUTE IMMEDIATE ''BEGIN CALL DBMS_OUTPUT.PUT_LINE(''''Hello '' || MSG || ''''''); END''; END'; END
The next step would be to see how something in the deepest inner-world can make it back up into the outermost world, but that’s enough for today. In my next post, I will return to discussing db2top with a new video.