Evaluation Order


When programming your game using GML you should be aware that function call arguments are not guaranteed an evaluation order. What this means is that the order in which you place functions in your code will change from platform to platform, so you should code them in an explicit manner. This is due to optimisation differences between the different target platforms, for example on the Windows target functions may be evaluated from right to left, but on the HTML5 target, they may be evaluated from left to right. So to avoid any issues you are best not to call multiple functions in the arguments of a function call as you may well be building in a reliance on the order of evaluation.

To see an example of what this means, consider the following code which is calling several functions and using them as arguments to a script:

buffer_seek(buff, buffer_seek_start, 0);
scr_buffer_get_info(buffer_read(buff, buffer_s8), buffer_read(buff, buffer_s16),buffer_read(buff, buffer_s16));

Now, the problem here is that on some platforms, the last buffer_read will be called first, and so all the arguments of the script will be wrong as the data is being read from the buffer in "reverse" order as you would perceive it. This has the knock-on effect here of affecting all further values for the buffer_read function so all the arguments being passed to this script will be wrong!

To get around this you should explicitly call the functions in the required order and store the returned values in variables, like this:

var val[0] = buffer_read(buff, buffer_s8);
var val[1] = buffer_read(buff, buffer_s16);
var val[2] = buffer_read(buff, buffer_s16);
scr_buffer_get_info(val[0], val[1], val[2]);

While it may seem a more verbose method, it keeps everything clear and avoids any possible problems with evaluation order.

You should also take care when using expressions too, as the order in which they are evaluated in will change depending on which target you are compiling to. So, when using expressions in your code, ensure you use brackets () to properly control the order of operations. This is very important to ensure the correct behaviour of your games across all the target platforms games and is essential for JavaScript platforms. For example, consider the following code:

a = b == c || d;

The different target compilers will perform the operations in different orders since they are not explicitly shown, giving rise to "odd" results that you may not expect when you play your game. To avoid this, use the () to separate out the parts, like this:

a = (b == c || d);   //better
a = ((b == c) || d); //best