#### 1.2.2 Defining Procedures ¶

Any Yorick function may be invoked as a procedure; the return value is simply discarded. Calling `damped_wave` as a procedure would be pointless, since it has no side effects. The converse case is a function to be called only for its side effects. Such a function need not have an explicit `return` statement:

    func q_out(Q, file_name)
    {
      file = create(file_name);
      write, file, "Q = "+pr1(Q);
      write, file, "   theta       amplitude";
      write, file, theta, damped_wave(theta,Q);
    }

The `pr1` function (for “print one value”) returns a string representation of its numeric argument, and the `+` operator between two strings concatenates them.

You would invoke `q_out` with the line:

    q_out, 3, "q.out"

Besides lacking an explicit `return` statement, the `q_out` function has two other peculiarities worth mentioning:

First, the variable `theta` is never defined. But neither are the functions `create` and `write`. Any symbol not defined within a function is external to the function. As already noted, parameters and variables defined within the function are local to the function. Here, `theta` is the 200 element array of phase angles defined before q_out was called. You can change theta (both its dimensions and its values) before the next call to `q_out`; that is, an external reference may change between calls to a function that uses it.

Second, `file` is never explicitly closed. When a function returns, its local variables (such as `file`) disappear; when a file object disappears, the associated file automatically closes.