Statements are the fundamental element of NCL. Everything NCL does happens only after a statement is entered. Statements are not restricted to being a single line of source, and statements can be nested within statements. There are 17 different kinds of statements: assignment, procedure call, function definition, procedure definition, block, do, if-then, if-then-else, break, continue, setvalues, getvalues, return, record, new, stop, and quit.
There are two very important things to understand about statements. First, each statement only executes after it has been parsed and is found to be free of syntax errors. Second, if a runtime error occurs while executing a statement, execution of the statement and any statements in which the erroneous statement is nested is immediately terminated.
begin
The are two kinds of if statements: the if-then statement and the if-then-else statement. These function like if statements in other popular programming languages. The following is the syntax for the NCL if statements:
if(scalar_logical_expression) then
The scalar_logical_expression is an expression made of relational operators. For if statements, the result of the logical expression within the parentheses must result in a single scalar value. Since logical operators can operate on entire arrays of values, produce array results, and each element in the array result could be True, False, or a missing value, if statements require the results of the logical expression to be a single scalar logical value. When if statements encounter a missing value instead of True or False, a FATAL error message is generated and execution is terminated if the if statement is in a block statement list. There are three intrinsic functions that help with this problem. The intrinsic functions any and all return a single True scalar value if any element in a logical array is True, or if all elements in a logical array are True, respectively. The intrinsic function ismissing returns True if the input to it is a missing value. Combined with lazy conditional expression evaluation, the ismissing function can filter possible error conditions before they occur.
Lazy expression evaluation means that if the first term of an .AND. expression is False, or the first term of an .OR. expression is True, the entire expression--regardless of the result of the remaining terms--is False and True respectively. When this is the case, NCL does not evaluate the remaining terms. This is a very useful tool for avoiding error conditions. For example, consider the integer i and the array a. Lazy evaluation can avoid indexing the array a with i when i is out-of-range. The following example demonstrates this:
if((i .lt. dimsizes(a)) .and. (a(i) .gt. 10 )) then . . . end if
do identifier = scalar_start_expr , end_expr
The following shows how to specify a stridden loop. The following form is also necessary to loop backwards. With this form, if start is greater than end, then the identifier is decremented by the stride value, which must always be positive. If the start is less than the end, then the identifier is incremented by the stride value.
This example shows the while loop syntax. The scalar_logical_expression adheres to the same restrictions placed on the conditional expression of the if statement. Specifically, it must be a scalar logical value and not be a missing value. Also lazy evaluation of .AND. and .OR. statements occurs.
The assignment statement can be used to assign values of any type to variables, subsections of variables, coordinate variables, and attributes. In addition, the assignment statement is used to assign string values to dimension names. Several NCL language constructs are used to identify what type of assignment is to take place. The constructs '->', '!', '&', and '@' are used to specify file variable assignment, dimension name assignment, coordinate variable assignment, and attribute assignment, respectively. Without these constructs, normal-value-to-variable assignment occurs.
a!0 = "Dimension1" file->a!0 = "Dimension1"
a&Dimension1 = (/.1,.2,.3,.4,.5,.../) file->a&Dimension1 = (/.1,.2,.3,.4,.5,.../)
a@units = "Degrees C" a@_FillValue = -9999.0 file->a@units = "Degrees C"The _FillValue attribute is a special reserved attribute. It allows the user to associate a missing value with a variable. This allows values to be filtered when the array of values is an operand to an algebraic expression. When set, all of the missing values in the value array referenced by the variable are changed to the new missing value.
NCL procedures, in many ways, are the same as in most programming languages, but NCL procedures also have some distinct differences. The key differences are in how the types and dimension sizes for parameters are specified and handled by NCL. In NCL, parameters can be specified to be very constrained and require a specific type, number of dimensions, and a dimension size for each dimension, or parameters can have no type or dimension constraints. Parameters in NCL are always passed by reference, meaning changes to their values, attributes, dimension names, and coordinate variables within functions change their values outside of the functions. There is one very important exception that does generate a WARNING message: when a parameter must be coerced to the correct type, the variable is not affected by changes to the parameter. Even parameters that are subsections of variables are passed by reference. When the procedure finishes, the values of the subsection are mapped back into their original locations in the referenced variable.
Functions and procedures are defined using a similar syntax; the only difference is that the keyword "procedure" is used instead of the keyword "function". To define a new function, the proper keyword is entered, followed by the name to assign the function to, followed by a list of declarations that can optionally be followed by a list of local variable names. Finally, a block of statements follows.
It is very important to note that if a variable is intended to be local to the function or procedure does not occur in the local list that the function may find that variable name outside of the scope of the function or procedure. It is very important to note the consequences of not putting a local variable into the local list. There are two possibilities. First, if the variable is defined at the time of function definition and is in the function's scope, the variable will be referenced. If the variable is not defined at the time of definition, it will be an undefined variable local to the function. Placing the local variable's name in the local list assures that the variable truly is local only to the current function. The scope rules for NCL are identical to Pascal. The main NCL prompt is the bottom level of NCL's scope. Function and procedure blocks are the next level. When a variable is referenced in a function, NCL first looks within the scope of the function for that variable. If it doesn't exist, NCL looks in the scope containing the function and continues to search outward until either the bottom level is reached or a variable of the correct name is found. If it is not found, then an undefined variable reference error message is generated.
As mentioned previously, parameters can be constrained or unconstrained. The following shows the syntax of the variable declaration. The square brackets ( '[' and ']' ) are used to denote optional parts of the declaration syntax and are not part of the structure of the declaration list. Each declaration in the declaration list is separated by a comma.
Declaration list element syntax:
Unlike the preceding example syntax, the characters '[' and ']' are part of the syntax for the dimension size list. They are used to separate dimension sizes. Each pair of brackets can contain an integer representing the size of the dimension or a star to indicate that the dimension may be any size. The number of pairs of brackets is the number of dimensions the parameter will be constrained to.
Dimension size list syntax:
Local variable list syntax:
The local variable list is very important. If a local variable name is not in the local list and the same identifier is defined in a lower scope level, then the variable reference in the function or procedure will refer to that variable. Sometimes this may be the desired effect. However, if the variable is to be local, it should be referenced in the local list.
The create visualization block is actually an expression; it is described here for consistency. The create block returns an id to a newly created HLU object. HLU resources are assigned using the syntax for the NCL resource list. In NCL resource lists, resource names are entered by their string representation followed by a colon (':') and an NCL expression. The create block requires a string name for the HLU object, which can be different than the name of the variable it is being assigned to. Create also requires a HLU object class identifier that tells NCL what type of HLU object to create. Finally create either needs a reference to the object's parent, usually a workstation, or the keyword "defaultapp" to signify that the object's parent is the default application class. Refer to the HLU user guide and reference guide for a discussion of HLU objects and application classes.
Use setvalues to modify resources in an HLU object after it has been created. setvalues takes an NCL resource list in the same fashion that create does. It then sets each resource to its corresponding value.
load "file_path"
The record command will cause all syntactically correct commands entered at the command line to be saved in the file pointed to by the file_path literal string value. The "stop record" command terminates this process.
NG4 Home, Index, Examples, Glossary, Feedback, Ref Contents, Ref WhereAmI?