Function parameter qualifiers

Revision as of 15:04, 27 November 2006 by Fredbrunt (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Evaluation Mode Qualifiers

IndexType

Synonyms: Index, IndexType

Notable Combinations:
I : IndexType
I : optional IndexType
I : ... IndexType
I : ... optional IndexType
I : IndexType = J
I : IndexType = Run

Declares that the parameter should identify an index object. The Index may be either a global or local index. If the argument to the function is an identifier containing a self-index (or domain) and a value, the self-index (or domain) part is referenced here.

When used with the ellipsis notation, a list of indexes may be specified.

Parameters declared as indexes may appear in the dimensionality declaration of other non-index parameters -- see "Array" keyword below.

Prob

Synonyms: Prob, ProbType, Probabilistic, Uncertain

Forces the parameter to be evaluated in probabilistically, independent of the context evaluation mode.

Samp

Synonyms: Samp, Sample, SampType, SampleType

Like Prob, it forces the parameter to be evaluated in probabilistic mode, irrespective of the context mode, but it gives an error message if the resulting value is not uncertain -- i.e. it does not contain the Run index.

Determ

Synonyms: Determ, DetermType, DetermMode, Mid, MidMode

Forces the parameter to be evaluated in Mid (deterministic) mode, irrespective of the context evaluation mode.

Context

Synonyms: Context, Expr, ContextType, (nothing specified)

This is the default if no other evaluation mode is specified.

The parameter is evaluated in the current evaluation mode, i.e., the same evaluation mode used to evaluate the function being called.

Unevaluated

Synonyms: Unevaluated, Expression

This qualifier is of little use within user-defined functions, but is used in various built-in functions, where the internal code can manipulate or interpret the expression directly. The argument is not evaluated before the function is called, leaving it up to the function to evaluate the expression if appropriate.

ContextSamp

Synonyms: ContextSamp, MaybeSamp, ContextSample, MaybeSample

Typical usage:
Parameters: ( A : ContextSamp[I] ; I : optional Index = Run )

A parameter declared using ContextSamp could be evaluated in either Context mode or Prob mode (see Context and Prob qualifiers), depending on whether the Run index is passed to the function. If any of the index dimensions in the declaration of the function bind to the Run dimension, then the parameter is evaluated in Prob mode; otherwise, it is evaluated in Context mode.

For example, the built-in function:

  Mean( X : ContextSamp[I] ; I : Index=Run )

will evaluate in Prob mode when called as: Mean(Ch1) or Mean(Ch1,Run), but will evaluate in determ mode when called as Mean(X,J) -- equivalent to Average(X,J).

When the parameter declaration contains more than one dimension, Prob mode is used if ANY of the indexes is the Run index.

VariableType

Synonyms: Variable, VariableType, Var, VarType

Typical usage:
Fu1( Z : VariableType )

[MH: Should we call this ObjectType, since it can refer to any class of Analytica object, not just a Variable? Or would it be better to offer a several such qualifiers, to specify what Class of Object is acceptable? E.g. ModuleType (any module type, including Model, Module, Library), VariableType (any Variable type, including Index, Constant, Chance, Decision, and Variable), or ObjectType, that allows an Object of any class. Alternatively, we could add ObjectType <Class>, where <class> can be any Analytica class. Should or could you be able to pass an Attribute, or User-defined Function, or System Function to an ObjectType parameter?]

[MH: Please review changes below]

A VariableType parameter must identify an Analytica object (variable, module or other class of Analytica object). The actual parameter can be simply the identifier of an object, or an expression returning an identifier, such as GetVarFromName(x), or X.I, or (Identifier OF x).

Within the Definition of the function, the parameter name X serves as an alias for the original object, and can be passed to other functions that expect objects (i.e., VariableType parameters), such as WhatIf(y, X, x0), or <attrib> Of X, or X Of o if X is the name of an Attribute. A Function called from a Script (not called from a Variable) can assign to the parameter, X := <expr>, hence assigning a new definition to the variable X refers to. In other contexts, if X is in an expression or a parameter to another function that evaluates its parameters, Analytica evaluates X to return its value.

The VariableType qualifier is similar to pass-by-reference in other computer languages. When called from a script (with no caching variables involved), the underlying variable's value, probValue, or other attributes, can be assigned to. (However, because of a prohibition on side-effects with dependency maintenance, you can't assign to the object when a function is called from a variable evaluation).

