In every codebase you run into unique challenges. Space and time complexity are the enterprise programmer’s nemeses, and all too often appear as cousins to another problem: extensibility.
The problem with making anything a solitary factor more expandable is that it increases the complexity required to interface with that feature by at least twice that factor — twice in the sense that time and complexity, remember them?, are lower-bounded to being capable of handling the expansion.
Case in point: The difference between a pre-populated list and one whose values are variant depending on which portions of a codebase are considered “active.” This can pose quite the problem depending on how mission-critical this list is. (After all, this is a science; and all science should be repeatable ad infinity.) But how to retain this ability to accept a near-infinite range of values and manage them in some human-readable way?
Here we find the strengths and weaknesses of a language. In C, everything you touch is memory whether you realize it or not. From byte-pointers to malloc-ed blocks of hard disk, C keeps you up to your elbows in references. Perl scales the complexity back by a good factor, but grabbing references is still do-able: $ref = \$scalar is a direct accessor to the memory allocated by $scalar; and conversely, $val = $$ref gets the value of whatever variable resides at the memory location $ref. Pretty handy if you have an unknown-length set of variables with similar names. Now we have a common variable name we can manipulate without having a half-dozen Eval() functions in our code. (Aside: Eval() is nice, but sneakily evil; it’s slow, offers arbitrary code execution if use improperly, and just plain ugly.) Our syntax highlighters can show us exactly what we meant, and in six months when we’ll use this as the basis for the program’s next feature, we’ll have a much clearer idea of what the hell we wanted to get out of it.
But this is Perl. How do we do this in a language which masks references like PHP? Unfortunately, we can’t go flying around the memory stack as easily as Perl does, but we can get pretty close with a single Eval(). (Aside 2: I know, I just got done bashing Eval(); I haven’t forgotten, but we’re in control of the string this code evaluates, so take a breath.)
PHP offers an arguably more elegant Eval() than most languages, the inline eval. So let’s reassume our situation: an unknown number of similarly-named variables is in our module’s scope and we want an elegant, memorable way to access their values for modulation.
In Perl:
$value_1 = "some important value";
for($i=1; $i < $some_known_upper_bound; $i++) {
$value_variable_name = "value_" . $i;
$value = $$value_variable_name;
# some modulator code
}
In PHP:
$value_1 = "some important value";
for($i = 1; $i < $some_known_upper_bound; $i++) {
$value_variable_name = "value_" . $i;
# the magic...
$value = ${$value_variable_name};
# some modulator code
}
And there you have it. Future proof code that modifies a like-named set of variables with a single, easily understood and aptly named variable.
[...] same decimal separator, or even the same character encoding. The customization is fairly complex, and your portion of the product must accept this. Whether you do this elegantly or not is another [...]
Hey Zack. Very true. Runtime evaluation is extremely handy and one of the beauties of loose typed scripting languanges. In php this also can extend to function and class method names.
if(method_exists($obj, $method))
$result = $obj->{$method}();
or
$function = "nl2br";
echo $function("a\nb");
Recently used this doing some MVC style controllers mapping URLs to models. Obviously, with this kind of flexibility comes responsibility – “eval” style statements can be dangerous without the proper checks and string cleansing.
In more recent versions of PHP, I believe you can also use variables to set classes at runtime just as you can for variables and functions.
@Nate: That’s a very good point, and in fact one of the pillars most MVC frameworks I’ve seen are built on. A well-designed framework leverages its strengths and minimizes its weaknesses, of course; so any language with code generators is perfectly adept at taking advantage. (Lisp is utterly famous for this.)
In the technology market, it’s invaluable to have a language that can adapt as fast as you need it to. Rapid prototyping and tracer bullet-style development require quick thinking and even quicker typing. Eval() makes short work of this.
Case in point: In an MVC with an RDB backend, it’s worth while making a generic linking function in your base object. Leverage what you have: an instantiated object pulled from the DB with an attribute/field which is a valid pointer to another loadable object. By using Eval() to load that object, zipping along your foreign keys can be a relative breeze.