<?xml version="1.0" encoding="windows-1252"?>
<node id="222451" title="MOPT-03 - identification, part 1" created="2002-12-26 21:08:01" updated="2005-08-10 10:22:39">
<type id="120">
perlmeditation</type>
<author id="131815">
mstone</author>
<data>
<field name="doctext">
&lt;p&gt;&lt;b&gt;Meditations on Programming Theory
&lt;br&gt;meditation #3:  identification, part 1: variables&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Okay, this is where things get complicated.&lt;/p&gt;

&lt;p&gt;The concept of identification is only the tip of a
tightly-interconnected iceberg.   I'm going to start by blasting my
way through a bunch of vocabulary so you have some idea of where the
major pieces are, then I'll go back and fill in the details.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;(and apologies for slipping schedule by 4 days.. I'll try to be back on 
track with the next one)&lt;/i&gt;&lt;/p&gt;
&lt;readmore&gt;

&lt;h1&gt;Vocabulary:&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;The first piece of the identification iceberg is the concept of
&lt;b&gt;encapsulation.&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;Encapsulation means &lt;b&gt;putting something in a container.&lt;/b&gt;  
When we encapsulate something, we create a boundary that separates
'things on the inside' from 'things on the outside'.   Then we treat
that container, and everything in it, as a single, coherent unit.  
For want of a better term, we call that unit an &lt;b&gt;entity.&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; Encapsulation gives rise to the concept of &lt;b&gt;abstraction.&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;We treat entities differently depending on whether we're looking
at them from the inside or from the outside.   From the inside, an
entity can have any number of pieces.   From the outside, an entity
is a single, irreducible thing.&lt;/p&gt;

&lt;p&gt;The word &lt;b&gt;'abstraction'&lt;/b&gt; means &lt;b&gt;'taking something
away',&lt;/b&gt; and in this case, moving from the inside of an entity to
its outside takes away information about the entity's internal
structure.   We &lt;b&gt;abstract&lt;/b&gt; an entity's structure by putting
those pieces into a container.   The boundary between an entity's
inside and outside, which defines the limits of what we can see, is
called an &lt;b&gt;abstraction barrier.&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Abstraction barriers gives rise to a concept called &lt;b&gt;scope.&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;We can only see the pieces that make up an entity from inside the
entity's abstraction barrier.   For all intents and purposes,
neither the pieces, nor the rules that apply to them, exist outside
that barrier.   The term &lt;b&gt;scope&lt;/b&gt; refers to the region inside
the abstraction barrier, where those pieces and rules do exist.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;An &lt;b&gt;identifier&lt;/b&gt; is a string that represents an entity,
    as seen from outside the abstraction barrier.
&lt;/ul&gt;

&lt;p&gt;Encapsulation and abstraction are powerful concepts, but we can't
actually do much with an entity until we give it a name.   The rule
that associates a specific name with a specific entity is called a
&lt;b&gt;binding,&lt;/b&gt; and bindings give us the concept of
identification.&lt;/p&gt;

&lt;p&gt;Identification gives us two further concepts:
&lt;b&gt;specification&lt;/b&gt; and &lt;b&gt;object permanence.&lt;/b&gt;   Specification
means we have the power to select a specific entity any time we want
it, and object permanence means we can safely assume that we'll get
the same entity every time.   It's hard to overstate the importance
of those two concepts.   If we lose either one, we lose the ability
to solve any but the most trivial of problems.   Most bugs, in fact,
boil down to a failure in of one of those two areas.   An entity
that observes those two principles strictly is said to be
&lt;b&gt;referentially transparent,&lt;/b&gt; and I'll discuss that idea in more
detail later.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; A &lt;b&gt;value&lt;/b&gt; is a string that represents an entity, as
    seen from inside the abstraction barrier.
&lt;/ul&gt;

