MyArray[3][-2] fails (quelle surprise), how to detect this?

F

Fabian

function getImage(id,x,y) {
if (mpdef[0 + yy + y][0 + xx + x] == undefined) {
// set to default image
document.getElementById(id).src = terrdef[13];
}
else {
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y][0 + xx
+ x] ];
}
return;
}

I use this function to grab an index number which refers to a graphics
file. In theory, firt it checks to see if the mpdef array has a valid
value as teh specified row/colum index, and then either puts in a
default index number or grabs the index number from teh array, depending
on whether the mpdef array has a value at that location.

However, it seems to choke when either teh referenced row or column
is -1 or lower. How should I catch this?
 
M

Michael Winter

on 12/11/2003:
function getImage(id,x,y) {
if (mpdef[0 + yy + y][0 + xx + x] == undefined) {
// set to default image
document.getElementById(id).src = terrdef[13];
}
else {
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y][0 + xx
+ x] ];
}

This return statement shouldn't be necessary. Correct me if I'm
wrong, but the closing brace should create an implicit return.
return;
}

I use this function to grab an index number which refers to a graphics
file. In theory, firt it checks to see if the mpdef array has a valid
value as teh specified row/colum index, and then either puts in a
default index number or grabs the index number from teh array, depending
on whether the mpdef array has a value at that location.

However, it seems to choke when either teh referenced row or column
is -1 or lower. How should I catch this?

Umm, is there any reason why you can't just check if the array indices
are greater than, or equal to, zero. If either are negative, display
the default. If they are zero or positive, then check if the array
element contains a value. If it doesn't display the default. If it
does contain a value, display that:

if( 0 > x || 0 > y )
{
document.getElementById(id).src = terrdef[13];
}
else if( undefined == mpdef[0 + yy + y][0 + xx + x])
{
document.getElementById(id).src = terrdef[13];
}
else
{
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y][0 + xx
+ x] ];
}



If right-to-left evaluation is guaranteed, you can reduce the above
to:

if(( undefined == mpdef[0 + yy + y][0 + xx + x] ) || ( 0 > x || 0 >
y ))
{
document.getElementById(id).src = terrdef[13];
}
else
{
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y][0 + xx
+ x] ];
}

Mike
 
L

Lasse Reichstein Nielsen

Fabian said:
function getImage(id,x,y) {
if (mpdef[0 + yy + y][0 + xx + x] == undefined) {
// set to default image
document.getElementById(id).src = terrdef[13];
}
else {
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y][0 + xx
+ x] ];
}
return;
}
However, it seems to choke when either teh referenced row or column
is -1 or lower. How should I catch this?

Actually, it only chokes when the *first* coordinate is negative (or
any other value that doesn't correpspond to a property of the mpdef
array.

Try this:

function getImage(id,x,y) {
var elem = document.getElementById(id);
var mpdefColumn = mpdef[0+yy+y]; // I assume "y" means "column"
if (mpdefColumn) {
var mpdefCell = mpdefColumn[0+xx+x];
if (mpdefCell !== undefined ) {
elem.src = terrdef[mpdefCell];
return;
}
}
elem.src = terrdef[13];
}

if (mpdef[0 + yy + y][0 + xx + x] == undefined) {

if mpdef[0+yy+y] is undefined, the second lookup fails.

/L
 
F

Fabian

Lasse Reichstein Nielsen hu kiteb:
Try this:

function getImage(id,x,y) {
var elem = document.getElementById(id);
var mpdefColumn = mpdef[0+yy+y]; // I assume "y" means "column"
if (mpdefColumn) {
var mpdefCell = mpdefColumn[0+xx+x];
if (mpdefCell !== undefined ) {
elem.src = terrdef[mpdefCell];
return;
}
}
elem.src = terrdef[13];
}

function getImage(id,x1,y1) {
// shiftys to account for all compass direction facings
if ((ff==0) || (ff==1)) { x2 = x1; y2 = y1; }
if ((ff==2) || (ff==3)) { x2 = -y1; y2 = x1; }
if ((ff==4) || (ff==5)) { x2 = -x1; y2 = -y1; }
if ((ff==6) || (ff==7)) { x2 = y1; y2 = -x1; }
// detect undefined map locations
if ((0 + yy + y2 < 0) || (0 + xx + x2 < 0) || (1 + yy + y2 >
mpdef.length) || (1 + xx + x2 > mpdef[0].length)) {
document.getElementById(id).src = terrdef[ nullterr ];
}
else {
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y2][0 + xx +
x2] ];
}
}

