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

Calling Traversable#map from java: impossible? #4389

Closed
scabug opened this issue Mar 25, 2011 · 4 comments
Closed

Calling Traversable#map from java: impossible? #4389

scabug opened this issue Mar 25, 2011 · 4 comments
Assignees

Comments

@scabug
Copy link

scabug commented Mar 25, 2011

Chosen as a sample of the impressive difficulty of calling into scala. I can't make this compile at all. Is there a way to make it work? If there is not, is it due to the signature? If nontrivial things aren't going to work anyway then there's no point in suffering so much for the cause.

import scala.*;
import scala.collection.Traversable;
import scala.collection.Traversable$$;
import scala.collection.generic.CanBuildFrom;

class A { };
class B { };

public class J {
  // The generic signature we are trying to implement:
  //
  // public abstract <B,That> That scala.collection.TraversableLike.map(scala.Function1<A, B>,scala.collection.generic.CanBuildFrom<Repr, B, That>)
  
  public void sum(Traversable<A> x) {
    // 1) This way, or any other deviation from 2), and we get "incompatible types"
    // at the declaration.
    CanBuildFrom<Traversable<A>, B, Traversable<B>> cbf1 = Traversable$$.MODULE$$.<B>canBuildFrom();
    // 2) This way, we get "cannot find symbol" at the call site.
    CanBuildFrom<Traversable<?>, B, Traversable<B>> cbf2 = Traversable$$.MODULE$$.<B>canBuildFrom();
    // A function.
    Function1<A, B> f = new scala.runtime.AbstractFunction1<A, B>() {
      public B apply(A a) {
        return null;
      }
    };
    x.map(f, cbf1);
    x.map(f, cbf2);
    
    // For our 3) and last trick, we try to take the working part from each of those, and
    // cast the cbf to the type it wants.  And it won't even let me cast.
    x.map(f, (CanBuildFrom<Traversable<A>, B, Traversable<B>>)cbf2);

    // Error 1:
    // J.java:12: incompatible types
    // found   : scala.collection.generic.CanBuildFrom<scala.collection.Traversable<?>,B,scala.collection.Traversable<B>>
    // required: scala.collection.generic.CanBuildFrom<scala.collection.Traversable<A>,B,scala.collection.Traversable<B>>
    //     CanBuildFrom<Traversable<A>, B, Traversable<B>> cbf1 = Traversable$$.MODULE$$.<B>canBuildFrom();
    //                                                                                                ^

    // Error 2:
    // J.java:23: cannot find symbol
    // symbol  : method map(scala.Function1<A,B>,scala.collection.generic.CanBuildFrom<scala.collection.Traversable<?>,B,scala.collection.Traversable<B>>)
    // location: interface scala.collection.Traversable<A>
    //     x.map(f, cbf2);
    //      ^
    
    // Error 3:
    // J.java:43: inconvertible types
    // found   : scala.collection.generic.CanBuildFrom<scala.collection.Traversable<?>,B,scala.collection.Traversable<B>>
    // required: scala.collection.generic.CanBuildFrom<scala.collection.Traversable<A>,B,scala.collection.Traversable<B>>
    //     x.map(f, (CanBuildFrom<Traversable<A>, B, Traversable<B>>)cbf2);
    //                                                               ^
    // 3 errors
    // 

    x.map(f, null); // "works"
  }
  
  // Nope, not these either
  //
  // CanBuildFrom<Traversable, B, Traversable<B>> cbf3 = Traversable$$.MODULE$$.<B>canBuildFrom();
  // CanBuildFrom<? super Traversable<A>, B, Traversable<B>> cbf4 = Traversable$$.MODULE$$.<B>canBuildFrom();
  // CanBuildFrom<Object, B, Traversable<B>> cbf5 = Traversable$$.MODULE$$.<B>canBuildFrom();
  // CanBuildFrom<Traversable<?>, B, Traversable> cbf6 = Traversable$$.MODULE$$.<B>canBuildFrom();
  // 
  // You can try explicit parameterization, it won't help.
  //
  // x.<B, Traversable<B>>map(f, cbf2);
}
@scabug
Copy link
Author

scabug commented Mar 25, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4389?orig=1
Reporter: @paulp

@scabug
Copy link
Author

scabug commented Apr 11, 2011

@odersky said:
I played with it until it got too tedious. I think the signatures work fine. What does not work is that the variances of CanBuildFrom cannot be modelled in Java, so types do not match. And it seems Java does not even let me override with a cast. So short answer: You can't call these things from Java because instead of declaration side variance you have only a broken wildcard system.

@scabug scabug closed this as completed May 18, 2011
@scabug
Copy link
Author

scabug commented Dec 11, 2015

dpinol (dani) said:
http://stackoverflow.com/questions/11678756/calling-scala-monads-from-java-map shows 2 solutions.

@scabug
Copy link
Author

scabug commented Dec 14, 2015

@paulp said:
When I opened this ticket, the release version of scala was 2.8, with 2.9.0 a couple months out. Applicability of whatever is on offer at the stackoverflow question is unknown.

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

No branches or pull requests

2 participants