&lt;p&gt; Identification is all well and good, but computation still boils
down to replacing one string with another.   A name is a string, but
it's a string we apply from the outside.   It tells us that an
entity exists, but nothing more.   We still need a string that
represents whatever's inside the abstraction barrier.   We call that
string a &lt;b&gt;value.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;A value summarizes an entity's internal structure.   Summation is
a form of abstraction, which means that a summary can pass through
an entity's abstraction barrier.   The process of finding a string
that serves as an abstract summary for whatever lives inside an
entity is called &lt;b&gt;evaluation.&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; The association between an entity's name and its value is
    called &lt;b&gt;reference.&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;At this point we have three items to consider:  

&lt;ol&gt;
    &lt;li&gt; an entity
    &lt;li&gt; the name that identifies it
    &lt;li&gt; and the value that summarizes it 
&lt;/ol&gt;

&lt;p&gt;We know that the relationship between the entity and its name is
called identification, and that the relationship between the entity
and its value is called summation.   That still leaves the
relationship between the name and the value, though.   We call that
relationship &lt;b&gt;reference.&lt;/b&gt;   A name identifies its entity, but
we say that it &lt;b&gt;refers to&lt;/b&gt; the entity's value.   The act of
replacing a name with its associated value is called
&lt;b&gt;dereferencing.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Dereferencing is a type of substitution, but it's different from
the kind we saw back in [id://nnnnn|MOPT-02.]   We can't write a
simple "replace this string with that string" rule to represent it. 
 Dereferencing is the form of substitution that crosses an
abstraction barrier, and is &lt;i&gt;much&lt;/i&gt; more powerful than the
"replace this string with that string" kind.&lt;/p&gt;


&lt;h1&gt;Discussion:&lt;/h1&gt;

&lt;p&gt;Now that we have all those terms out on the table, entities tend
to fall into one of two general categories:  &lt;b&gt;variables&lt;/b&gt; and
&lt;b&gt;functions.&lt;/b&gt;   The distinction is an arbitrary one, though.  
Technically we could say that variables are just a special kind of
function, or that functions are just a special kind of variable.  
Either version works, but it's easier to describe certain ideas if
we think of variables and functions as different kinds of
entities.&lt;/p&gt;

&lt;h2&gt;variables:&lt;/h2&gt;

&lt;p&gt;I should start by saying that this kind of variable has very
little to do with the &lt;tt&gt;'$x'&lt;/tt&gt; structures that Perl programmers
call 'variables'.   When programmers think about variables, they
tend to think about addressable blocks of mutable storage.  
Officially, those are called &lt;b&gt;lvalues&lt;/b&gt; because they can appear
on the left-hand side of an assignment expression.   For the
purposes of this discussion, &lt;b&gt;lvalues are not variables.&lt;/b&gt;  
Lvalues can do things that variables can't (i.e: violate the
principle of referential transparency), which gives rise to
unsolvable problems.&lt;/p&gt;

&lt;p&gt;&amp;lt;digression&amp;gt;

&lt;br&gt;Functional programming languages try to eliminate those problems
by getting rid of lvalues entirely.    The results are subject to
debate.   Functional languages do encourage good programming habits
by 'Huffmann coding' them appropriately (making good things easy to
do, and bad things hard to do), but they're hardly immune to the
problems that lvalues pose, as some advocates would like to believe.
  It's also worth noting that the principle of referential
transparency raises its own unsolvable problems when applied to the
subjects of concurrent or distributed processing.&lt;/p&gt;

&lt;p&gt;As Larry Wall once said, "Perl is a mess because the problem
space is a mess," and it's easy enough to use Perl in a
referentially transparent way.

&lt;br&gt;&amp;lt;/digression&amp;gt;&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;For the sake of this discussion, &lt;b&gt;a variable is an entity
    that can have some value, but isn't restricted to any specific
    value.&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;Variables represent the concept of picking a single value out of