The above is what I am using now, and it seems to work. In case you're
interested, the above is being used at [ www.lajzar.co.uk/midnight ].
(arrow keys to navigate, or use the buttons in the corner).
Two points to question...

1) I'm sure having 4 parallel if statements is not particularly
efficient, but I'm not sure of a better solution that checks all four
map edges properly.

2) I think there is probably a more efficient way to account for the 8
possible facings.
 
D

Dr John Stockton

JRS: In article <[email protected]>, seen in
news:comp.lang.javascript said:
function getImage(id,x1,y1) {
// shiftys to account for all compass direction facings
if ((ff==0) || (ff==1)) { x2 = x1; y2 = y1; }
if ((ff==2) || (ff==3)) { x2 = -y1; y2 = x1; }
if ((ff==4) || (ff==5)) { x2 = -x1; y2 = -y1; }
if ((ff==6) || (ff==7)) { x2 = y1; y2 = -x1; }
// detect undefined map locations
if ((0 + yy + y2 < 0) || (0 + xx + x2 < 0) || (1 + yy + y2 >
mpdef.length) || (1 + xx + x2 > mpdef[0].length)) {
document.getElementById(id).src = terrdef[ nullterr ];
}
else {
document.getElementById(id).src = terrdef[ mpdef[0 + yy + y2][0 + xx +
x2] ];
}
}

The above is what I am using now, and it seems to work. In case you're
interested, the above is being used at [ www.lajzar.co.uk/midnight ].
(arrow keys to navigate, or use the buttons in the corner).
Two points to question...

1) I'm sure having 4 parallel if statements is not particularly
efficient, but I'm not sure of a better solution that checks all four
map edges properly.

2) I think there is probably a more efficient way to account for the 8
possible facings.

if ((ff==0) || (ff==1)) // etc
or
f2 = (ff-ff%2)/2
if (f2=1) ...
...

You seem to be rotating by 0..3 times 90 deg. Consider the following
test, for ff = 0..7 :
ff = 6
x2 = 4 ; y2 = 3
for (j=ff; j>1; j-=2) { T = x2 ; x2 = -y2 ; y2 = T } // rot 90
Math.atan2(y2, x2) // for convenience in my test

