Difference between revisions of "Side effects"

m
m (added mention of Mutables library)
Line 1: Line 1:
 
A variable A or a function F has a '''side effect''' when evaluating it also a  changes the value of another variable B.  Side effects are the bane of computer programmers because it means you can’t be sure of how B was computed without looking for some other variable or function that may change it, even they may be in a totally different part of the code. Computer scientists term this problem “referential opacity”. It makes code much harder to understand and debug.
 
A variable A or a function F has a '''side effect''' when evaluating it also a  changes the value of another variable B.  Side effects are the bane of computer programmers because it means you can’t be sure of how B was computed without looking for some other variable or function that may change it, even they may be in a totally different part of the code. Computer scientists term this problem “referential opacity”. It makes code much harder to understand and debug.
  
Analytica is unusual among computer languages in that ''it does not allow side effects,'' except in special cases where they aren’t harmful. This is a major reason why Analytica code is so much easier to write, read, and debug than standard procedural languages like C, C++, Basic, R, Python, and so on.  
+
Analytica is unusual among computer languages in that ''it does not allow side effects,'' except in special cases where they aren’t harmful. In particular, it doesn't let you assign to a global variable using the [[Assignment Operator :=]]. This is a major reason why Analytica code is so much easier to write, read, and debug than standard procedural languages like C, C++, Basic, R, Python, and so on.  
Analytica lets you [[Assignment Operator :=|assign]] to a local variable V inside a Definition, for example:
+
 
 +
Analytica does let you [[Assignment Operator :=|assign]] to a local variable V inside a Definition, for example:
 
   Variable A := BEGIN
 
   Variable A := BEGIN
 
       Local v := 0;
 
       Local v := 0;
Line 9: Line 10:
 
But that doesn’t cause referential opacity because the local variable is declared right there in the same definition.
 
But that doesn’t cause referential opacity because the local variable is declared right there in the same definition.
  
The most common cause of side effects (and the consequent opacity) is an assignment to a global variable defined somewhere else. Analytica only allows assignments to  global variables in these special cases:
+
The most common cause of side effects (and the consequent opacity) is an assignment to a global variable defined somewhere else. That's why Analytica only allows assignments to  global variables in these special cases that avoid referential opacity:
 +
 
 +
* You may assign to a global variable in an [[OnClick]] or [[OnChange]] attribute using the [[Assignment Operator :=]]. In these cases, evaluation is triggered by a user action, and the assignment changes the definition of the variable to the assigned value or expression, so you can still see how it was computed. You can't assign to a global variable in a standard Definition.
  
* You may assign to a global variable in an [[OnClick]] or [[OnChange]] attribute, which must be triggered by a user action, but not in a standard Definition. In this case, the assignment changes the definition of the variable to the assigned value or expression, so you can still see how it was computed.
+
* An exception to the "no global assignments" rule is that you may assign to a global variable B in a variable or function A if B is specifically defined as [[ComputedBy]](A). This is useful when it is algorithmically convenient to compute B as well as A in the Definition of A. It doesn’t cause any referential opacity because you can see that B is computed by A right in the Definition of B.
  
* You may assign to a global variable B in a variable or function A if B is specifically defined as [[ComputedBy]](A). This is useful when it is convenient to compute B as well as A in the Definition of A. It doesn’t cause any referential opacity because you can see right in the Definition of B that it is computed by A.
+
Occasionally, it is useful to save a value in a place where it can be used elsewhere, especially for debugging purposes. The [[Mutables library]] let's you save the value (possible an array or other complex data structure) as a side effect and read it later.  
  
 
== See also ==
 
== See also ==
Line 19: Line 22:
 
* [[Assignment Operator :=]]
 
* [[Assignment Operator :=]]
 
* [[ComputedBy]]
 
* [[ComputedBy]]
 +
* [[Mutables library]]

Revision as of 18:21, 8 January 2025

A variable A or a function F has a side effect when evaluating it also a changes the value of another variable B. Side effects are the bane of computer programmers because it means you can’t be sure of how B was computed without looking for some other variable or function that may change it, even they may be in a totally different part of the code. Computer scientists term this problem “referential opacity”. It makes code much harder to understand and debug.

Analytica is unusual among computer languages in that it does not allow side effects, except in special cases where they aren’t harmful. In particular, it doesn't let you assign to a global variable using the Assignment Operator :=. This is a major reason why Analytica code is so much easier to write, read, and debug than standard procedural languages like C, C++, Basic, R, Python, and so on.

Analytica does let you assign to a local variable V inside a Definition, for example:

  Variable A := BEGIN
      Local v := 0;
      v := B*C^2
  END;

But that doesn’t cause referential opacity because the local variable is declared right there in the same definition.

The most common cause of side effects (and the consequent opacity) is an assignment to a global variable defined somewhere else. That's why Analytica only allows assignments to global variables in these special cases that avoid referential opacity:

  • You may assign to a global variable in an OnClick or OnChange attribute using the Assignment Operator :=. In these cases, evaluation is triggered by a user action, and the assignment changes the definition of the variable to the assigned value or expression, so you can still see how it was computed. You can't assign to a global variable in a standard Definition.
  • An exception to the "no global assignments" rule is that you may assign to a global variable B in a variable or function A if B is specifically defined as ComputedBy(A). This is useful when it is algorithmically convenient to compute B as well as A in the Definition of A. It doesn’t cause any referential opacity because you can see that B is computed by A right in the Definition of B.

Occasionally, it is useful to save a value in a place where it can be used elsewhere, especially for debugging purposes. The Mutables library let's you save the value (possible an array or other complex data structure) as a side effect and read it later.

See also

Comments


You are not allowed to post comments.