I haven’t found this in the documentation, so I’m not sure if it’s considered a feature or a bug, but I just discovered empirically that the boolean operators in GPScript don’t short-circuit. For example, the following code which looks safe to my eyes will actually fail with a runtime error:
var a : Integer Array = [ 0, 0, 0, 0, 0 ]
var i : Integer = 0
While i < Size(a) and a[i] == 0 Do // This line fails because "and" does not short-circuit
i = i + 1
End
if i == Size(a) Then Print("all zero") Else Print("non-zero in element " + i) end
I hope this post saves somebody a few hours of bug-hunting!
Yep, that’s what I’m saying. If the “and” operator were short-cuircuiting, then when the “i < Size(a)” evaluates as false, the “a[i] == 0” would never get evaluated, and there would be no runtime error. This is the behaviour that I would expect, coming from languages derived from C, but today I learned that some languages don’t behave that way!
I didn’t mean to imply that it was. I meant that I am coming from C-derived languages, and hence I may be making incorrect guesses and assumptions when learning a language that isn’t. This post isn’t a complaint (except perhaps to suggest that future users may benefit from this being explicitly documented).
I will have to teach myself a new idiom for “find the first non-zero array element” though. Here’s what I’ve come up with (as a fix for the erroneous code in my original post), but it requires an extra variable (a boolean to use in place of the possibly out-of-bounds array reference). Is there a more elegant alternative?
var a : Integer Array = [ 0, 0, 0, 0, 1 ]
var i : Integer = 0
var foundOne : Boolean = false
While i < Size(a) and !foundOne Do
If a[i] == 0 Then
i = i + 1
Else
foundOne = true
End
End
if i == Size(a) Then Print("all zero") Else Print("non-zero in element " + i) End