Eek! Boolean operators are not short-circuiting

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!

I get this error in the Script Logger:
Array index out of bounds: index (zero-based) = 5: Current array length = 5

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! :smiley:

No, they don’t short circuit (it’s something I’m considering, but probably using Ada syntax to make it explicit)

GP script is not derived from C

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