a set of possible values.   The set of all values a variable can
possibly have is called the variable's &lt;b&gt;type,&lt;/b&gt; and I'll talk
about types in a minute.&lt;/p&gt;

&lt;p&gt;We use the term &lt;b&gt;raw variable&lt;/b&gt; to describe the situation
where we know a variable's type, but not its value.   A raw variable
is an abstraction of its type, having all the characteristics common
to every item of that type, but none of the characteristics that
make one item different from another.   If you happen to be into set
theory, a raw variable is an abstraction which represents the
intersection of all characteristics belonging to every member of its
type.&lt;/p&gt;

&lt;p&gt;Raw variables are useful, because they let us define 'generic'
operations that appply to every member of a type.   We'll get a lot
of mileage out of raw variables when start talking about
functions.&lt;/p&gt;

&lt;h3&gt;variables and type:&lt;/h3&gt;

&lt;p&gt;As I mentioned before, a type is the set of all values a variable
can possibly have.   If we take that idea all the way back to the
level of human assumptions, &lt;b&gt;a type tells us everything we can
safely assume about a variable.&lt;/b&gt;   A type is an information
space, and we can represent that space with an appropriately defined
language.&lt;/p&gt;

&lt;p&gt;Now before anyone tries to make this point for me:  Perl
&lt;i&gt;does&lt;/i&gt; happen to use a very relaxed type system.   The
interpreter does a lot of work behind the scenes to make sure a
given value supports as many reasonable-to-a-human assumptions as
possible.   That doesn't make Perl a 'weak and sloppy' language, as
advocates of strictly-typed languages sometimes imply, but it
doesn't mean Perl programmers can ignore type systems, either.&lt;/p&gt;

&lt;p&gt;Perl is a language for big kids, the way unix is an operating
system for grownups.   Perl acknowledges the fact that defining a
type system is just as hard as writing the program itself, and that
"one size fits all" type systems tend to fit everyone equally badly.
  Perl gives programmers both the freedom and the responsibility to
define their own type systems wherever those systems happen to be
necessary.&lt;/p&gt;

&lt;p&gt;From a theoretical standpoint, the most interesting part of that
whole rant was the statement, "defining a type system is just as
hard as writing the program itself."   That's true, but it takes a
bit of work to show how and why.&lt;/p&gt;

&lt;p&gt;As I mentioned above, a type is an information space, and we can
represent that space with a language.   We use formal systems to
generate languages, so there must be some kind of connection between
types and formal systems.&lt;/p&gt;

&lt;p&gt;That connection is called a &lt;b&gt;decision problem.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;A decision problem is a question you can answer with a simple
'yes' or 'no'.   The question "is this value defined for this type?"
is a decision problem.   Since we represent sets with languages, and
generate languages using formal systems, deciding whether a value is
defined for a given type boils down to the decision problem, &lt;b&gt;"is
this string a theorem?"&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;As we saw in MOPT-02, the process of deriving theorems is called
&lt;b&gt;computation.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Now, as it turns out, it's much harder to prove that a string is
a theorem than it is to derive a theorem from an axiom.   In fact,
it's half-way impossible.   All we can do is generate theorems, and
compare them to the one we want to prove.   Eventually (by which I
mean "some time between now and forever"), we'll generate every
theorem that &lt;i&gt;can&lt;/i&gt; be computed, and if one of them matches our
candidate, we can stop with an answer of 'yes'.   We don't have any
way to stop with an answer of 'no', though.&lt;/p&gt;

&lt;p&gt;Theorem proving belongs to a set of problems that are called
&lt;b&gt;partially decidable,&lt;/b&gt; or &lt;b&gt;recursively enumerable.&lt;/b&gt;  
We'll run into those terms again when we start looking at the kinds
of problems we can solve with various tools.   For now, it's enough
to know that the only way to decide whether a value is defined for
some type is to build a set of theorems up from their
axioms.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;We generally do that using raw variables.   We start with a bunch
of axioms of the form:&lt;/p&gt;

