0

I am having trouble understanding the use of gawk function arguments. Customarily, arguments define variables that are local to the function.

But can arguments be used as input that the function can use ?

Have seen the use of return which can actually return a value by calling

val=myfunc()

What is the advantage of passing a global value as an input argument to a function, when you can access the global variable nonetheless ?

2
  • 5
    Can you please edit your question and clarify? Perhaps give an example function and explain what you would expect? Also, gawk is a specific implementation of awk, although I doubt it would behave differently in this case, so it is a bit confusing that you use the terms interchangeably.
    – terdon
    Commented Apr 5, 2023 at 21:25
  • 2
    Please get the book Effective AWK Programming, 5th Edition, by Arnold Robbins as it explains this (which you've already asked variations of) and everything else you've been asking about from your many accounts here and on SO (e.g. stackoverflow.com/q/75941917/1745001 and many others)
    – Ed Morton
    Commented Apr 6, 2023 at 14:35

3 Answers 3

4

Your question is based on a false premise.

Customarily, arguments define variables that are local to the function.

No. Customarily, arguments define variable names for values passed in to the function.

awk doesn't have the ability to declare locally scoped variables. But since all function arguments are optional, it's considered acceptable practice to overload the function argument list with variables that have no purpose other than that they can be used locally in the function.

Therefore the answer to your question is "yes": variables can be used to pass in values to a function.

For example,

awk '
    function factorial(n) { return n>1 ? n*factorial(n-1) : 1 }
    BEGIN { print factorial(5) }
'

Here the function calls itself with a different value each time (first 5 and then descending values 4, 3, 2). Trying to use a global variable for this would be exceedingly hard.

16
  • 1
    If awk doesn't have the ability to declare locally scoped variables, why is it that when one does not add the names as arguments, the global values get changed ?
    – Vera
    Commented Apr 6, 2023 at 0:39
  • 1
    @Heime, anyway, I'm not exactly sure what it is you're asking there? Are you asking if there's a point in passing arguments to functions instead of just using global variables always, everywhere? What if the programmer wants the function to use variable A at one point, and variable B at another...? It might help if you could edit your question to demonstrate what you mean.
    – ilkkachu
    Commented Apr 6, 2023 at 4:47
  • 1
    @Heime As noted in my previous answer: (a) Awk can declare locally scoped variables as excess arguments. If you do not declare their names like that, they are assumed to be global. (b) Array arguments can be written into by their function -- they are passed by reference. This is all in GNU Awk Users Guide 9.2.3.2. Commented Apr 6, 2023 at 7:39
  • 1
    Global variables or an array, @Heime. awk 'function sa(a, b, x) { x[1] = a+b; x[2] = x[1]/2 } BEGIN { sa(2, 3, r); print r[1], r[2] }' Commented Apr 7, 2023 at 21:39
  • 1
    @Heime, an array name as a function argument (x in my example) is local to the function. If you have a global x array it remains untouched by operations performed on the local array named x - operations on this local x only affect the array r passed in to the function Commented Apr 7, 2023 at 22:23
3

Note also that scalar arguments to a function are passed by value, but array arguments are passed by reference. Thus, the function can change array values declared in the calling code to that function, and so return multiple values.

That includes the ability to create new elements in an array argument, even if it was initially passed in as an empty array.

Suppose I want a function that takes two numbers, and want to output two variable values, one containing the sum, the other containing the average. What can one do?

One can do this: it demonstrates that global and local scopes exist for arrays of the same name, that they can be of different lengths and contain different data, and that an array is passed by reference and can return multiple values.

#! /bin/bash

Awk='
#.. Define and fill an array X at global scope.
BEGIN { X[1] = 45; X[2] = 98; }
#.. Function that fills in a result array (passed by reference).
function Math (X, v1, v2) {
    X[1] = v1 + v2; X[2] = (v1 + v2) / 2; X[3] = v1 * v2;
}
#.. Function that declares an array X at local scope, and reports it.
function Wrapper (a, b,      X, j) {
    Math( X, a, b);
    for (j = 1; j in X; ++j) printf ("Local X[%d] is %f\n", j, X[j]);
}
{ 
    Wrapper( $1, $2);
    #.. Prove that the Global X is unaffected, in length or content.
    for (j = 1; j in X; ++j) printf ("Global X[%d] is %f\n", j, X[j]);
}
'   
    echo 3.5 2.7 | awk "${Awk}"
$ ./Heime.awk
Local X[1] is 6.200000
Local X[2] is 3.100000
Local X[3] is 9.450000
Global X[1] is 45.000000
Global X[2] is 98.000000 

GNU Awk runs this just fine -- it decides the type of X when it is first accessed. nawk (Solaris Awk) seems to make that decision when it is passed in (and may SegViol as a result).

To ensure nawk passes X into the function by reference, you may need to explicitly create it as a zero-length array before passing it in, by splitting a zero-length string using a zero-length pattern:

    split ("", X, ""); Math( X, a, b);
6
  • Why would one declare array arguments if they are global. There would be no need. It started some confusion for me.
    – Vera
    Commented Apr 6, 2023 at 0:30
  • @Heime If you wite a function to print the elements of an array in a certain way, where the array is passed to the function, that function could be used to print any array. If you used a global array in the function, only that array would be able to be printed.
    – Kusalananda
    Commented Apr 6, 2023 at 5:14
  • 1
    @Heime The distinction is not as distinct as global or local. Because awk functions can call other functions to any (reasonable) depth, I can create and populate a local array in an intermediate level function, and pass that array to one or more utility functions as an argument. It is generally considered good practice to avoid creating global variables as much as possible. Commented Apr 6, 2023 at 7:23
  • 3
    Regarding "Why would one declare array arguments if they are global. There would be no need." - to write your code using the fundamentals of all software development: encapsulation, tight cohesion, and loose coupling.
    – Ed Morton
    Commented Apr 6, 2023 at 14:21
  • If I avoid using any global variables in a function called this_func, is return var and arrays the only ways to pass updated arguments in this_func to be used for that_func ? E.g. that_func() { r=0 ; s=0 ; this_func(r,s) ; print r s }
    – Vera
    Commented Apr 8, 2023 at 5:24
1

What is the advantage of passing a global value as an input argument to a function, when you can access the global variable nonetheless ?

Same as with any function in any programming language: you can pass a different (global) variable each time, and the function doesn't need to know about things it doesn't need for doing it's job.

As a trivial example:

function sum(a,b) { return a+b; }

{ partial = sum($2, $3); }
$1 == 0 { print sum(partial, $4); }
$1 != 0 { print sum(partial, $5); }

Imagine a more involved function there in place of sum(), so that duplicating it in both branches would no longer make sense.

8
  • Fantastic explanation that helps explain the necessity of function arguments in awk.. In the example one can pass any variable, whether global or not. The function then becomes a sort of generic function seen in programming languages. Although experienced with programming languages, I was hesitant about the peculiarities of awk function programming.
    – Vera
    Commented Apr 6, 2023 at 19:04
  • 1
    @Heime, umh, "The function then becomes a sort of generic function seen in programming languages"... well, I wonder, what did you expect, then? And isn't AWK a programming language itself?
    – ilkkachu
    Commented Apr 6, 2023 at 20:28
  • I find the awk syntax for local variable definition quite appalling.
    – Vera
    Commented Apr 7, 2023 at 21:03
  • @Heime The (empty) syntax grows on you -- there are other examples to be appalled by. The conventional way to differentiate local variables is to leave a gap between the args and the locals. However, I prefer to show them like myFunc (a, b, Local, c, d, e) { .... Note that Local is not an awk keyword, it is merely the name of the first (unused) local variable (and itself has local scope, so it can safely be used in every function). Commented Apr 7, 2023 at 23:33
  • I know that I can pass values a and b to myFunc. But I certainly cannot change them. Thus r=3 ; s=5 ; myFunc(r,s) ; print r s will keep r and s with values 3 and 5 respectively, even though the values are changed inside myFunc. Although they look like arguments, their values cannot be changed by the function so that their updated values can be used elsewhere. I would like to have a function that compute some complicated values from some input data, so I can use the computed values in the body of my awk script. Something that is creating me a lot of problems.
    – Vera
    Commented Apr 8, 2023 at 4:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .