6.12 Functions

Asymptote functions are treated as variables with a signature (non-function variables have null signatures). Variables with the same name are allowed, so long as they have distinct signatures.

Function arguments are passed by value. To pass an argument by reference, simply enclose it in a structure (see Structures).

Here are some significant features of Asymptote functions:

  1. Variables with signatures (functions) and without signatures (nonfunction variables) are distinct:
    int x, x();
    x=5;
    x=new int() {return 17;};
    x=x();              // calls x() and puts the result, 17, in the scalar x
    
  2. Traditional function definitions are allowed:
    int sqr(int x)
    {
      return x*x;
    }
    sqr=null;           // but the function is still just a variable.
    
  3. Casting can be used to resolve ambiguities:
    int a, a(), b, b(); // Valid: creates four variables.
    a=b;                // Invalid: assignment is ambiguous.
    a=(int) b;          // Valid: resolves ambiguity.
    (int) (a=b);        // Valid: resolves ambiguity.
    (int) a=b;          // Invalid: cast expressions cannot be L-values.
    
    int c();
    c=a;                // Valid: only one possible assignment.
    
  4. Anonymous (so-called "high-order") functions are also allowed:
    typedef int intop(int);
    intop adder(int m)
    {
      return new int(int n) {return m+n;};
    }
    intop addby7=adder(7);
    write(addby7(1));   // Writes 8.
    
  5. One may redefine a function f, even for calls to f in previously declared functions, by assigning another (anonymous or named) function to it. However, if f is overloaded by a new function definition, previous calls will still access the original version of f, as illustrated in this example:
    void f() {
      write("hi");
    }
    
    void g() {
      f();
    }
    
    g(); // writes "hi"
    
    f=new void() {write("bye");};
    
    g(); // writes "bye"
    
    void f() {write("overloaded");};
    
    f(); // writes "overloaded"
    g(); // writes "bye"
    
  6. Anonymous functions can be used to redefine a function variable that has been declared (and implicitly initialized to the null function) but not yet explicitly defined:
    void f(bool b);
    
    void g(bool b) {
      if(b) f(b);
      else write(b);
    }
    
    f=new void(bool b) {
      write(b);
      g(false);
    };
    
    g(true); // Writes true, then writes false.
    

Asymptote is the only language we know of that treats functions as variables, but allows overloading by distinguishing variables based on their signatures.

Functions are allowed to call themselves recursively. As in C++, infinite nested recursion will generate a stack overflow (reported as a segmentation fault, unless a fully working version of the GNU library libsigsegv (e.g. 2.4 or later) is installed at configuration time).