&lt;code&gt;
    If we apply operation X to a variable of type Y, 
    we get a variable of type Z.
&lt;/code&gt;

&lt;p&gt;which usually gets collapsed to the form:&lt;/p&gt;

&lt;code&gt;
    X(Y) : Z
&lt;/code&gt;

&lt;p&gt;and then we start combining those rules to establish the limits
of what's possible.   We have to know what the operations are,
though, and we have to break them down in sufficient detail to prove
that &lt;tt&gt;X(Y)&lt;/tt&gt; really does generate &lt;tt&gt;Z.&lt;/tt&gt;    By the time
we've done that, we've built a microscopically-detailed
specification for the actual program.&lt;/p&gt;

&lt;p&gt;Type systems are actually quite useful as design tools.   They
give us a way to keep track of our assumptions without getting
bogged down in the details of implementation.   They also give us
line-by-line suggestions about testing and error handling
procedures.&lt;/p&gt;

&lt;h3&gt;variables and scope:&lt;/h3&gt;

&lt;p&gt;So.. we know that types can be cool, and that a variable can
adopt any value appropriate to its type.   The trick of working with
values is keeping track of when and where they're defined.&lt;/p&gt;

&lt;p&gt;Both the entity that acts as a variable, and the name that acts
as that variable's identifier, can be defined within the scope of
some other entity (called a &lt;b&gt;parent&lt;/b&gt;) (1).   If they are, they
only have meaning within that parent's abstraction barrier, which
means that they're subject to scope limitations.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;(1) - A variable's value, of course, will always be defined in
the same scope as its name.   We have to replace the one with the
other, after all.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;An identifier that lives in a different scope than the entity
it's bound to is called a &lt;b&gt;free variable.&lt;/b&gt;   Free variables
aren't bound to any entity at all by the terms of their definition,
so it's up to the compiler and runtime environment to work out a
binding.   The rules the compiler and runtime environment use to
establish that binding are called &lt;b&gt;scope rules.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Perl has four different sets of scope rules:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; &lt;b&gt;Global scope rules&lt;/b&gt;
    &lt;li&gt; &lt;b&gt;Local scope rules&lt;/b&gt;
    &lt;li&gt; &lt;b&gt;Lexical scope rules&lt;/b&gt;
    &lt;li&gt; and &lt;b&gt;Package scope rules&lt;/b&gt;
&lt;/ul&gt;

&lt;p&gt;which cover most of the options available in any language.&lt;/p&gt;

&lt;p&gt;Under &lt;b&gt;global scope rules,&lt;/b&gt; every occurrence of the same
name is bound to the same entity.   That entity is defined in the
outermost parent, regardless of where the variable is first defined.
  Global scoping is also called &lt;b&gt;static scoping,&lt;/b&gt; because the
binding between the identifier and the entity never changes.   The
compiler can create the entity at compile time, and bind every
instance of the identifier it sees to that entity as it works its
way through the code.&lt;/p&gt;

&lt;p&gt;The following code, which demonstrates global binding:&lt;/p&gt;

&lt;code&gt;
    $GLOBAL  = "static";
    $LOCAL   = "dynamic";
    $LEXICAL = "lexical";
    
    sub show_evaluation_context {
        printf (
            "evaluation context:  %s \n",
            join (',', ($GLOBAL, $LOCAL, $LEXICAL))
        );
    }
    
    sub global_scope {
        printf (
            "global scope:        %s \n",
            join (',', ($GLOBAL, $LOCAL, $LEXICAL))
        );
        show_evaluation_context();
    }
    
    global_scope();
&lt;/code&gt;

&lt;p&gt;produces the following ouput:&lt;/p&gt;

&lt;code&gt;
    global scope:        static,dynamic,lexical 
    evaluation context:  static,dynamic,lexical
&lt;/code&gt;

&lt;p&gt;which is pretty much what we'd expect.&lt;/p&gt;