You could also try :
if (ff>3) { ff -= 4 ; x2 = -x2 ; y2 = -y2 }
if (ff>1) { ff -= 2 ; x2 = -y2 ; y2 = x2 }
if (ff>0) { // rotate 45 degrees?


Untested :
A = mpdef[0 + yy + y2]
if (A) A = A[0 + xx + x2]
document.getElementById(id).src = A ? A : terrdef[ nullterr ];

Why add 0 ?
 
F

Fabian

Dr John Stockton hu kiteb:
if ((ff==0) || (ff==1)) // etc
or
f2 = (ff-ff%2)/2
if (f2=1) ...
...

You seem to be rotating by 0..3 times 90 deg. Consider the following
test, for ff = 0..7 :
ff = 6
x2 = 4 ; y2 = 3
for (j=ff; j>1; j-=2) { T = x2 ; x2 = -y2 ; y2 = T } // rot 90
Math.atan2(y2, x2) // for convenience in my test

This one works. I just had to add x2 = x1 and y2 = y1 before the for
statement. Its faster than my original too. Thanks.
You could also try :
if (ff>3) { ff -= 4 ; x2 = -x2 ; y2 = -y2 }
if (ff>1) { ff -= 2 ; x2 = -y2 ; y2 = x2 }
if (ff>0) { // rotate 45 degrees?

The 45 degree rotation uses a separate set of image placeholders. I use
display=none styles to hide them when looking along a straight compass
direction, and conversely I hide the normal images when looking along a
diagonal compass direction.
Untested :
A = mpdef[0 + yy + y2]
if (A) A = A[0 + xx + x2]
document.getElementById(id).src = A ? A : terrdef[ nullterr ];

Why add 0 ?

Adding zero forces javascript to treat the variables as numbers instead
of text, thus forcing addition instead of concatenation. What does that
? operator do? It isn't in my (very old) reference book, and a question
mark is, somewhat understandably, hard to search for on the Internet.
 
D

Dr John Stockton

JRS: In article <[email protected]>, seen in
news:comp.lang.javascript said:
Dr John Stockton hu kiteb:
Untested :
A = mpdef[0 + yy + y2]
if (A) A = A[0 + xx + x2]
document.getElementById(id).src = A ? A : terrdef[ nullterr ];

Why add 0 ?

Adding zero forces javascript to treat the variables as numbers instead
of text, thus forcing addition instead of concatenation. What does that
? operator do? It isn't in my (very old) reference book, and a question
mark is, somewhat understandably, hard to search for on the Internet.

Better to convert them to numbers when first generated. Operating with
numbers ought to be faster than operating with strings; or, at least, no
slower.


X ? Y : Z means if X then Y else Z

Here, ? is an operator with lower priority than anything apart from
assignment or comma

So A = A<0 ? -A : A // much as Math.abs(A)
isNaN(X) ? alert('Ooo') : alert('Aaa')
alert(isNaN(X) ? 'Ooo' : 'Aaa')

Seek "conditional operator" in Netscape's Javascript references, via
<URL:http://www.merlyn.demon.co.uk/js-index.htm#WL>, if the links still
work. They don't actually say that only one of Y, Z is evaluated.

A good place to look is ECMA-262; I guess the links in the FAQ will lead
towards a copy of it, and the link on my site should. Section 11.12.
 
D

Douglas Crockford

Untested :
A = mpdef[0 + yy + y2]
if (A) A = A[0 + xx + x2]
document.getElementById(id).src = A ? A : terrdef[ nullterr ];

Why add 0 ?

Adding zero forces javascript to treat the variables as numbers instead
of text, thus forcing addition instead of concatenation.

Wrong. Adding zero does not do that. It will only append a '0' at the head of
the string. For most purposes it is better to use the '+' prefix operator.

A = mpdef[+yy + (+y2)];
Better to convert them to numbers when first generated. Operating with
numbers ought to be faster than operating with strings; or, at least, no
slower.

For most scripting applications, the relative speed of number operations vs.
string operations is irrelevant. A vastly more important consideration is
correctness. If you are doing additions, made very sure that the values are
numbers. If either value is a string, the result will be wrong.

So it is best to write

A = mpdef[yy + y2];

and make sure that yy and y2 are correctly initialized as numbers. If JavaScript
had used separate operators for addition and concatenation this would not be a
problem. Unfortunately, the combination of operator overloading with type
coercion and loose typing makes the summing of two values unnecessarily
difficult and error prone.

http://www.crockford.com
 
F

Fabian

Dr John Stockton hu kiteb:
Better to convert them to numbers when first generated. Operating
with numbers ought to be faster than operating with strings; or, at
least, no slower.

Aren't there some situations where a number can still get interpreted as
a string? I wasn't aware that there is a way to explicitly declare that
a variable is only ever to be considered as a number.
X ? Y : Z means if X then Y else Z

So this is exactly equivalent to:

if (X) { Y }
else { Z }

?
 
L

Lasse Reichstein Nielsen

Fabian said:
Aren't there some situations where a number can still get interpreted as
a string?

Lots. Anything that expects a string only will probably convert its
argument to a string if it isnt.

Addition to a string is one example. ""+0 and 0+"" both give the
string "0".
I wasn't aware that there is a way to explicitly declare that
a variable is only ever to be considered as a number.

Not in Javascript versions below 2, and JS2 is still work in progress.
So this is exactly equivalent to:

if (X) { Y }
else { Z }

No. The if statement is a statement, while X?Y:Z is an expression.

You can write
var x = 42 + (y==2?10:37);
You can't write
42 + if (...)...
since "if" generates a statement, and statments aren't expressions.

/L
 
D

Dr John Stockton

JRS: In article <[email protected]>, seen in
news:comp.lang.javascript said:
Dr John Stockton hu kiteb:

Note : the second of those sentences is a comment, not a reason. If the
meaning of a variable is fundamentally numeric, then it should be a
Number.

Aren't there some situations where a number can still get interpreted as
a string? I wasn't aware that there is a way to explicitly declare that
a variable is only ever to be considered as a number.

If the algorithm is correct, one will never want to numerically add a
Number to a String, since the second value will have been converted to a
Number at the first opportunity. If a number is to be converted to a
string and concatenated, it should be obvious what the intent is. These
ate not matters of javascript language design, but of writing code so
that it can be executed and read with the same interpretation.

So this is exactly equivalent to:

if (X) { Y }
else { Z }

No; but I think the converse is true. The first is a superset of the
second, since it can be used where a value is required; A=X?Y:X
 
L

Lasse Reichstein Nielsen

Dr John Stockton said:
JRS: In article <[email protected]>, seen in
No; but I think the converse is true. The first is a superset of the
second, since it can be used where a value is required; A=X?Y:X

It depends on what Y and Z are. If they can stand for arbitrary
Javascript syntax, then it isn't true. You can't put statements into
the ?:-operator. If Y and Z are just variables, then they are expressions,
and can be used in both places (expressions can be used as statements,
although using an expression with no side effect is pointless).

I.e., there are four different things that can vary:
- use ?: or if-then as conditional branch
E.g., x?...:... or if(x) ... else ...
- have expressions or statements in the branches
E.g., 2+2 (expression) or return 2+2; (statement)
- use the value of the conditional branch or not
E.g., q=(conditional branch); or (conditional branch);
- have side effects in the branches or not
E.g., w=2+2/foo() or 2+2

That give 16 different cases, many of them invalid.

It is invalid to use statments in the branches of the ?: operator.
It is invalid to use the value of an if-statement.
It is meaningless to not have side-effects in an if-statment

Without side effects in branches:
As a statement (not using value):
if (x) {2+2;} else {4+4;} : valid but pointless
if (x) {return 2+2;} else {return 4+4;} : valid and meaningful
x?(2+2):(4+4) : valid but pointless
x?(return 2+2;):(return 4+4;) : invalid
As an expression (value is used):
q = if (x) {2+2;} else {4+4;} : invalid
q = if (x) {return 2+2;} else {return 4+4;} : invalid
q = x?(2+2):(4+4) : valid and meaningful
q = x?(return 2+2;):(return 4+4;) : invalid
With side effects:
As a statement:
if (x) {w=2+2;} else {foo();} : valid and meaningful
if (x) {return w=2+2;} else {return foo();} : valid and meaningful
x?(w=2+2):(foo()) : valid but you should use if
x?(return w=2+2;):(return foo();) : invalid
As an expression (value is used):
q = if (x) {w=2+2;} else {foo();} : invalid
q = if (x) {return w=2+2;} else {return foo();} : invalid
q = x?(w=2+2):(foo()) : valid and meaningful
q = x?(return w=2+2;):(return foo();) : invalid

Hope this makes any sense :)

/L
 
T

Thomas 'PointedEars' Lahn

Lasse said:
It depends on what Y and Z are. If they can stand for arbitrary
Javascript syntax, then it isn't true.
Right.

You can't put statements into the ?:-operator.

Wrong because it is too general. Try this:

var x = false;
y = x ? alert(x) : alert(42);

A method call is a statement and an assignment
(see below) is a statement, too.
As a statement (not using value):
if (x) {2+2;} else {4+4;} : valid but pointless
if (x) {return 2+2;} else {return 4+4;} : valid and meaningful
x?(2+2):(4+4) : valid but pointless
x?(return 2+2;):(return 4+4;) : invalid

return (x ? 2 + 2 : 4 + 4);
As an expression (value is used):
q = if (x) {2+2;} else {4+4;} : invalid
q = if (x) {return 2+2;} else {return 4+4;} : invalid
q = x?(2+2):(4+4) : valid and meaningful
q = x?(return 2+2;):(return 4+4;) : invalid

return (q = x ? 2 + 2 : 4 + 4);
With side effects:
As a statement:
if (x) {w=2+2;} else {foo();} : valid and meaningful
if (x) {return w=2+2;} else {return foo();} : valid and meaningful
x?(w=2+2):(foo()) : valid but you should use if
x?(return w=2+2;):(return foo();) : invalid

return (x ? w = 2 + 2 : foo());


PointedEars
 
L

Lasse Reichstein Nielsen

Thomas 'PointedEars' Lahn said:
Wrong because it is too general. Try this:

var x = false;
y = x ? alert(x) : alert(42);

A method call is a statement and an assignment
(see below) is a statement, too.

A method call and an assignment are expressions. So are additions and
a single identifier. They are not *by themselves* statements.

*Any* expression [1] *followed by a semicolon* is a statement (more
precisely: an "ExpressionStatement" in the grammar of ECMAScript -
ECMA 262, section 12.4).

[1] except function expressions and literal objects.

So:
x = 4
is an expression, not a statement (although automatic semicolon insertion
can turn it into one, if it is used in a position where the grammar requires
a statement).
x = 4;
is a statement, not an expression.
return (x ? 2 + 2 : 4 + 4);

Yes, but that is not the same. If you wrote the original, invalid,
expression, then this is probably what you meant. But it is just an
example of an invalid construction, not something you would want
to write.

/L
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top