private static Result<IValue> callWith( List<AbstractFunction> candidates, Type[] argTypes, IValue[] argValues, Map<String, IValue> keyArgValues, boolean mustSucceed) { AbstractFunction failed = null; Failure failure = null; for (AbstractFunction candidate : candidates) { if ((candidate.hasVarArgs() && argValues.length >= candidate.getArity() - 1) || candidate.getArity() == argValues.length || candidate.hasKeywordArguments()) { try { return candidate.call(argTypes, argValues, keyArgValues); } catch (MatchFailed m) { // could happen if pattern dispatched } catch (Failure e) { failed = candidate; failure = e; // could happen if function body throws fail } } } if (failed != null && mustSucceed) { throw new UnguardedFail(failed.ast, failure); } return null; }