T getFunction(final List<SqlArgument> arguments) {

    // first try to get the candidates without any implicit casting
    Optional<T> candidate = findMatchingCandidate(arguments, false);
    if (candidate.isPresent()) {
      return candidate.get();
    } else if (!supportsImplicitCasts) {
      throw createNoMatchingFunctionException(arguments);
    }

    // if none were found (candidate isn't present) try again with implicit casting
    candidate = findMatchingCandidate(arguments, true);
    if (candidate.isPresent()) {
      return candidate.get();
    }
    throw createNoMatchingFunctionException(arguments);
  }
@Test
  public void shouldChooseSpecificOverVarArgsInMiddle() {
    // Given:
    givenFunctions(
            function(EXPECTED, -1, INT, INT, STRING, STRING, STRING, STRING, INT),
            function(OTHER, 2, INT, INT, STRING_VARARGS, STRING, STRING, STRING, INT)
    );

    // When:
    final KsqlScalarFunction fun = udfIndex.getFunction(ImmutableList.of(
            SqlArgument.of(SqlTypes.INTEGER), SqlArgument.of(SqlTypes.INTEGER),
            SqlArgument.of(SqlTypes.STRING), SqlArgument.of(SqlTypes.STRING),
            SqlArgument.of(SqlTypes.STRING), SqlArgument.of(SqlTypes.STRING),
            SqlArgument.of(SqlTypes.INTEGER)
    ));

    // Then:
    assertThat(fun.name(), equalTo(EXPECTED));
  }