On 2009-05-11, at 11:00EDT, Henry Minsky wrote:
On Mon, May 11, 2009 at 10:40 AM, P T Withington <[email protected]>
wrote:
I'm concerned that my r13731 change that sets the initial value of
constrained attributes to `undefined` rather than `null` may have
more
fallout. This change by André fixes one instance, but there could
be many
more lurking.
The issue: Constraints run in random order. Constraints that
depend on
attributes that are themselves constrained may reference those
attributes
when they are still undefined. When used in a numeric expression,
undefined
coerces to NaN. NaN's are "sticky", hence may pollute other
attributes, and
the constraint system may never recover.
Yeah, I think that not only will we find that some existing code has
gotten
broken, but people will also get into trouble in the future with NaNs.
Maybe we should have a way to ensure that all attributes have a
defined
default value?
It's just finding an initial value that will work as the constraint
system starts up. Since the order of constraints is indeterminite,
some constraints may depend on other constrained values that have not
yet had their constraint computed. So, where do you start?
Ideally, the runtime would know the actual type of each attribute and
be able to set the constrained attributes initially to some innocuous
value. (e.g., 0 for numeric, empty string for string, etc.) Barring
that, we need to at least go back to using `null` as the initial
default, since `undefined` when used in a numeric expression will
coerce to `NaN` and pollute the result (and any dependents).
r13731 was an attempt to make events fire less often by not having
them
fire when a constraint updated an attribute to the value it already
had. To
do this I needed a sentinel value that indicated that the attribute
had
_never_ been updated (to distinguish the case where a constraint
was setting
the attribute to `null`). `undefined` seemed to fit that bill, but
clearly
it has additional consequences, as seen in LPP-8088.
I'm looking for a way to achieve the optimization of 13731 without
the NaN
hazard. I think this means that we have to revert to storing
`null` as the
initial value of constrained attributes (even better would be to
store some
type-correct equivalent of null). And we'll have to have some sort
of a
flag that says you always send the event the first time around
(e.g., when
called from __LZapplyArgs).
That sounds like a reasonable approach; the optimization holds in
normal
use, but when the setter gets run the first time it always fires.
In fact, you don't even need the 'first time' flag, because if someone
depended on you and used your initial value, and your constraint set
your actual value to a value that is `===` your initial value, then
your dependents will already be correct.
I have a patch I am sending you to review that simply reverts to using
`null` as the initial value for constrained attributes. It seems to
work.