If the VariableType qualifier is followed by a Datatype qualifier, such as:

 Fu3( X: VariableType Number)

Analytica will evaluate X when calling Fu3 to check that its value has the specified Datatype. But, in the Definition of Fu3, it will treat X as an unevaluated VariableType, as just above.

 [LC: I'm not sure if this really happens -- need to check].

LVarType

This qualifier is for internal use by built-in functions. It is a variation on the VariableType qualifier.

VarList

Synonyms: VarList, VariableList, Variable List, List of Variable Related: List of IndexType

Specifies that a function expects a list of variables -- i.e., a list of pointers to Analytica objects. An example of such a function is the built-in WhatIfAll function.

If you are really interested in passing variable number of variable objects into a function, the preferable declaration is to use the ellipsis qualifier:

( Vs : ... VariableType )

In this case, each argument is not evaluated, and the reference to that object is passed. Inside the function, Vs contains a list of VarTerms.

When the VarList parameter is used, as with the declarations:

( Vs : VarList )
( Vs : VarList[ ] )
( Vs : VarList[I] )
( Vs : List[I] of Variable )

or with the related declaration:

( Vs : List[] of IndexType )
etc.

Then the argument IS evaluated. The elements of the evaluated result must then be VarTerms. If not, an error results. In normal Analytica usage, it is pretty unusal for a result to evaluate to VarTerms. If you use an identifier within an expression, it will evaluate to the underlying value, so it doesn't work to pass a list of identifiers. For example:

Function Fu1( Vs : VarList )
Function Fu2( Vs : ... VariableType )
Fu1( [ Va1, Va2, Va3 ])    -- no good
Fu1( GetVariableByName(["Va1","Va2"]) ) -- Good
Fu2( [ Va1, Va2, Va3 ])    -- good
Fu2( Va1, Va2, Va3 )       -- good, equiv to previous
Fu2( GetVariableByName(["Va1","Va2"]) ) -- no good

Dimensionality Qualifiers

Dimensionality qualifiers declare the dimensions of each parameter that are expected by the function within the function definition. These allow Analytica to apply Horizontal Array Abstraction, iterating over extra indexes until only the allowed dimensionality is reached, evaluating the function repeatedly for each slice, and reassembling the results. When multiple parameters have dimensionality qualifiers that require each to be iterated, Analytica's function invocation coordinates the iteration so that indexes impacting multiple parameters are iterated together.

Array

Typical Usage:
( X : Array[Time,I,J] ; I : IndexType ; J : optional IndexType )

The Array qualifier is also referred to as a dimensionality declaration, since it is used to declare the expected dimensionality of a parameter. The keyword "Array" is optional -- a list of indexes inside square brackets implies the Array qualifier (unless the vector or list qualifiers are used, both of which are slight variations on the Array qualifier semantics).

The Array qualifier specifies that the parameter is a multi-dimensional array (of zero or more dimensions), and is most importantly used to declare what those dimensions are. Inside the body of the function, parameter variable is guaranteed to contain no dimensions other than those declared. Analytica iterates over the function, calling it repeatedly on successive slices when an argument contains extra dimensions, so that this guarantee is satisifed within the function body -- this is the basis for Array Abstraction.

Suppose A is indexed by Time, In1, In2, and In3 and that a function having the above Typical Usage declaration is called as F(A,In1). Analytica will iterate over all combinations of In2 and In3, slicing A at each combination and calling F, such that inside the function body, parameter X is indexed only by Time and In1 (and parameter I is an alias for In1 inside the function body).

The Array keyword is optional, the brackets alone have the effect of declaring the dimensionality. Thus, the following are the same:

(X : Numeric Array[Time] )
(X : Numeric[Time] )

An array declaration does not add in dimensions, so for example, if in the earlier example, if the function were called using: F(5,In1), inside the function body X will be the scalar 5 -- the dimensions Time and In1 are not automatically added to the parameter. However, since for all array-abstractable function, 5 is equivalent to an array containing 5 for every element, computations will usually remain equivalent (and sometimes more efficient) even if the argument does not contain the dimension. The All keyword (described elsewhere on this page), used in conjunction with a dimensionality declaration.

When creating user-defined functions using procedural programming constructs, it is highly recommended that you explicitly declare dimensionality of each parameter using the array qualifier. Constructs such as While loops or local index sequences are then more likely to continue working if dimensions are added to your model later.

Atomic

Synonyms: Atomic, Atom, AtomicType, AtomType

Typical Usage:
( X : Atomic )

Specifies that the parameter is atomic -- a single element. If an array is passed to this parameter, Analytica will iterate over its dimensions so that at each call the parameter value is guaranteed to consist of a single element, typically a number, text string, a reference, or the value Null.

In esoteric cases, some internal data types can also be passed, which could theoretically include an parsed expression structure, a varset, a data blob (such as an image), a LP, QP or NLP problem-specification object.

Because an atom is considered to be a zero-dimensional array, the atomic qualifier is functionally equivalent to the Array qualifier with zero indexes, i.e.:

( X : Array[ ] )

Scalar

Synonyms: Scalar, ScalarType, Scalars

Typical usage:
( X : Scalar )

The scalar qualifier is an alias for "numeric atomic".

Vector

Synonyms: Vector, VectorType

Typical Usage:
( X : Vector[I] ; I : optional IndexType )

The vector qualifier specifies that the argument passed must contain at least one dimension, even if that dimension is not explicitly specified. When there is an explicit index provided, the behavior is the same as the Array qualifier. The distinguishing behavior occurs when no index is specified, such as when an optional index is omitted in the typical preceding typical usage. In such a case, array abstraction is applied to a vector parameter until a single dimension remains, while in the case of Array it would be applied until the parameter is scalar. When the parameter contains multiple dimensions, the default single remaining dimension will be the canonically first dimension. If no index can be identified, an error results.

Examples:

Fu1 ( X : Vector[I,J] ; I,J : optional IndexType ) 
Fu2 ( X : Array [I,J] ; I,J : optional IndexType )
Fu3 ( X : Vector )
Variable A := (indexed by In1 and In2)
Dimensionality of X within function body:
   Fu1(A)  ==> X is dimensioned by In1.  Iterates over In2.
   Fu2(A)  ==> X is atomic. Iterates over In1 and In2.
   Fu1(A,In2) => X is dimensioned by In2.  Iterates over In1.
   Fu1(A,In1,In2) => X is dimensioned by In1 and In2.
   Fu3(A)  ==> X is dimensioned by In1.  Iterates over In2.
   Fu1([A,A^2])  ==> X is a null-indexed list of atoms.  Iterates over In1 and In2.
   Fu2([A,A^2])  ==> X is atomic.  Iterates over null-list, In1 and In2.

Note that the example illustrate the difference between Vector and Array qualifiers.

Many built-in Analytica functions that operate on 1-D parameters act as if they are declared in this fashion (internally not all built-in functions use the newer parameter scheme documented here). These include Sum, Min, Max, Product, Cumulate, Uncumulate, CumProduct, etc.

List

Synonyms: List, ListType

Typical Usages:
( L : List[ ] )
( L : List All [ ] )
( L : List[ I ] ; I : IndexType )

The List parameter qualifier is a variation of the Array qualifier that is used when a null-indexed dimension is expected, and the function does not want array abstraction it iterate over and remove that dimension before evaluating the function.

The array qualifier has no syntactic variation that allows you to the Null-dimension within the list of dimensions. The so-called Null-dimension does not really correspond to an actual Analytica object, but rather is a term that refers to a list. But, essentially, a declaration "List[I,J]" would be the conceptual equivalent of "Array[NullDim,I,J]". It declares that the parameter may be indexed by the null-dimension, I, and J. Without the All qualifier, none of these dimensions are required, but they are the only ones allowed.

As is the case with the Array qualifier, a List declaration with no brackets is allowed but not particularly useful, since it doesn't restrict the dimensionality of the parameter.

The declaration ( L : List[ ] ) specifies that only the null-dimension is allowed. If the argument is not a list, then L will be atomic at each function invocation. If the argument has a null-dimension, then all other dimensions are iterated, with only the null-dimension passed to the function.

When the All qualifier is included, as in ( L : List All[I] ) or (L : List All[ ] ), then both the specified index(es) and the null-index are required. When a null-index is added, Analytica has no reference index object to determine its length, so a null-list of length one is added.

When the list qualifier is used in conjunction with the VariableType or IndexType qualifiers, a somewhat different treatment results. For these cases, see the VarList qualifier. "Variable List" or "List of Variable" is synonymous with "VarList".

All

Typical Usage:
( A : Array All[I,J] )

The All qualifier is used in conjunction with the Array qualifier (or the Vector or List qualifier) to specify that the function definition expects all listed indexes to be present. Without the All qualifier, the declaration specifies the dimensions that are allowed, but does not guarantee that the parameter actually has these dimensions. With the All qualifier, the function body is guaranteed that the parameter has all and exactly the listed dimensions.

If an argument to an array parameter has extra indexes not listed, the are iterated, whether or not the All qualifier is present. If the parameter names indexes that are not present in the argument, these dimensions are added to the value in such a manner that the actual value is constant across the added dimensions. Internally, these are added as sparse dimensions, so that there is very little memory or time penalty involved in passing the extra dimensions; however, if your definition operates over that dimension, intermediate or final results may require more memory, because for example, those intermediate value may no longer be constant over those dimensions.

Data Type Qualifiers

Each parameter may have zero or one data type qualifier, specifying the required data type for all atomic elements passed to the parameter. It may be used in conjunction with any of the evaluation modes, including for example IndexType (in which case the index elements are tested), as well as with any dimensionality declarations. The presence of absence of the coerce keyword determines whether Analytica attempts to coerce atomic values into the indicated data type or flags values as errors. The data type is optional, and if omitted, no data type checks are performed when a function is called. A small performance penalty is incurred at the time of a function call when the data type is specified.

Numeric

Synonyms: Numeric, Number, Numbers, NumberType, NumericType, Num, Real, Boolean

( X : Numeric )

Here X must be a number, the special values INF, -INF, or NaN, or an array containing only these types of values.

Textual

Synonyms: Textual, Text, TexType, TextType

( S : Textual )

Here S must be a text string, or an array containing only text string elements.

Reference

Synonyms: Reference, Ref, RefType, ReferenceType

( R : Reference )

R must be a reference, or an array of references. The reference may point to any Analytica value, data types and other restrictions on the underlying value cannot be specified within the parameter qualifier list.

Positive

( X : Positive )

Numeric and positive.

NonNegative

Synonyms: NonNegative, PositiveOrZero, NotNegative

Numeric and zero or positive.

Coerce

Synonyms: Coerce, Coerced

Typical Usages:
( S : coerce textual; X : coerce numeric )

Attepts to force arguments into the declared parameter data type.

When parameters are coerced to textual, a string representation of each atomic value is rendered (atomic values that are already textual remain unchanged). The number format for the object calling the function is used for the coercion -- not the number format for the function. (If a coercion occurs within the body of the function, such as with the expression ("" & s ), then the number format of the function is used.

Examples:

Fu1 ( S : coerce textual ) := S      # format = short date
Fu2 ( S ) := Fu1( S )                # format = fixed pt currency w/commas
Fu3 ( S ) := "" & S                  # format = #.##% trailing zeroes
Va1 := Fu1( 39K )                    # format = suffix
Va2 := Fu2( 39K )                    # format = exponential
Va3 := Fu3( 39K )                    # format = long date

A number to text coercion occurs in the evaluation of Va1, Va2 and Va3. In the case of Va1, Va1's number format determines the coercion. In the case of Va2, Fu2's number format is used. In the case of Va3, Fu3's number format is used. Thus the results would be:

 Va1 = '39K'
 Va2 = '$39,000'
 Va3 = '3900000.00%'

When coercing to numeric, strings containing numeric values are parsed. Thus, the string "45" would be parsed to the numeric value 45. The number format of the caller determines whether the value is parsed as a date, in the same manner as the coercion to string previously described.

Coercion to a reference will cause add a reference to an atomic value that is not already a reference, resulting in a reference to a number, reference to a string, etc.

In all cases, if a coercion is not possible (including the case where a string can't be parsed to a number), an error results.

Ordering Qualifiers

Ascending

Typical Usages:
( A : Ascending[I] )
( L : Ascending List[ ] )
( I : Ascending IndexType )

The ascending qualifier specifies that the values of a list, vector, array, or index must be in non-strictly ascending order. Use of this qualifier requires that the declaration specifies a one-dimensional parameter. Without one dimension, the index over which it must be ascending is ambiguous, and hence an error is issued.

The test triggers an error if any element is less than the value that precedes it. The test is non-strict, so that a constant array, or an element equal to its precedesor, does not trigger an error. There is no parameter qualifier variation that tests for strict ascending order.

Descending

The descending qualifier specifies that the values of a list, vector, array, or index must be in non-strictly descending order. It is the exact dual of the Ascending parameter qualifier -- see the description above for Ascending for details.

Optional Parameters

Optional qualifier

Synonyms: optional, opt

Typical uses:
( X : optional )
( A : Array[I] ; I : optional IndexType )

The optional qualifier specifies that a parameter is optional. With the keyword, a default value is not necessary. Inside the function body, a user can test whether a parameter was providing using the function IsSpecified(...) or conversely, using IsUndef(...).

In the body of your function, you can pass a parameter declared as optional as a argument to another function having an optional parameter. If the parameter is not specified to the first function, it will appear to the second function as if it is not specified as well. Within the body, should the parameter variable itself be used, it contains the special system value Undefined.

Optional can be applied to values or indexes. Using the optional qualifier on index parameters causes array parameters using that index to be of variable dimensionality.

Note: Use of the ellipsis qualifier, or the inclusion of a default value, are alternative means to specify optional or variable-length parameter lists.

Default values

Syntax: ident : qualifiers = defaultValue

Typical Usages:
( X : optional Numeric = 0 )
( X : Numeric = 0 )
( A : ContextSamp[R] ; R : IndexType = Run )

An explicit default applies to an optional parameter and provides a value that is used when the parameter is omitted in a call. For value parameters, the optional value should usually be a constant, although an expression is also accepted. For Index and Variable parameters, the optional value must identify an index. For these Unevaluated parameters, it may refer to another parameter earlier in the declaration.

The optional qualifier keyword is implied when a default value is provided. Therefore, the optional keyword is itself optional, although stylistically it makes the declaration more readable.

This feature may not be extremely robust when general expressions are used for the default. Therefore, it is recommended that you try to limit your default values to simple constants.

Ellipsis (...)

Typical Usages:
( X : ... Scalar )
( A : Array[I] ; I : ... IndexType )
( A : Array[I] ; I : ... optional IndexType )

The ellipsis qualifier, consisting of three dots, declares a variable number of parameters having the same type and same parameter name. Inside the function body, the parameter variable will contain a list of values, rather than a single value.

By using the ellipsis on an index parameter, it is possible to specify array parameters having a variable number of explicit dimensions. Arguments passed to an ellipsis parameter are NOT allowed to contain a null dimension. (However, an explicit bracket syntax can be used to group a variable number of arguments in the call, see examples below).

If the ellipsis is used without an optional qualifier, one or more instances of the parameter may appear in a function call. When used in conjunction with the optional qualifier, a call may include the parameter zero or more times.

Consider these examples:

Function ValMax( X : ... scalar ) := Max(X)
Function Total( A : Array[I] ; I : ... IndexType ) 

The ValMax function returns the maximum value of its parameters. For example,

ValMax(3,6,-2,4) 

would evaluate to 6. Note that inside the body of the function, X is the null-indexed list [3,6,-2,4]. ValMax could also be applied to array arguments, such as

ValMax( sqrt(X), X^2, 0 )

The Total function takes the sum of its parameter over one or more dimensions -- a generalization of Sum(A,I). For example, you could write:

Total(A,In1,In2,In3)

as an alternative to Sum(Sum(Sum(A,In1),In2),In3).

Inside the body of Total, A would be an array containing the null-index, along with all dimensions listed in the I parameter.

Several syntaxes may be used when calling a function containing an ellipsis parameter. When the parameter is named in the call, then all arguments that follow are considered to be instances of that parameter up until another parameter name is indicated. For example, in the declaration:

 Fu1 ( X : ... scalar ; Y : ... optional scalar )

A function call that uses named parameters could appear as:

Fu1( X : 1,2,3,4 , Y:5,6,7 )

Here the first four arguments, 1,2,3,4, are sent as parameter X, while the last three arguments are sent as parameter Y. You could also name only parameter Y:

Fu1( 1,2,3,4, Y : 5,6,7 )

Since X is the first parameter, it is understood that the first four values are instances of X. In this case, it is necessary specify Y values by name.

Ellipsis parameters can also be grouped in brackets, thus allowing positional syntax, e.g.:

Fu1( [1,2,3,4], [5,6,7] )

Note that in this case there is no ambiguity if Y is not called by named. One you use brackets to group the arguments, the brackets circumscribe all arguments corresponding to that parameter.

The use of ellipsis on indexes is useful for allowing a variable dimensionality of incoming arrays, and for ensuring a minimum number of dimensions, but using the individual indexes explicitly from within the user-defined function is not really possible using Analytica's existing expression language (it requires the use of meta-level language constructs, which are not exposed publically at this time). The total function above might be implemented as:

 Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(Sum(A)))))))))))))))

