Analytica 4.2 beta Release Notes/Changes in 22.214.171.124
<< Back to Beta Tester Page
This page lists changes in 126.96.36.199 since beta build 188.8.131.52.
Known Bugs Introduced
We know of two bugs that have been inadvertently introduced into build 184.108.40.206:
- Function Evaluate -- issues a spurious warning that shouldn't be there.
- Function AskMsgText -- dialog messed up, so function doesn't work.
Both will be fixed in the next beta build. Since both involve esoteric functions, and since we wanted to get some enhancements to FindInText out in time for the Regular Expressions Webinar, we released this beta build anyway.
Changes to Dynamic
Build 220.127.116.11 introduced several enhancements to the processing of Dynamic models. Through the beta testing, we learned that some of these caused inefficiencies and introduced new problems into some legacy models. So we've refined this further, backing out to some degree a few of the enhancements. These changes restore/improve backward compatibility with models originally created in Analytica 4.1. If you did something in the 18.104.22.168 beta build that relied on these new enhancements, you might experience a change in functionality.
I will explain the primary issue in some detail here. If you aren't interested in the gory details, you can skip the remainder of this section without missing much.
Suppose Variable X is in a dynamic loop, and the identifier of Y appears in X's definition (e.g., perhaps X is defined as (1+Y^2)). During the evaluation of X, the sub-expression Y evaluates to
Y[Time=Time] -- i.e., only the Time-slice for the current dynamic evaluation context is returned. This is how it worked in Analytica 4.1 (and up through beta 22.214.171.124), and how it now works once again in 126.96.36.199.
In build 188.8.131.52, we attempted to generalize this, such that if Y was in the same dynamic loop as X, then Y[Time]] was used as before, but if Y was outside X's dynamic loop, then the full value of Y was returned. This made it possible to apply a function that operated over the Time index to the result, e.g.,
Sum(1+Y^2,Time). We also did this as part of an enhancement making it possible for a User-Defined Function to be part of a dynamic loop. In Analytica 4.1, UDFs always dropped the dynamic context, which made it possible for them to operate over the dynamnic Time index, but prevented them from actually being part of a dynamic loop.
In build 184.108.40.206, we've backed out this change when variables are being evaluated. As before, when a variable is being evaluated, an identifier Y always evaluates to Y[Time], as it always has. But, in a User-Defined Function, an identifier Y evaluates to Y[Time]] if Y and the UDF belong to the same dynamic loop, but Y evaluates to the full Y, unsliced along Time, when Y does not belong to the same dynamic loop. Therefore, UDFs that are part of a dynamic loop can operate over the Time index, provided the value they are operating over can be computed fully outside of the dynamic loop that the UDF belongs to.
These changes improve backward compatibility with models that were originally created in 4.1.
Suppose Y is not in X's dynamic loop, but you want to operate over Time on Y's result. How would you do that? Well, there are two possible methods.
Method 1: You could introduce a new variable, Z, that does the operation over Time on Y's value. Then you could use Z inside X's definition. This method works in 4.1. However, it also has a limitation - you can't operate over Time on a result that depends both on Y and on a dynamic value, such as
Sum(Y^X[Time - 1], Time).
Method 2: You can create a UDF:
Function Full(v: Variable) := v
Then inside X's definition, use
Full(Y) instead of
Y. For example:
Sum(1+Full(Y)^2,Time). This obtains the full unsliced value of Y since in a UDF the full value is retrieved.
- Repeated matches by FindInText: There is now options (controlled via 3 new optional parameters) that causes FindInText to return all matches, rather than just the first match found. This can be utilized with both plain-text matching and with regular expression matching. All the other various other options to FindInText remain applicable.
- When finding all matches, the result requires another dimension, and whenever we have an array dimension in Analytica, we need an index to represent that dimension. FindInText provides two options for this new dimension. You can either supply the index when you call it, specifying the index in the optional parameter «repeatIndex», or by not providing an index, you can let FindInText create a local index for the result. If you supply the index, the length of your index will place an upper bound on the number of matches that are returned -- if your index has length 5, then the only first 5 matches are returned.
- To find the position of all occurrences of the word the, with the result indexed by a local indexed named .Repeat:
- To find the position of all occurrences (up to
Size(J)occurrences) of words starting with a, and indexing the result by J:
FindInText("a\w*", myText, re: 1, repeatIndex: J)
- Finally, when using regular expression matches, the text matching a subpattern can be used as the labels for the local index created by FindInText. This subpattern is specified in the optional parameter «repeatSubpattern». When a named-subpattern is specified, the subpattern name is used as the local index name.
- The following parses the state name and corresponding population from an XML file. The result is an array indexed by a local index named .State, containing the name of the state, and the array values are the populations.
Var re := '<state.*?name="(?<state>.*?)".*?>.*?<population>(?<pop>/d+)</population>.*?</state>";
ParseNumber(FindInText(re, data, return:"S", repeatSubpattern: "state", subpattern: "pop"))
- Duplicate subpatterns in FindInText: If two subpatterns in a regular expression have the same name, FindInText will return data for the first one that matches something. Duplicate subpattern names can be useful in a disjunction. In the following example, a data item might either contain only numeric digits, or it may be surrounded by quotes if it contains commas between digits. So for example, we might match to
"45,678"(with quotes in the second case). So the regular expression would be:
- In the example, the named subpattern "X" occurs twice. When matched to
"45,678", the first disjunction matches, so
FindInText(...,subpattern:"x",return:"S")returns '45,678'. When matched to
45678, the same expression returns '45678'.
- ConcatRows -- the 2nd and 3rd («r» and «c» index parameters) are now optional to the built-in function ConcatRows. When omitted, your array should have either an index created by a previous call to ConcatRows or Concat, which is then implied, or an implicit dimension, which is then implied. The first case simplifies nested ConcatRows and Concat calls, for example when flattening over two dimensions. The second case is necessary since you cannot otherwise name an implicit dimension.
- Evaluate: Given a handle to a function, Evaluate can now be used to call the function. Parameters to be passed to the function are provided as the second, third, fourth, etc., parameters to evaluate. For example:
- Note: When only 1 parameter is given to Evaluate, a spurious warning that should not appear occurs in build 220.127.116.11, which will be fixed in the subsequent beta build.
- value Of obj: Now does not trigger the computation of obj -- returns whatever value for obj is currently cached (if any). The same holds for the typescript command "value obj", as well as for the probValue attribute. If you want the old functionality -- forcing of full evaluation before returning the value -- use Mid(X) or Sample(X). This subtle enhancement has a very practical use. If a variable is computed within a dynamic loop, at any given moment only a subset of Time-slices may be computed, with the others being Undefined (signifying that they are uncomputed). Particularly when debugging complicated dynamic loop bugs, having access to this partially computed result can be extremely helpful. To view, you can create a variable, Tmp, and in typescript type: (Tmp := value of X), with parens, then view the table for Tmp.
- The ability to change the color of a line on a plot by right-clicking on the data series in the graph was added in 18.104.22.168. It was only enabled when there was a color key (i.e., more than one color). You can now use this to change the line color when there is only one line.
- ReadImageFile - This new experimental function was added. It will remain unexposed for the time being, and may be subject to change.
- In cases where two local indexes have the same name, and both appear as indexes in a result, result tables and graphs can now distinguish the two, so that you can successfully pivot. It is a very bad practice to intentionally do this, of course, since you wouldn't be able to unambiguously name one particular index in an expression. But it isn't unheard of to encounter this case when debugging a buggy expression.
- In many cases, when an evaluation error occurs, and you press the [Edit Definition] option on the dialog, it will now take you to the definition and place the cursor at the position in the expresson where the error occurred. It is able to do this in the majority of cases, but not every case.
Notable bug fixes
(minor bug fixes not listed here)
- Fixed: Choice input control on diagram turns to text when pressing edit definition
- Fixed: Graph series color sometimes didn't stick when pressing [Set Default]
- Fixed: License activation glitch. (If you activated the same beta tester license on 2 or more different computers, when updating either from 22.214.171.124 to 126.96.36.199, or from 188.8.131.52 to 184.108.40.206, you may (or may have) enountered an error saying you've exceeded the maximum number of activations. With this update to 19, you may experience it again on the second computer, but with this fix, you should be okay for future beta updates. t
- Fixed: Several bugs, including a crash, when using the «keyIndex» option with Rank
- Fixed: Internal error reported with Sort when array was underdimensioned.
ADE Enhancements and fixes
- A new boolean property, NewLineAsCRLF, has been added to CARenderingStyle. It defaults to true to match previous behavior. When true, new line characters are converted to the [CRLF] combination when text is retrieved. This is what you want from a CScript when echoing results (and other cases) so the newlines print correctly. When the falg is false, new line characters are not converted. So if an internal text value contains only [CR], then the result contains only [CR], with on conversion.
- Fixed a bug in which in some cases, CAEngine::ErrorCode did not reflect the fact that an error occurred during evaluation of a variable, e.g., during execution of CAObject::ResultTable or CAObject::Result.
- The dialog that appears when you type
ADE.EXE /RegServernow contains the host id, which is used by the license manager, and is required for license manual activation.
- An intermittent crash that occurred when CAEngine::GetObjectByName was called with an empty string was fixed.
- A problem in which linked submodules located in different directories would, in certain cases, not be found and thus would not be loaded when the model was loaded, was fixed.