aboutsummaryrefslogtreecommitdiffstats
path: root/doc/gawktexi.in
diff options
context:
space:
mode:
Diffstat (limited to 'doc/gawktexi.in')
-rw-r--r--doc/gawktexi.in185
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