&lt;p&gt;Perl's &lt;b&gt;local scope rules&lt;/b&gt; create a new entity every time
the &lt;tt&gt;local()&lt;/tt&gt; keyword is executed.   Local scoping is also
known as &lt;b&gt;dynamic scoping,&lt;/b&gt; because a single identifier can be
bound to several different entities during the course of a program's
lifetime.&lt;/p&gt;

&lt;p&gt;The value of a dynamically-scoped variable depends on what's
called the variable's &lt;b&gt;evaluation context.&lt;/b&gt;   A variable
inherits its evaluation context from the entity that uses it, not
from the entity that defines it.   A dynamically scoped variable
uses the most recent binding it can find for that identifier.  
Technically, all of Perl's global variables are dynamically scoped,
but only the &lt;tt&gt;local()&lt;/tt&gt; keyword can create a new entity and
establish a new binding.&lt;/p&gt;

&lt;p&gt;If we use the code above with a function that creates a dynamic
(i.e.: local) variable:&lt;/p&gt;

&lt;code&gt;
    sub local_scope {
        local ($LOCAL) = "-------";
        printf (
            "local scope:         %s \n",
            join (',', ($GLOBAL, $LOCAL, $LEXICAL))
        );
        show_evaluation_context();
    }
    local_scope();
    print "\n";
    print "but outside local_scope(), we still have:\n";
    show_evaluation_context();
&lt;/code&gt;

&lt;p&gt;we get this output:&lt;/p&gt;

&lt;code&gt;
    local scope:         static,-------,lexical 
    evaluation context:  static,-------,lexical 
    
    but outside local_scope(), we still have:
    evaluation context:  static,dynamic,lexical 
&lt;/code&gt;

&lt;p&gt;which shows two different values for &lt;tt&gt;$LOCAL&lt;/tt&gt; when we call
it from two different evaluation contexts.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Lexical scope rules&lt;/b&gt; create entities that are only visible
in the scope where they're defined.   Lexically-scoped entities
replace globally (or locally) scoped entities that are defined for
the parent, but are not visible to any entity created in, of called
from, the same scope.&lt;/p&gt;

&lt;p&gt;A function that sets a lexical variable:&lt;/p&gt;

&lt;code&gt;
    sub lexical_scope {
        my ($LEXICAL) = "-------";
        printf (
            "lexical scope:       %s \n",
            join (',', ($GLOBAL, $LOCAL, $LEXICAL))
        );
        show_evaluation_context();
    }
    
    sub local_override {
        local ($LEXICAL) = 'DYNAMICALLY RE-BOUND VALUE';
        lexical_scope();
    }
    
    local_override();
    print "\n";
    lexical_scope();
&lt;/code&gt;

&lt;p&gt;gives us this:&lt;/p&gt;

&lt;code&gt;
    lexical scope:       static,dynamic,------- 
    evaluation context:  static,dynamic,DYNAMICALLY RE-BOUND VALUE 
    
    lexical scope:       static,dynamic,------- 
    evaluation context:  static,dynamic,lexical 
&lt;/code&gt;

&lt;p&gt;which shows that lexicals override both local and global bindings
in the scope where they're defined.   Unlike global or local
bindings, though, lexical bindings don't do anything to the
evaluation context &lt;i&gt;outside&lt;/i&gt; the scope where they're
defined.&lt;/p&gt;

