@Override
  public SEXP apply(Context context, Environment rho, FunctionCall call, PairList args) {

    PairList matchedArguments = ClosureDispatcher.matchArguments(formals, args);

    SEXP exprArgument = matchedArguments.findByTag(EXPR_ARGUMENT);
    SEXP envArgument = matchedArguments.findByTag(ENV_ARGUMENT);

    // Substitute handles ... in an idiosyncratic way:
    // Only the first argument is used, and there is no attempt to
    // match subsequent arguments against the 'env' argument.
    SEXP expr;
    if (exprArgument == Symbols.ELLIPSES) {

      SEXP ellipses = rho.getVariable(Symbols.ELLIPSES);
      if (ellipses == Null.INSTANCE) {
        expr = Null.INSTANCE;
      } else {
        PromisePairList.Node promisePairList = (PromisePairList.Node) ellipses;
        Promise promisedArg = (Promise) promisePairList.getValue();
        expr = promisedArg.getExpression();
      }
    } else {
      expr = exprArgument;
    }

    return substitute(expr, buildContext(context, rho, envArgument));
  }