1. Are local
variables created using bind within a function body,
locally scoped to
that function?
2. Are function argument names locally scoped to that
function?
By "locally scoped", I mean the usual lexical
scoping, i.e.
a) A distinct new variable is created on
entry to the function's scope,
and
is "destroyed" on
exit.
b) Within the function's scope, a local
variable hides any top-level
variable of the same
name.
c) Changing the local var doesn't change the
top-level var.
d) The local
var isn't changed by side-effect as a result of calling any
other function(s) that also use
the same name as a local var in their
own bodies.
I just encountered cross-scope variable
trashing, i.e. Jess is violating
(c) and (d).
Violates (c):
- At the top level, while "poor man's
single-stepping" through my code
(by pasting it line-by-line), I do (bind ?t triple).
- I then call a function (deffunction foo (?t)
...), passing a jess.Token.
- On return from foo, the top-level ?t has changed
to that token.
(This causes amusing exceptions
to be thrown when I paste the next
line that assumes the top-level
?t is still a symbol.)
Violates (d):
- Function f1 allocates a java.Util.Vector:
(bind ?U (new Vector))
- f1 then calls f2, and adds its return value to
?U.
- Function f2 also allocates its own Vector: (bind
?U (new Vector)),
and returns it.
- f2's use of the name ?U is the same object as
f1's use of the name ?U.
Hence, (i) when f2 does its own
thing, it already trashes f1's ?U by
overwriting it, and (ii)
when f2 returns ?U, f1 tries to add ?U to
itself.
Evidently, a Vector is smart
about this, and quietly does nothing.
- The result is that f1 returns, not a 2D Vector of
Vectors as I expected,
but a 1D Vector.
Fixing (d):
- I renamed f1's ?U to ?U1, and f2's ?U to
U2. And now it works.
The weird thing is that this entire call chain of
several functions was
working flawlessly yesterday, even with the same
variable names.
3. [Insight!] If a top-level variable ?X
already exists, then does
(bind ?X ...) within a function body simply re-use the
top-level variable,
instead of creating a new one
(and destroying it on exit)?
That would explain it! The difference between
today and yesterday is
that in today's intensive debugging session, I've
"polluted" my Jess
image's top-level namespace with about 50
global vars --
most of which are identical to local var names in
my functions.
Then all of my functions that share that local
variable name are really
sharing the same top-level variable.
So they'll trash it, each other,
yadda
yadda ...
That means I have to radically change my
"poor man's debugging"
strategy. It mean Jess violates lexical
scoping properties (a) and (b).
Is this explained in the Jess book? I didn't
notice any discussion of scoping
issues, and just assumed that it implemented
lexical scoping.
--
Eric Wang
CAD Lab, School of Mechanical Engineering,
Sungkyunkwan University
|