Dynamic scoping/binding of variables has a bad name, rather like GOTO and other remnants of the Bad Old Days before Structured Programming saved us all1. But there are times when dynamic binding is useful and looking around it is very common in web scripting languages, event propagation, meta-level programming, and document styles.
So is it really so bad?
tiny-screen coding and literate programming
This issue came to mind because I’ve been considering what programming language support might be like for tiny screens (and I mean mobile phone not laptop!). This was prompted by group discussions at the Mobile Design Dialogue conference last year2 and at a bootcamp session at the Winter School on Interactive Technologies in Bangalore in February.
One of my first thoughts was that something akin to literate programming might provide a useful contribution as it allows details to be elided. For example:
@{obtain email address from form variables} if @{check email address valid} then @{produce bad email error message} else @{send email message}
The placeholders (such as “check email address valid”) are then defined separately. In Knuth’s original WEB (and Harold Thimbleby’s cweb), all the definitions are in a single file, but in a phone-based environment this would be more like a hypertext — indeed reminiscent of the code browsers I worked on when I first came into computer science!
Using this form of named fragments would mean that one could have much smaller snippets of code on screen at any moment of time, basically substituting abstraction for scrolling, hence the reason for thinking this could be good for tiny-screen coding.
However, the semantics of these fragments in literate programming is textual inclusion, basically macro expansion. Amongst other things this means effectively dynamic scoping; for example, the code “obtain email address from form variables” might define a variable “email” that is then used in “send email message “.
However, the dynamic scoping is quite limited as the code fragments were always (or maybe normally) only used in one place, that is they are merely a way of hiding code. This is quite different from a piece of code that takes different meaning wherever you place it dependent on what variables it picks up.
scripts and templates
As I began to think about this I recalled early templating languages I developed for code generation from data types (somewhat similar to current web scripting languages). In these I used abstractions that were partly like a procedure, but also, similar to literate programming, in that ‘parameters’ could be extracted from context if not given explicitly. In the example earlier a ‘procedure’ like “check email address valid ” might have an explicit parameter ’email’, but this would be taken from the environment if it was not set explicitly. This reflects the fact that in many situations there is an ‘obvious’ parameter, just as in day to day life you just say “post the letter”, not “post the letter that is on the hall table just where you will obviously find it as you go out and where I always put it”.
While this still seems a little heretical when implemented as part of a programming language (or at least templating script), in fact it is common at the meta-coding level of ‘includes’ found in most web scripting including JSP. For example in PHP one might write:
<?php foreach ( $messages as $message ) { include "format-message.php"; } ?>
The PHP code in the file ” format-message.php ” is effectively textually included inside the ‘foreach’ block and hence ‘$message’ would be available to it as a variable. While the base language is largely lexically scoped, the includes effectively allow an alternative abstraction with dynamic binding. Purists would might decry the above code, but few have not used something similar at some point. Indeed the WordPress plugin system depends entirely on careful use of such constructs.
In my websites (e.g. hcibook.com/e3, snipit.org) I typically have a ‘top.php’ function that routes raw URLs to appropriate pages or scripts by use of ‘include’3. Often this performs common start-up actions such as establishing database connections, reading Cookies, or parsing URL path information, and, of course, the results of all of this are then available as context for the included scripts. Sometimes I wrap this in a single global variable $context, but not always (life is short, and the sensible time to code a website shorter!).
aggregate inheritance
In a HTML document, the font of a paragraph is set not by some form of object inheritance based on the class of the <p> tag, but instead on the smallest enclosing block that has an explicit font style. The binding of fonts is in a sense static or even lexical as it is based on where in the document structure the text sits, but it is not about the lexical structure of the CSS, but of the HTML document to which it is applied.
Similarly, in a GUI a mouse click on a button will typically go through a hierarchy where the enclosing elements (screen panel, etc.) get ‘first dibs’ to filter or react to the event, eventually dribbling down to the button itself, and then sometimes back up again with the containers getting a chance to do some sort of ‘after the event’ processing. Just like the font on the page, the meaning of ‘click on button’ cannot be found solely in the class structure of ‘JButton’, but in the dynamic location where it is found.
I don’t know a standard term for this, but I have always called it ‘aggregate inheritance‘ as elements inherit from the containers within which they are aggregated.
While lexical binding is about the structure of the code, normal dynamic binding is about the structure of the process (calling pattern) and aggregate inheritance is about the structure of the data.
the bad and the worse
The reasons for eschewing dynamic binding were partly about efficient compilation of block-structured languages, albeit now with complex object inheritance rules, dynamic binding seems tame! The other reason was semantic as static (and especially lexical) binding allows a limited form of referential transparency, you can tell what a variable means and track the data flow — locality.
Clearly at one stage the jury was still out, indeed one of the innovations (I believe) in Algol 68 was the inclusion of dynamic binding and as late (sic) as 1986 papers were discussing ways of implementing dynamic binding4. However, even Lisp eventually moved to making its default binding static.
Today all major languages use lexical binding — except they don’t. In fact there are numerous workarounds, just like the tortured workarounds we use for GOTO-less code5.
Simple object inheritance is static, but only so long as no one changes the classes you inherit from! Of course OO inheritance is itself often criticised, but is generally accepted as OK6.
In even simple code we also use global variables, which while static in scope certainly allow non-local effects. These are again especially common in web scripting where context seems particularly important. In fact they are so ubiquitous that special language constructs may be used such as PHP’s ‘superglobals‘ or ‘define‘. On the client side also, Javascript code is often replete with globals.
Those using ‘proper’ languages may look down on slack web programming practices. However, the popular singleton pattern or static Class variables (such as in the Java System class) are but globals by another name, and database access and the filesystem again access a large global name space.
But if the problem of dynamic binding is non-locality, surely the worst culprits are pointers and references. Pure functional programming takes referential transparency seriously, is side effect free and so avoids updatable references and pointers. However, few programmers, however pure, are willing to work totally under FP’s strictures7.
Non-locality of reference and effect seems, not just common but ubiquitous. It is dangerous, but that is because it is powerful. This is true of pointers, but equally of variable binding paradigms, the issue is how to ensure understanding and control of non-locality, not to forbid some kinds whilst allowing free reign to others.
context and pipelines
I’ve used the term ‘context’ several times. In ubicomp and intelligent interfaces issues connected with context are critical in interpreting user activity. Similarly, natural language processing and vision at first (many years ago), took a very pure layered approach with each level of processing giving its results to the next up in a pipeline: lexical to syntactic to semantic. However, human interpretation is not so neatly layered8. Both NLP and computer vision became a lot more successful when they allowed downwards paths from semantics back down to lower levels.
Compiler and language design took their form partly based on early models of language, indeed any cross-over between layers of processing was deemed problematic9. Whilst AI seems to have moved on, programming language design does not; in language and the physical world we assume that terms take meaning from context, why not in programming?
using dynamic binding
Recently I was writing shortcodes in a WordPress plugin. Shortcodes are tags in the text of a blog item that can be used as a form of extensible markup. For example “[cite key=Dx09]” in the text might lookup and link to an entry in a bibliographic database10. Some of the codes are stand alone, but some come in pairs
Being a typical hacker, I first of all created a generic helper plug-in (SimpleShortcodeHandler) that made it easy to do simple things like add a span or div with a specific class. However, I was aware that I might want to add more complicated things like a BibTeX-style bibliography list:
[bibliography format=APA"] A. Dix (2009). What's wrong with dynamic binding? Dykstra, E. (1968). GoTo … [/bibliography]
The behaviour of the ‘‘ codes would clearly need to depend on the format of the bibliography, but the normal shortcode extension mechanism means (as in all good programming!) the code to process each shortcode is in isolation applied to its own text. As a simple addition, the SimpleShortcodeHandler class keeps a stack of enclosing shortcodes in a post so that the handler for ‘bibitem’ can query the stack for the most recent enclosing ‘bibliography’ tag. That is, I added a workaround for dynamic binding in the program code to enable aggregate inheritance in the blog post.
In fact, the way WordPress processes shortcodes means that the code for ‘bibitem’ is called within a call to the expansion code for ‘bibliography’, however, there are intervening calls to WordPress’ internal functions, so one cannot simply pass in context information as an additional parameter.
Similar but more complex issues arise when dealing with sessions in web applications, AJAX programming, or other asynchronous remote procedure calls, all of which are basically an extreme case of program inversion as found following structure clash in old Jackson Structured Programming, or more generally in co-routine-based coding.
adding dynamic binding to the language
There seem to be two forms of dynamic binding that are commonly used.
The first is shallow dynamic binding, for things like the literate programming and PHP includes. Here the dynamic binding is almost a form of implicit parameter passing, a convenient shortcut for writing code like:
function do_some_work_to_x(x) { . . . } // . . . later in the code x = 3; do_some_work_to_x(x);
The expanded code may update variables as well as use their values, but that is then like passing variables by reference.
When using PHP includes that are doing work (e.g. web page templates, as opposed to declaring functions) I usually add a comment block at the top saying what variables it expects to find in its environment. There is no reason why this should not be made more explicit, whether hand written, or generated by a programming environment.
The second form is deep dynamic binding as in the shortcode stack described above, and indeed in many forms of meta-level programming where there is aggregate inheritance on a data structure. In these examples, the dynamic binding is to variables that are connected to a module or similar namespace, but where the scoping of the namespace is not the call structure.
In the shortcode example, this simply was a means to pass information up and down to related functions, ‘skipping’ other ‘foreign’ functions on the way.
However, in other cases there may be a more complex pattern of scoping the context. A simple example would be for having variable ‘constants’ in a mathematical function class:
module Math { context { precision = 0.0001; base = 10; } sqrt(x) { y = 1; while ( abs(y*y-x)> precision ) y = (y+x/y)/2; return y; } }
Then in the calling code something like:
Math.push_context; Math.precision=0.1; z = sqrt(2); Math.pop_context;
To some extent this form of deep context is relatively easy to manage through coding patterns, but the ubiquity in transactional, asynchronous and co-routine programming, suggests deeper infrastructure support would be useful.
in short
In dealing with the lack of good mechanisms for dynamic binding, programmers are often forced into workarounds that are worse than if there were a simple way to do it in the language. The non-locality problems of dynamic binding are also present in other accepted programming constructs such as pointers. On the other hand, there are many contexts, especially in web programming, where forms of dynamic binding lead to neater, more comprehensible, and hence more robust and maintainable code. Dynamic programming can be dangerous and the overall approach of the past 20 years has been to hope it will go away. However, its ubiquity and utility suggests that including support for safe and appropriate dynamic binding in tools, frameworks or languages (and the three can be conflated) may be a better approach for the future.
- Strangely also the days when major advances in substance seemed to be more important than minor advances in nomenclature[back]
- Recently Ken Banks, Matt Jones and Gary Marsden who proposed the MDD discussion are amongst the partners in a new project ‘mobility‘, which is planning to work on mobile-based programming tools.[back]
- Similar to the pattern proposed by Joseph Scott in “PHP URL Routing (PUR)“[back]
- e.g. Gantenbein, R. E. and Jones, D. W. 1986. Dynamic binding of separately compiled objects under program control. In Proceedings of the 1986 ACM Fourteenth Annual Conference on Computer Science (Cincinnati, Ohio, United States). CSC ’86. ACM, New York, NY, 287-292. DOI= http://doi.acm.org/10.1145/324634.325436[back]
- The argument for avoiding where possible GOTOs was of course clearly made by Dijkstra in “Go To Statement Considered Harmful” (Communications of the ACM, Vol. 11, No. 3, March 1968, pp. 147-148). However, see the example of an LR parser in David Tribble‘s commentary on Dijkstra’s paper. The parser would typically be coded now-a-days using a number of state variables, obfuscating the meaning far more than the controlled use of GOTO.[back]
- Oddly, whilst inheritance is deemed OK, for some reason mix-ins are avoided in Java and indeed most modern OO languages. This seems to be due to some of the semantic quagmire of multiple-inheritance, but mix-ins can be made semantically innocuous and would be so useful! To some extent Aspect-Oriented Programming has some of the feel of mix-ins, and can be used to solve some similar problems; however it too brings issues of locality and transparency.[back]
- Although Google’s MapReduce shows functional programming can be very powerful. Having worked with FP people for many years, I find much of my own code has an FP feel.[back]
- In particular, semantic levels of processing ‘pass down’ context to lower levels so that they ‘know what to expect’ and so can disambiguate stimuli. To some extent we see and hear what we expect, hence various forms of optical illusion.[back]
- For example, in K&R C, the expression: “kind (*fun)();” is syntactically ambiguous unless you know whether ‘kind’ is a user defined type. This rare cross-over between syntax and semantics was seen as a weakness in the language.[back]
- I’m writing plugin’s to help write the TouchIT book[back]
Pingback: Alan’s blog » fix for Wordpress shortcode bug