which would work up to 15 dimensions (the maximum # of dimensions allowed in Analytica anyway), but note that the indexes are not specified explicitly. It would be very difficult currently to use the I parameter in the function itself.

Note that ellipsis indexes can be mixed with non-ellipsis indexes in array declarations, e.g.

( A : Array[I,J] ; I : IndexType ; J : ... IndexType )

In this example, 2 or more indexes could be specified, since I is required and one or more instances of J is required.

Other Qualifiers

Hidden

When marked as hidden, a parameter will not be exposed to a user in the object finder dialog, or when pasting the definition via the definition menu. The parameter, however, is there and can be specified in a function call.

Internally Analytica makes use of hidden parameters in the following construct:

( A ; exprA : hidden unevaluated = A )

This allows the underlying implementation access to the expression for A, while still receiving the evaluated parameter A (suitably iterated and typechecked if other qualifiers are attached to A).

Of

The Of qualifier is ignored by the parameter qualifier parser, but can be included within qualifier list for stylistic preference, such as:

( X : Ascending Array[I,J] of Numbers )
( L : List of Numbers )

as equivalent alternatives to

( X : Ascending Numeric Array[I,J] )
( X : Numeric List )

and so on. Note that qualifiers can appear in any order, and contain various aliases (such as Numeric or Numbers) to make either stylistic variation sensible, depending on user preference.

Deprecated Qualifiers

These qualifiers originated in earlier releases, and have been replaced by simpler or more flexible constructions. They still work in Analytica 4.0, but we do not guarantee to support them in future releases. So, we strongly recommend that you avoid them.


Synonyms

Some qualifiers have synonyms with identical meaning to the original name, introduced in previous releases. We strongly recommend that you use the preferred name as listed above, and not one of the synonyms. We list these synonyms only for the benefit of those looking at old Analytica code.

Original: Array Synonyms: ArrayType, Arr

Comments


You are not allowed to post comments.