Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
cshupp1 opened this issue Nov 20, 2015 · 2 comments · Fixed by #3809
Closed

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

cshupp1 opened this issue Nov 20, 2015 · 2 comments · Fixed by #3809

Comments

@cshupp1
Copy link

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
Copy link
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 JRuby doesn't play nice with the new stream api 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
…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 jruby#3475
kares added a commit to kares/jruby that referenced this issue Apr 18, 2016
…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 jruby#3475
@kares kares added this to the JRuby 9.1.0.0 milestone Apr 19, 2016
@kares
Copy link
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.

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

Successfully merging a pull request may close this issue.

2 participants