Objects and Values
There are two primary types of entities that comprise and are manipulated by Analytica models: Objects and Values. Understanding this simple distinction can help you understand several of the other language features and concepts in Analytica.
An Analytica value is essentially data. A value can be an atomic value or an intelligent array, which is a collection of atomic values. The result of any calculation is a value. Anything passed as a parameter to a function or an operator is a value. Values can be stored in various ways, and are the entities manipulated through calculation.
An Analytica object is an entity, such as a Variable, Model, or Function. It has a class, a name, and set of attributes. Each attribute has an associated value. For example, a (global) Variable, which you often see as a rounded rectangle on an influence diagram, is an object that usually with attributes Class, Identifier, Title, Description, Units, Definition, (mid-)Value, ProbValue (aka. Sample value), Domain and Check among others.
The word entity is not a term we use when referring to Analytica concepts. I use it here to help with the description. The terms value and object are specific terms we use within Analytica, and each have each have a precise meaning as described in this article. Both of these words are used in other ways in English and in computer science, so take note that we are using these here to refer to Analytica values and Analytica objects, as opposed to other common meanings of each of those words.
Values
These are the main subtypes of a value:
- Atomic values
- Numbers
- Text
- The Null value
- Handles
- References
- Arrays
- Lists
We use the term "atomic value", or just "atom", to distinguish it from an array. For example, the result of 1+2 is the atomic value 3. The Title attribute of any object is an atomic text value.
A array is a rectangular (or hyper-rectangular) collection of "cells", where each cell contains an atomic value. Arrays can have between 1 and 24 dimensions (or between 1 and 15 dimensions in 32-bit Analytica). Each dimension is associated with an index, with each dimension associated with a different index. An index, by the way is an object. There is one exception -- during computation, one dimension of an array can contain an implicit index. A list is a 1-D array where the only dimensions is an implicit dimension. Lists are used to define indexes. See also Atomic function parameters and Atomic..Do.
Objects
An Analytica object is an entity that has a Class, an Identifier (or name), and several other attribute values. The class and identifier are in fact attributes themselves. Most objects are in the global namespace, and each object in the global namespace must have a unique identifier. Some objects, most notably local indexes, are not in the global namespace, and don't need to have a unique identifier.
Objects can be sub-divided into the following subtypes (among others)
- Global variables
- Decision variables
- General variables
- Chance variables
- Objective variables
- Constraint variables
- (Global) indexes
- Constants
- System variables
- Functions
- Built-in functions
- User-Defined Functions
- Modules
- Model objects
- Libraries
- Buttons
- Pictures
- Text nodes
- FormNodes (user input and output nodes)
- Alias nodes
- Graph style templates
- Local Indexes
- Domain Indexes
- Attributes
The Object Window is used to view an object, and from that window you can directly see the various attribute values contained within the object. The Object Window shows you a subset of these values. From the Typescript Window, you can use the Profile command so see all the attribute values in an object.
What about COM Objects?
Are COM objects actually objects, as the name implies? The answer is that they are not Analytica objects, as identified above, although they do have similar characteristics in many ways. For example, whereas Analytica objects have attribute values, COM objects have properties. As mentioned earlier, the word object is used in many ways in computer science, and the term COM objects was created outside the context of Analytica. When you call COMCreateObject, a thing called a COM object is instantiated somewhere in your computer's memory (it can even be in the memory of a remote computer), but the result from COMCreateObject is a "moniker" or "pointer" to that object, which is a type of atomic value that is used to reference that thing. This pointer is an Analytica value.
Suppose you define a variable, A
, to be a call to COMCreateObject. Its result is a pointer to that COM object. If you then define variable B
to be A
, the pointer is copied, but there is still only a single COM object. Now both A
and B
point to the same COM object.
Indirect Referents
A Handle is an indirect referent to an Analytica object, and a Reference is an indirect referent to an Analytica value. These are the two fundamental forms of indirection referents. You can think of an indirect referent as a pointer. For example, an object exists somewhere in memory. There is only one copy of this object. But you might want to refer to this object -- that is the role of a handle. Similarly, a value exists somewhere in memory. You may want to refer to that value without making a copy of it -- a Reference allows you to do this. When you create multiple copies of a handle, the object itself is not copies -- they all point to the same object -- you end up with several handles to the same object.
Because Analytica is a functional language with referential transparency, a reference does not allow you to change the contents of a value. Any time you make a change to a value, a new copy must be made. However, the useful thing about a reference is that it is itself an atomic value. So even though it might "point" to an array, it acts as an atom for Array Abstraction.
Locals
Locals are identifies in expressions that act as names for either values or objects. There are a couple different types of locals:
- A value parameter of a User-Defined Function. A value parameter is any parameter that is not an alias parameter.
- An alias parameter of a User-Defined Function. An alias parameter is a parameter declared using one of the these qualifiers:
Index
,Object
,Variable
,Module
,Attribute
orClass
. - Local Indexes
- LocalAlias
- Local values, declared using Local..Do, or passed as value parameters to a User-Defined Function.
- A local with hybrid semantics, declared using For..Do, or one of the deprecated declarations constructs Using..Do or Var..Do. Hybrid semantics is a confused carryover from the distant past which persists only for backward compatibility.
Local indexes create an index object, which can then serve as the dimension on an array. The identifier of the local index is therefore a name that can be used to refer to the index object. Local indexes to not live in the global namespace, so they do not need to have a unique identifier. When you declare a local index, you can specify the object name explicitly, and it does not have to be the same as the local name. This is done using this syntax
LocalIndex I / "Name" := expr;
Within the lexical scope of I
, you can refer to this index object by I
, but the name of the object is actually Name
.
A LocalAlias declares a name for an object, that can be used within a local lexical expression scope. Hence, in the following declarations, I
, J
, and K
can be used as names for other pre-existing objects.
LocalAlias I := Data.Row;
LocalAlias J := Handle(Va1);
LocalAlias K := Contains of ModelDetailsModule;
In the last example, Contains of ModelDetailsModule
is a list of handles, but within the lexical scope of K
, K
will name only one of these objects at a time. The body expression -- that expression in the lexical scope of K
, will be evaluated once for each object in Contains of ModelDetailsModule
.
Most other local variables, declared using Local..Do (or the synonymous but deprecated MetaVar..Do)are alias to values. It is important to note that local variables are not Analytica objects, whereas global variables (those that show on influence diagrams) are Analytica objects. Again -- local variables declare a name for a value. There is only one value -- there is not a separate Mid-Value or Sample-Value. The value is computed and set when the variable is declared (or assigned to), and after that, the evaluation mode has no relevance.
Value semantics vs Alias semantics
Any given identifier either follows a value semantics or an alias semantics. Analytica does not enforce any strict naming convention for each, but many Analytica coders adopt the stylistic convention of using a lower-case letter for the first character of an identifier with value semantics and an upper case first letter for identifiers with alias semantics. Of course, this is an English-centric convention and may not transfer to your native language.
Since a global always has alias semantics, you would always capitalize a global variable. Similarly, since an index identifier has an alias semantics, index identifiers are capitalized.
Local identifiers declared with LocalAlias..Do or LocalIndex..Do have alias semantics, so would be capitalized. Conversely, locals declared with Local..Do have value semantics and hence are not capitalized.
Alias parameters (qualified with Index
, Object
, Variable
, Module
, Class
or Attribute
) use an alias semantics and hence are capitalized. All other parameters use value semantics (and are passed-by-value) and hence are lower cased. Since it is only a stylistic convention, and not enforced by the software, you cannot rely on other people's code adhering to the convention.
Whenever an identifier has an alias semantics, you can use it exactly as you would use a global identifier, as if it where the identifier of the object. Whenever an identifier has a value semantics, you can use the identifier as if it were a literal value (including possible an array value).
In between pure alias semantics and pure value semantics is a legacy hybrid semantics. As long as you are not dealing with handles, hybrid semantics acts basically the same as value semantics. But when dealing with handles, hybrid semantics is horribly inconsistent. It is a hold-over from bygone days that exists only to support backward compatibility for very old legacy models. The For..Do construct declares an identifier with hybrid semantics, but remains as a non-deprecated construct. The other declarations constructs that create an identifier with hybrid semantics have all been deprecated, but you may encounter them in legacy models. These constructs include: Var..Do
, Using..Do
and the Object
qualifier (which was replaced with the Alias
qualifier in Analytica 6.5, which of course uses pure alias semantics).
See Also
- The domain of possible values
- Values in Object Window
- Evaluation Modes
- Objects and Their Attributes
- Attrib of Obj
- Classes of variables and other objects
- Change class of an object
- Atom
- Array
- Class
- COM objects
- Object window
- Object menu
- Object Manipulation Typescript Commands
- LocalAlias
- Contains
- Identifier
- Numbers
- Handles to Objects
Enable comment auto-refresher