Constants in code

For the roadmap, this might be a very useful idea: introduce constants / parameters in code. Apart from syntax and initialization, they should have the same status as globals (see the argumentation below).

The distinction with globals (on the one hand) and sliders etc. (on the other hand) is that they are automatically initialized, and not cleared by clear-all (and clearing-globals), but they are not visible in the interface.
For experimentation (sensitivity analysis, uncertainty analysis) these should be considered variable. BehaviorSpace can assign different values. This would solve a recurring problem (also addressed in NetLogo’s FAQ) of how to control “globals” by BehaviorSpace.

Another advantage is that constants / parameters stand clearly apart from true globals, improving readability of the model code.

In another simulation tool (for ODE models), that I have been maintaining for years, we had a long discussion about the distinction between constants and parameters. It depends very much on the point of view and purpose. The extreme cases are clear: fixed constants (like pi) and free parameters (in NetLogo typically sliders in the interface).
But for measured constants (like the speed of light) and arbitray numbers (like the number of agents of some kind), we might want to vary them for sensitivity analysis and uncertainty analysis, but not expose them in the interface.
There were still more arguments, not very relevant here, but in the end, we decided to make one category for “constants and parameters” with several kinds within the category.

Once, we have constants, we could also use them for the same purposes that other languages have symbolic constants for, especially avoiding magic numbers and magic strings.

For syntax, there would be several options. Given that free parameters are already in the interface, I would prefer a keyword constants (like globals) to introduce these constants / parameters.
Then each parameter could be introduced as a pair name–value, with for values either only literals or formulas that refer to earlier constants and literals only. So something like:

Feel free to suggest other variants for the syntax.

Another question is whether code should be allowed to change the value of a constant. My answer is yes.
We are already allowed to change values of sliders (etc.) in code; changing a value through the Command Center can be useful; setup code in BehaviorSpace could set a value instead of using “vary variables as follows”; and this is still the start.

With these ideas, I think introduction of constants would not interfere with other aspects of NetLogo code.

Hi Mark,

I think this is a great idea, and something we can definitely consider when making our development priority list. As it turns out, many others have previously suggested this as well, according to this open issue in our GitHub repo. The only thing I disagree with is your suggestion that constants could be changed programmatically. I think the one case where that should be allowed is BehaviorSpace, but you shouldn’t be allowed to change the value of a constant from anywhere else. Otherwise, there would be no difference between constants and globals that you initialize at the start of the program.

Isaac B.

Hi Isaac,

Thank you for the reference. I had missed that.
So, independently I arrived at variant B of the issue at github.

Considering the ability to change the value afterwards, that is related to the continuum from constants to parameters. Why allow code to change slider values and not to change constants in code?
And then, what about changing values through the controlling API?
Of course, just changing values of parameters and constants in code is bad practice. But if you forbid it completely, you block useful cases as well.

The question of allowing to change the value of a constant afterwards intrigued me further.
Maybe I can put it in a broader context, so I’ll post a separate topic.

Another afterthought is about formulas in defining constants. This can be very tricky.
What if the formula calls one or more functions that have side-effects (including random-* functions)?
If we use formulas to ensure consistency between constants, it is probably better to use functions (reporter procedures) instead.
So, is it useful having formulas in constant definitions?

That’s an interesting question. I agree that it definitely makes sense to allow arithmetic expressions in constant declarations. It would make it easier to show the meaning/derivation of a constant, and would also allow you to create a constant based on a previous constant. However, my intuition is that the idea of a randomized constant is fundamentally flawed, because if it’s different every time you run the program, then it’s not constant.

Initializing a constant with a side-effecting function feels like a totally different issue to me. In terms of model design, I think it can be helpful to make a distinction between constants and “helper globals”. In my mind, constants are just numbers that mathematically define a model, whereas “helper globals” are values that get computed at runtime but don’t change after setup. In my opinion, if you need a complicated side-effecting function to compute some value, that value is probably not suited to be a constant.

Isaac B.

Hi Isaac,

On using random functions in the definition of constants, I fully agree. This was meant to show an extreme case.

What you call “helper globals” is somewhere on the scale from fixed constants to free parameters.
The boundary between constants and parameters is not clear, and even depends on the situation. A “constant-or-parameter” would be constant for presentation purposes, while it might be a parameter for validation purposes.

So maybe we should change constants into constants-and-parameters to emphasize that it is broader than just constants?