Java8のLambda用Interfaceの命名規則

[前回](http://qiita.com/irxground/items/983a7d25239eef02bf8f)、Javaの命名規則がよくわからんと言ったので、頑張って探してみた。

プログラマなら、文章読むより、コード見たほうがうれしいよね。

[Ideone](https://ideone.com/)で作業したせいで1ファイルでやってしまった

```rb:java_lambda_name.rb
module JavaLambdaName
  PKG = 'java.util.function.'

  module_function

  # ===== ===== ===== ===== MAIN ===== ===== ===== =====

  def infer(types)
    *params, ret = *types

    return consumer(params)           if ret == 'void'
    return supplier(ret)              if params.size == 0
    return predicate(params)          if ret == 'boolean'
    return operator(ret, params.size) if params.all?{ |x| ret == x }
    return function(ret, params)
  end

  # ===== ===== ===== ===== Lambda Type ===== ===== ===== =====

  def consumer(params)
    if params.size == 0
      return 'java.lang.Runnable', 'run'
    else
      return common_signature(params, 'Consumer', 'accept')
    end
  end
  def supplier(ret)
    return PKG + cap(ret) + 'Supplier', 'get' + cap(ret, 'As')
  end

  def predicate(params)
    return common_signature(params, 'Predicate', 'test')
  end

  def common_signature(params, c, m)
    if params.all?{ |x| generic? x }
      prefix = params.size == 2 ? 'Bi' : ''
    else
      prefix = params.map{|x| generic?(x) ? 'Obj' : x.capitalize }.join
    end
    return PKG + prefix + c, m
  end

  def operator(ret, n)
    rank = n == 1 ? 'Unary' : 'Binary'
    return PKG + cap(ret) + rank + 'Operator', 'applyAs' + cap(ret)
  end

  def function(ret, params)
    from = params.map{ |x| cap x }.join
    rank = params.size == 2 ? 'Bi' : ''

    return PKG + from + cap(ret, 'To') + rank + 'Function', 'apply' + cap(ret, 'As')
  end

  # ===== ===== ===== ===== HELPERS ===== ===== ===== =====

  def generic?(type)
    type.length == 1
  end

  def cap(type, prefix = '')
    if generic? type
      return ''
    else
      return prefix + type.capitalize
    end
  end
end

def test
  ok = []
  ng = []
  
  DATA.each_line do |line|
    line.strip!
    if /\| (?<expr>[^\|]+) \| (?<klass>[^\|]+) \|/ =~ line
      types = expr.split(/\W+/).select{|x| x.size > 0 }
      expect = klass
      actual = JavaLambdaName.infer(types).join(".")
      if expect == actual
        ok << "OK: #{expect}"
      else
        ng << "NG: #{expect} expected, but was #{actual}"
      end
    end
  end
  puts "#{ng.size} data failed."
  ng.each do |line|
    puts "\t" + line
  end
end
test


__END__
| () -> void                 | java.lang.Runnable.run |
| (T, U) -> void             | java.util.function.BiConsumer.accept |
| (T, U) -> R                | java.util.function.BiFunction.apply |
| (T, U) -> boolean          | java.util.function.BiPredicate.test |
| () -> boolean              | java.util.function.BooleanSupplier.getAsBoolean |
| T -> void                  | java.util.function.Consumer.accept |
| (double, double) -> double | java.util.function.DoubleBinaryOperator.applyAsDouble |
| double -> void             | java.util.function.DoubleConsumer.accept |
| double -> R                | java.util.function.DoubleFunction.apply |
| double -> boolean          | java.util.function.DoublePredicate.test |
| () -> double               | java.util.function.DoubleSupplier.getAsDouble |
| double -> int              | java.util.function.DoubleToIntFunction.applyAsInt |
| double -> long             | java.util.function.DoubleToLongFunction.applyAsLong |
| double -> double           | java.util.function.DoubleUnaryOperator.applyAsDouble |
| T -> R                     | java.util.function.Function.apply |
| (int, int) -> int          | java.util.function.IntBinaryOperator.applyAsInt |
| int -> void                | java.util.function.IntConsumer.accept |
| int -> R                   | java.util.function.IntFunction.apply |
| int -> boolean             | java.util.function.IntPredicate.test |
| () -> int                  | java.util.function.IntSupplier.getAsInt |
| int -> double              | java.util.function.IntToDoubleFunction.applyAsDouble |
| int -> long                | java.util.function.IntToLongFunction.applyAsLong |
| int -> int                 | java.util.function.IntUnaryOperator.applyAsInt |
| (long, long) -> long       | java.util.function.LongBinaryOperator.applyAsLong |
| long -> void               | java.util.function.LongConsumer.accept |
| long -> R                  | java.util.function.LongFunction.apply |
| long -> boolean            | java.util.function.LongPredicate.test |
| () -> long                 | java.util.function.LongSupplier.getAsLong |
| long -> double             | java.util.function.LongToDoubleFunction.applyAsDouble |
| long -> int                | java.util.function.LongToIntFunction.applyAsInt |
| long -> long               | java.util.function.LongUnaryOperator.applyAsLong |
| (T, double) -> void        | java.util.function.ObjDoubleConsumer.accept |
| (T, int) -> void           | java.util.function.ObjIntConsumer.accept |
| (T, long) -> void          | java.util.function.ObjLongConsumer.accept |
| T -> boolean               | java.util.function.Predicate.test |
| () -> T                    | java.util.function.Supplier.get |
| (T, U) -> double           | java.util.function.ToDoubleBiFunction.applyAsDouble |
| T -> double                | java.util.function.ToDoubleFunction.applyAsDouble |
| (T, U) -> int              | java.util.function.ToIntBiFunction.applyAsInt |
| T -> int                   | java.util.function.ToIntFunction.applyAsInt |
| (T, U) -> long             | java.util.function.ToLongBiFunction.applyAsLong |
| T -> long                  | java.util.function.ToLongFunction.applyAsLong |
| T -> R                     | java.util.function.Function.apply |
```