code: public Val apply(Env env, Env.StackHelp stk, AstRoot[] asts) {
      Val[] args = new Val[asts.length];
      args[0] = null;
      for (int i = 1; i < asts.length; i++) {
        args[i] = stk.track(asts[i].exec(env));
      }
      return exec(args);
    }
docs: <p>Primary method to invoke this function, passing all the parameters
  as the `asts` list.</p>
  
  <p>The default implementation of this method executes all Asts within
  the provided environment, and then calls {@link #exec(Val[])} passing it
  the arguments as the list of {@link Val}s. A derived class will then only
  need to override the second `exec()` function which is much simpler.</p>
  
  <p>However for certain functions (such as short-circuit boolean operators)
  executing all arguments is not desirable -- these functions would have to
  override this more general method.</p>
  
  @param env Current execution environment. Variables are looked up here.
  @param stk TODO need clarification
  @param asts List of AstRoot expressions that are arguments to the
  function. First element in this list is the function itself.
  @return value resulting from calling the function with the provided list
  of arguments.