diff options
Diffstat (limited to 'doc/gawktexi.in')
-rw-r--r-- | doc/gawktexi.in | 185 |
1 files changed, 183 insertions, 2 deletions
diff --git a/doc/gawktexi.in b/doc/gawktexi.in index bfefda24..651bd8d2 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -778,6 +778,7 @@ particular records in a file and perform operations upon them. * Function Calling:: Calling user-defined functions. * Calling A Function:: Don't use spaces. * Variable Scope:: Controlling variable scope. +* Local Variables:: Enhanced Awk (@command{egawk}) local variables. * Pass By Value/Reference:: Passing parameters. * Function Caveats:: Other points to know about functions. * Return Statement:: Specifying the value a function @@ -20376,6 +20377,7 @@ the function. @menu * Calling A Function:: Don't use spaces. * Variable Scope:: Controlling variable scope. +* Local Variables:: Enhanced Awk (@command{egawk}) local variables. * Pass By Value/Reference:: Passing parameters. * Function Caveats:: Other points to know about functions. @end menu @@ -20414,8 +20416,11 @@ there is no way to make a variable local to a @code{@{} @dots{} @code{@}} block good practice to do so whenever a variable is needed only in that function. -To make a variable local to a function, simply declare the variable as -an argument after the actual function arguments +Enhanced GNU Awk (@command{egawk}) has language extensions in this area, +described in @ref{Local Variables}. + +In standard @command{awk}, to make a variable local to a function, simply declare the +variable as an argument after the actual function arguments (@pxref{Definition Syntax}). Look at the following example, where variable @code{i} is a global variable used by both functions @code{foo()} and @@ -20540,6 +20545,182 @@ At level 2, index 1 is not found in a At level 2, index 2 is found in a @end example +@node Local Variables +@subsubsection @command{egawk} Local Variable Extension +@cindex @code{@@let} statement +This @value{SECTION} describes an extension specific to a custom +version of GNU Awk called Enhanced GNU Awk, which is installed +under the command name @command{egawk}. + +As documented in @ref{Variable Scope}, function-wide local variables +are defined as function parameters in standard @command{awk}. The +language does not distinguish parameters used as local variables +from true parameters that receive arguments. This is only a programmer +convention, which is enforced by discipline and the use of traditional +annotation devices, such as visually separating the parameters intended +for argument passing from the parameters intended to serve as local +variables. + +@command{egawk} provides a language extension in this area, allowing +the programmer to specify conventional function-wide local variables which do +not appear in the parameter list and cannot receive arguments. + +The extension takes the form of the construct @code{@@let} +statement. + +The @code{@@let} statement is introduced by the @code{@@} symbol +followed by the special keyword @code{let}. These tokens are +then followed by a comma-separated list of variable declarators, +enclosed in parentheses. After the parentheses comes a required statement, +The list of variables may be empty. + +The statement is executed in a scope in which the specified variables are +visible, in addition to any other variables that were previously visible that +do not have the same names. When the statement terminates, the variables +specified in that statement disappear. + +Declarators consist of variable names, optionally initialized by expressions. +The initializing expressions are indicated by the @code{=} sign: + +@example +function fun(x) +{ + ... + @let (a, b = 3, ir2 = 0.707) { + ... + } + ... +} +@end example + +Local variables introduced by @code{@@let} may have the same names as global +variables, or, in a function, the parameter names of the enclosing function. +In this situation, over their scope, the @code{@@let} variables are visible, +hiding the same-named parameters or variables. This is called @emph{shadowing}. + +Shadowing also takes place among same-named @code{@@let} variables, +which occurs when a variable name is repeated in the same @code{@@let} +construct, or in two different @code{@@let} constructs which are nested. + +A @code{@@let} variable may not have the same name as the enclosing +function, or the same name as an Awk special variable such as @code{NF}. +A name with a namespace prefix such as @code{awk::score} also may not be used +as a local variable. + +The @code{@@let} construct may be used outside or inside of a function. +The semantics is identical, but the implementation is different. +Inside a function, the construct allocates variables from the local variable +frame of the function invocation. Outside of a function, it allocates +anonymous variables from the global namespace. These hidden variables +can be seen in the output of the @code{-d} option, having numbered names +which look like @code{$let0001}. This is an implementation detail that may +change in the future. + +A local variable that has no initializing expression has the empty numeric +string value, just like a regular Awk variable that has not been assigned: it +compares equal to the empty string as well as to zero. + +In the following example, the function's first reference to @code{accum} is a +reference to the global variable. The second reference is local. + +@example +function fun() +{ + accum = 42 + @let (accum) { + print "fun: accum = ", accum + accum = 43 + } +} + +BEGIN { fun(); print "BEGIN: accum = ", accum } +@end example + +The output is + +@example +fun: accum = +BEGIN: accum = 42 +@end example + +After the @code{@@let} statement inside the function, @code{accum} no longer +appears to have a defined value, even though @code{accum} was just assigned the +value 42. This is because @code{@@let} has introduced a local variable +unrelated to any global variable, and that variable is not initialized. + +The @code{print} statement in the @code{BEGIN} block confirms that the +assigning the value 43 to the local @code{accum} had no effect on the global +@code{accum}. + +The scope of a local variable begins from its point of declaration, just +after the initializing expression, if any. The initializing expression +is evaluated in a scope in which the variable is not yet visible. + +@example +function helper() +{ + print "helper: level =", level +} + +function main() +{ + @let (level = level + 1) { + print "main: level =", level + helper() + } +} + +BEGIN { + level = 0 + main() +} +@end example + +the output is: + +@example +main: level = 1 +helper: level = 0 +@end example + +In this example, the function @code{main} locally shadows the global +variable @code{level}, giving the local @code{level} value which is one greater +than the global @code{level}. + +This local variable is lexically scoped; when @code{main} invokes +@code{helper}, it is evident that @code{helper} is, again, referring to the +global @code{level} variable; the @code{helper} function has no visibility +into the scope of the caller, @code{main}. + +Because a local variable's scope begins immediately after its declaration, +within a single @code{@@let} statement, the initializing expressions of +later variables are evaluated in the scope of earlier variables. Furthermore, +later variables may repeat the names of earlier variables. These later +variables are new variables which shadow the earlier ones. + +The following statement makes sense: + +@example +BEGIN { + @let (x = 0, x = x + 1, x = x + 1, x = x + 1) + print x +} +@end example + +Output: + +@example +3 +@end example + +While the variable initializations may resemble the steps of an +imperative program which assigns four successive values to a single +accumulator, that is not the case; four different variables named +@code{x} are defined here, each one shadowing the preceding one. +The @code{print} statement is then executed in the scope of the +rightmost @code{x}. The initializing expressions @code{x + 1} +have the previous @code{x} still in scope. + @node Pass By Value/Reference @subsubsection Passing Function Arguments by Value Or by Reference |