proc-to-interface dispatch method collision using Java 8 streams #3475

Closed
cshupp1 opened this Issue Nov 20, 2015 · 2 comments

Comments

Projects
None yet
2 participants
@cshupp1

cshupp1 commented Nov 20, 2015

The following java code:

public static void main (String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
    List<Integer> twoEvenSquares =
        numbers.stream()
               .filter(n -> {
                        System.out.println("filtering " + n);
                        return n % 2 == 0;
                      })
               .map(n -> {
                        System.out.println("mapping " + n);
                        return n * n;
                      })
               .limit(2)
               .collect(() -> new ArrayList<>(),
                           (c, e) -> c.add(e),
                           (c1, c2) -> c1.addAll(c2));
    System.out.println("Output: " + twoEvenSquares);
  }

yields:

filtering 1
filtering 2
mapping 2
filtering 3
filtering 4
mapping 4
Output: [4, 16]

The ostensibly equivalent JRuby code:

numbers = java.util.Arrays.asList(1,2,3,4,5,6,7,8)

filter_lamb = ->(n) {
  puts "filtering #{n}"
  n % 2 == 0
}
map_lamb = ->(n) {
  puts "mapping #{n}"
  n*n
}
l1 = -> { java.util.ArrayList.new }
l2 = -> (c,e) { c.add(e) }
l3 = -> (c1,c2) { c1.addAll(c2)}

two_even_squares =
numbers.stream().filter(filter_lamb).map(map_lamb).limit(2).collect(l1,l2,l3)

bombs out with:

ArgumentError: wrong number of arguments (1 for 2)

in the collect call.

Inspection in irb shows my method:

two_even_squares.java_class.java_instance_methods.map(&:to_s).reject do
|e| e !~ /.*collect.*/ end
=> ["public final java.lang.Object
java.util.stream.ReferencePipeline.collect(java.util.stream.Collector)",
"public final java.lang.Object
java.util.stream.ReferencePipeline.collect(java.util.function.Supplier,java.util.function.BiConsumer,java.util.function.Bi
Consumer)"]

Getting explicit doesn't help:

irb(main):024:0>  two_even_squares.java_send :collect,
[java.util.function.Supplier,java.util.function.BiConsumer,java.util.function.BiConsumer],
l1, l2, l3
ArgumentError: wrong number of arguments (1 for 2)
        from org/jruby/java/proxies/JavaProxy.java:352:in `java_send'
        from (irb):24:in `<eval>'
        from org/jruby/RubyKernel.java:978:in `eval'
        from org/jruby/RubyKernel.java:1291:in `loop'
        from org/jruby/RubyKernel.java:1098:in `catch'
        from org/jruby/RubyKernel.java:1098:in `catch'
        from C:/languages/jruby/jruby-9.0.4.0/bin/jirb:13:in `<top>'
@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Nov 21, 2015

Member

hitting conflicts with proc-impl method dispatch using method_missing, this one in particular is due to Predicate#test ending up as Kernel#test - simplified failing test-case would be e.g. :

numbers = java.util.Arrays.asList 1, 2, 3
numbers.stream.filter { |e| puts "filter : #{e.inspect}"; e > 0 }.mapToInt { |e| e }.sum
ArgumentError: wrong number of arguments (1 for 2)
    from org/jruby/gen/InterfaceImpl1011617339.gen:13:in `test'
    from (irb):6:in `evaluate'
    from org/jruby/RubyKernel.java:1079:in `eval'
    from org/jruby/RubyKernel.java:1479:in `loop'
    from org/jruby/RubyKernel.java:1242:in `catch'
    from org/jruby/RubyKernel.java:1242:in `catch'
    from /opt/local/rvm/rubies/jruby-1.7.22/bin/jirb:13:in `(root)'

... hooking up methods to be implemented directly should be considered

NOTE: have been dealing with a similar issue where Runnable#run did collide with test-unit 2 being present as it adds a run method (which has just changed lately on 3.1).

Member

kares commented Nov 21, 2015

hitting conflicts with proc-impl method dispatch using method_missing, this one in particular is due to Predicate#test ending up as Kernel#test - simplified failing test-case would be e.g. :

numbers = java.util.Arrays.asList 1, 2, 3
numbers.stream.filter { |e| puts "filter : #{e.inspect}"; e > 0 }.mapToInt { |e| e }.sum
ArgumentError: wrong number of arguments (1 for 2)
    from org/jruby/gen/InterfaceImpl1011617339.gen:13:in `test'
    from (irb):6:in `evaluate'
    from org/jruby/RubyKernel.java:1079:in `eval'
    from org/jruby/RubyKernel.java:1479:in `loop'
    from org/jruby/RubyKernel.java:1242:in `catch'
    from org/jruby/RubyKernel.java:1242:in `catch'
    from /opt/local/rvm/rubies/jruby-1.7.22/bin/jirb:13:in `(root)'

... hooking up methods to be implemented directly should be considered

NOTE: have been dealing with a similar issue where Runnable#run did collide with test-unit 2 being present as it adds a run method (which has just changed lately on 3.1).

@kares kares changed the title from JRuby doesn't play nice with the new stream api to proc-to-interface dispatch method collision using Java 8 streams Nov 21, 2015

kares added a commit to kares/jruby that referenced this issue Apr 18, 2016

[ji] at last - deal with Ruby - Java method conflicts with interface …
…impl using a block

we're now add an internal "impl" method for each prescribed abstract interface method

this is expected to resolve conflicting issues (e.g using Java 8 streams) such as #3475

kares added a commit to kares/jruby that referenced this issue Apr 18, 2016

[ji] at last - deal with Ruby - Java method conflicts with interface …
…impl using a block

we're now add an internal "impl" method for each prescribed abstract interface method

this is expected to resolve conflicting issues (e.g using Java 8 streams) such as #3475

@kares kares added this to the JRuby 9.1.0.0 milestone Apr 19, 2016

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Apr 19, 2016

Member

// cc @Lan5432 if you're interested in understanding the internals - there's a PR that resolves this issue and some more problems under Java 8 with interfaces. (<= 9.0.5 failing) specs are provided part of the PR.

Member

kares commented Apr 19, 2016

// cc @Lan5432 if you're interested in understanding the internals - there's a PR that resolves this issue and some more problems under Java 8 with interfaces. (<= 9.0.5 failing) specs are provided part of the PR.

@kares kares closed this in #3809 Apr 27, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment