9.2.5 Functions and Their Effects on Variable Typing

It’s a desert topping!
It’s a floor wax!

Saturday Night Live (back when it used to be funny)

awk is a very fluid language. It is possible that awk can’t tell if an identifier represents a scalar variable or an array until runtime. Here is an annotated sample program:

function foo(a)
{
    a[1] = 1   # parameter is an array
}

BEGIN {
    b = 1
    foo(b)  # invalid: fatal type mismatch

    foo(x)  # x uninitialized, becomes an array dynamically
    x = 1   # now not allowed, runtime error
}

In this example, the first call to foo() generates a fatal error, so awk will not report the second error. If you comment out that call, though, then awk does report the second error.

Here is a more extreme example:

BEGIN {
    funky(a)
    if (A == 0)
        print "<" a ">"
    else
        print a[1]
}

function funky(arr)
{
    if (A == 0)
        arr = 1
    else
        arr[1] = 1
}

Here, the function uses its parameter differently depending upon the value of the global variable A. If A is zero, the parameter arr is treated as a scalar. Otherwise it’s treated as an array.

There are two ways this program might behave. awk could notice that in the main program, a is subscripted, and so mark it as an array before the program even begins to run. BWK awk, mawk, and possibly others do this:

$ nawk -v A=0 -f funky.awk
error→ nawk: can't assign to a; it's an array name.
error→  source line number 11
$ nawk -v A=1 -f funky.awk
-| 1

Or awk could wait until runtime to set the type of a. In this case, since a was never used before being passed to the function, how the function uses it forces the type to be resolved to either scalar or array. gawk and the MKS awk do this:

$ gawk -v A=0 -f funky.awk
-| <>
$ gawk -v A=1 -f funky.awk 
-| 1

POSIX does not specify the correct behavior, so be aware that different implementations work differently.