&lt;p&gt;Officially, all the variables in the samples above are lvalues,
but we haven't made them do anything a pure variable couldn't do.  
None of the code above assigns a new value to an entity that was
defined somewhere else.   All it does is create new entities with
different values, and bind them to the same names:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;All three variables in &lt;tt&gt;show_evaluation_context()&lt;/tt&gt;
    are free variables, and so are the three in
    &lt;tt&gt;global_scope().&lt;/tt&gt;

    &lt;li&gt;&lt;tt&gt;$GLOBAL&lt;/tt&gt; and &lt;tt&gt;$LEXICAL&lt;/tt&gt; are free in
    &lt;tt&gt;local_scope(),&lt;/tt&gt; while &lt;tt&gt;$LOCAL&lt;/tt&gt; is dynamically
    bound to the entity defined in that scope.

    &lt;li&gt;&lt;tt&gt;$GLOBAL&lt;/tt&gt; and &lt;tt&gt;$LOCAL&lt;/tt&gt; are free in
    &lt;tt&gt;lexical_scope(),&lt;/tt&gt; while &lt;tt&gt;$LEXICAL&lt;/tt&gt; is lexically
    bound to the entity defined in that scope.
&lt;/ul&gt;

&lt;p&gt;As soon as the new entities went out of scope, the free variables
returned to their previous bindings.   Re-binding free variables to
new entities lets us create code that acts like the entity values
are changing, without ever changing the values of the entities
themselves.&lt;/p&gt;

&lt;p&gt;Finally, &lt;b&gt;package scope rules&lt;/b&gt; partition the global scope
into a set of mutually-exclusive regions.   The entities defined in
one package are, by default, invisible to entities defined in
another package.   All packages inherit the ability to refer to each
other from the global scope, though.   Therefore, a name defined in
one package can refer to an entity defined in another by using a
&lt;b&gt;fully-qualified&lt;/b&gt; identifier:&lt;/p&gt;

&lt;code&gt;
    package Foo;
    
    $VAR1 = "VAR1 in package 'Foo'.";
    
    package main;
    
    $VAR1 = "VAR1 in package 'main'.";
    $VAR2 = "VAR2 in package 'main'.";
    
    print $Foo::VAR1, "\n";
    print $VAR1, "\n";
    print $VAR2, "\n";
&lt;/code&gt;

&lt;p&gt;produces the output:&lt;/p&gt;

&lt;code&gt;
    VAR1 in package 'Foo'.
    VAR1 in package 'main'.
    VAR2 in package 'main'.
&lt;/code&gt;

&lt;h3&gt;variables and referential transparency:&lt;/h3&gt;

&lt;p&gt;&lt;b&gt;The principle of referential transparency&lt;/b&gt; says that the
same entity should always produce the same value, no matter where or
when it ends up being evaluated.   All the code samples shown above
observe that principle.   The bindings between free variables and
entities change, but the entities themselves keep the same value for
the life of the program.&lt;/p&gt;

&lt;p&gt;The very idea of referential transparency seems crazy to most
programmers who are used to thinking of variables as lvalues.   The
way they see it, the whole &lt;i&gt;point&lt;/i&gt; of a variable is to store
intermediate values while the program works its way through a
calculation.   Even so, for most problems, lvalues are just a
convenience.   In theoretical terms, we can get the same effect by
re-binding a free variable to a series of new entities.&lt;/p&gt;

&lt;p&gt;In practical terms, lvalues can be one &lt;i&gt;heck&lt;/i&gt; of a
convenience, and when used with a smattering of discipline, can make
code more readable while still observing the general spirit of
referential transparency.&lt;/p&gt;

&lt;p&gt;For example.. the following snippet of code:&lt;/p&gt;

&lt;code&gt;
    my $total = 0;
    for $i (1..10) {
        $total += $i;
    }
    print $total, "\n";
&lt;/code&gt;

&lt;p&gt;isn't referentially transparent, because we assign a new value to
&lt;tt&gt;$total&lt;/tt&gt; each time we pass through the loop.   The
referentially transparent way to do the same job would be:&lt;/p&gt;

&lt;code&gt;
    sub sum_of {
        my ($item, @list) = @_;
        return ((defined $item) ? $item + sum_of (@list) : 0);
    }
    print sum_of (1..10), "\n";
&lt;/code&gt;

&lt;p&gt;which is mathematically correct, but harder to read.&lt;/p&gt;

&lt;p&gt;Functional programming advocates will say that the latter version
is just as easy to read once you've learned the idioms of the
functional style, but I'm sorry, it just ain't so.   Recursive
structures are almost always harder to understand than iterative
ones because they make you keep track of several layers of bindings.
  As the recursion gets deeper and more entities participate in the
evaluation context, it gets easier and easier to lose track of
something.   Recursive structures have a long and well-documented
history of famous logicians making embarrassing bloopers.&lt;/p&gt;

&lt;p&gt;That's not to say lvalues are automatically better, though.   It
only takes a few undisciplined assignments to turn a seemingly
innocent piece of code into a vicious and evil mess.   And
functional programming types are correct when they say that the
problems bad lvalues create are far worse than the problems bad
recursion can create.&lt;/p&gt;

&lt;p&gt;The problems with lvalues all share a common theme, though:  &lt;b&gt;timing.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;When you use referentially transparent variables, the order of
evaluation doesn't matter.   Every entity will return the same
value, so as long as you have all your bindings worked out,
everything's fine.&lt;/p&gt;

&lt;p&gt;Lvalues don't work that way, though.   The order of evaluation is
very important.   You have to keep your evaluations in synch with
your &lt;b&gt;mutations&lt;/b&gt; (changes to the entity's value), or the whole
thing will go blooey.   You don't want to want to rearrange the
sequence: &lt;p&gt;

&lt;ol&gt;
    &lt;li&gt; make sure X is greater than Y
    &lt;li&gt; subtract Y from X
    &lt;li&gt; make sure X is greater than Z
    &lt;li&gt; subtract Z from X
&lt;/ol&gt;

&lt;p&gt;as:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt; make sure X is greater than Y
    &lt;li&gt; make sure X is greater than Z
    &lt;li&gt; subtract Y from X
    &lt;li&gt; subtract Z from X
&lt;/ol&gt;

&lt;p&gt;if you want to guarantee that X will always be greater than
zero.&lt;/p&gt;

&lt;p&gt;The more widely you scatter evaluations and mutations of an
lvalue, the more chances you have for something to fall out of
synch.   If something does fall out of synch, it will usually do so
at runtime, in response to a set of operating conditions you may or
may not be able to reproduce.   The result is a bug which will be
very hard to isolate and fix.&lt;/p&gt;

&lt;p&gt;By the same reasoning, though, the more tightly you focus your
work with an lvalue, the better your chances of staying in
synch.&lt;/p&gt;

&lt;p&gt;As a general rule of thumb, it's okay to manipulate an lvalue as
long as:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt; you only do it in the same scope where the lvalue was
    defined,     
    &lt;li&gt; and you never refer to a previous value after a mutation is
    complete. &lt;/ul&gt;

&lt;p&gt;If you do that properly, you should be able to encapsulate that
chunk of code, and use it as a referentially transparent function.  
The little summation loop that uses &lt;tt&gt;$total,&lt;/tt&gt; above, obeys
both of those rules.   I'd personally use that version over the
recursive version every time.&lt;/p&gt;

&lt;p&gt;If you &lt;i&gt;can't&lt;/i&gt; encapsulate a chunk of code and create a
referentially transparent function, that's a warning sign that
should tell you to look for design problems.&lt;/p&gt;


&lt;h1&gt;Surrender:&lt;/h1&gt;

&lt;p&gt;Okay, that's enough.   This post only covers about a third of the
topics in my original outline, it took twice as long to write as I'd
planned, and it's about twice as long as I expected it to be.  
There's no way I'm going to try dumping any more material on you
this week, when we could all be wassailing ourselves into oblivion
instead.&lt;/p&gt;

&lt;p&gt;Spend some time getting used to the vocabulary, and think about
types, scoping, and referential transparency.   I'll be back next
week to talk about functions.&lt;/p&gt;
</field>
</data>
</node>
