Robert said:
Richard Cornford wrote:
You have to mentally insert the assignment statement and
realize that it isn't a conditional thing.
Maybe it takes the realisation that the - if - statement evaluates an
expression and that only a small sub-set of expressions are 'conditional
things'. An assignment is just as much an expression as any other, and
has a well-defined result. Hence:- a = b = c = d = null; - ( or
parenthesised: - a = (b = (c = (d = null))); -)
My thought process is that I have to push the if statement
down in my thinking. Remember the assignment. Then, I have
to recall the if statement. You can see from my formatting
of the code. That I do not have to do this mental activity
because it is written on paper.
At least for me, I have to do the translation in my head.
It is more complicated for me to understand.
Humans vary considerably in the way they view, model and perceive the
world, and there is no doubt in my mind that that is a good thing (there
wouldn't be nearly as much invention if everyone's perceptions were
identical). Where you see this change as a clarification of the testing
logic I see it as an obscuring of the structure of the testing. Which
was originally a clear one choice of three and is now two nested choices
of two (the outcome is the same but my preference was for the former).
I reformulated the logic here.
var node = domCore.getElementById(label);
if(node)
{
var child;
if('string' == typeof node.innerHTML)
{
node.innerHTML = text.value;
}
else
{
child = node.firstChild;
if(child)
{
child.data = text.value;
}
else if(document.createTextNode &&
node.appendChild)
{
node.appendChild(
document.createTextNode(text.value));
}
}
}
Shows clearly:
1) What goes with what
2) code parrallels the oder the machine will run the code.
You do not have to back scan in the if statment nor do
mental push and pop operations.
While computer languages all exhibit operator precedence in one form or
another I don't think there are many programmers who learn (all of) the
precedence in any language they work with. Preferring instead to use the
appropriate placement of parentheses to make the desired sequence of
operations both certain and obvious.
I don't see the mental operations involved in comprehending a
parenthesised complex mathematical operation as significantly different
from that involved in comprehending a logical expression or if
expressions that contains assignment expressions (appropriately
parenthesised).
3) avoids the confusion over = and ==
There is no doubt that they are often confused, though mostly by those
unfamiliar with javascript (and the many other languages that use the
two). And JavaScript 1.2 confused matters even more by considering an
assignment directly within an - if - statement's expression as
comparison instead. And JSLINT will not put up with it, *unless* the
assignment is parenthesised (which also has JavaScript 1.2 treat it as
assignment).
4) Hilights the assignment statement because is valid for
the rest of the code block. It is valid outside the rest
of the if statement. I believe this reason alone is something
you want to hilight. Don't try to hide the assignment in the if
statement where it is easier to miss than if it had it's own
line of code.
While the results of the assignment do indeed stand for the remainder of
the execution following it the value assigned to - child - (the fact
that it has been assigned a value at all) is only of significance within
the one branch of the original code guarded by the - if - statement in
which the assignment happened. So it might be argued that placing the
assignment in the - if - expression more closely/directly associates it
with the code that may employ the result.
You can see from the format of the code that I like to
understand one simple thing at a time then go onto the
next thing.
Fair enough. But consider how some alternative structures might be
effected by this type of re-structuring. For example, suppose an
initial - if - branch was conditional on two assignments:-
var a, b;
if(
(a = getA()) &&
(b = getB())
){
// do something with a and b
}else{
//default action on failure
}
- once you re-structure it to get the assignments out of the - if -
expressions you get something like this:-
var b, a = getA();
if(a){
b = getB();
if(b){
// do something with a and b
}else{
// default action on failure
}
}else{
// default action on failure
}
- in which the - else - code has been doubled-up.
Make that three assignments and:-
var a, b, c;
if(
(a = getA()) &&
(b = getB()) &&
(c = getC())
){
// do something with a, b and c
}else{
// default action on failure
}
- becomes:-
var c, b, a = getA();
if(a){
b = getB();
if(b){
c = getC();
if(c){
// do something with a, b and c.
}else{
// default action on failure
}
}else{
// default action on failure
}
}else{
// default action on failure
}
- and it is looking like the - else - code is going to need passing off
to a parameterised function call to avoid the repetition (with the
consequence that what was previously directly visible code is moved
elsewhere, hardly a contribution to clarity).
And now if the - else - code itself branches, two branches become six.
That looks like escalating complexity to me.
There are alternative structures that could avoid repeating the - else -
code, such as flagging the success of the nested - if - blocks:-
var success = false, c, b, a = getA();
if(a){
b = getB();
if(b){
c = getC();
if(c){
success = true;
// do something with a and b
}
}
}
if(!success){
//default action on failure
}
- in which success cannot short-circuit the test for success and an
extra local variable has been added to the context.
However, returning from the function within the innermost - if -
branch:-
var c, b, a = getA();
if(a){
b = getB();
if(b){
c = getC()
if(c){
// do something with a, b and c
return; // avoid the default action by
// returning here.
}
}
}
// default action on failure (because the function did
// not return above)
- will short-circuit the default code and remove the necessity to test
for success/failure. But now the entire default action code is outside
any branching structure and someone missing the return statement might
waste time wondering why it is applied on each execution of the
function. Indeed there is quite a lot of debate about how and where
functions should return, centred around source code clarity, and the
above structure illustrates the case for claming that returning from
anywhere but the end of a function is less than clear.
In examples to folks who are not as familiar with program,
I believe it is best to code things in an easy to understand
format and avoid coding styles that many programs have noted
as problematic. Look at the code posted to this forum and
note the problems with it.
Even though you may like using an assignment statement in
an if statement many programmer have found it troublesome.
I assume this must be getting at something. Best to avoid
troublesome situations.
For a novice there probably are advantages in seeing code that is clear
on the level of individual expressions. Hopefully I have made a case for
suggesting that code written to be clear at that level might be
detracting form clarity and simplicity at a higher (structural) level.
In learning javascript there must come a point where the individual
expressions become second nature and interest moves on to the bigger
picture. It wouldn't be fair or reasonable to insist that all code
posted to the group catered for a lowest common denominator javascript
novice, and under those circumstances a lot of very interesting code
would never get the wider public exposure it deserves.
Richard.