Плавный способ использования Java-интерфейса Function <A, R> из scala? - PullRequest
5 голосов
/ 20 сентября 2011

Здесь на работе большинство людей используют Java, а я работаю со Scala.Мы решили собрать некоторые общие классы в библиотеке, которые будут написаны на Java.Теперь я хочу добавить псевдо-функциональное программирование в библиотеку, взгляните на следующее:

java:

public interface Func<A, R> {
    public R f(a A);
}

public AClass {
    public <R> ArrayList<R> myMethod(
                             Func<String, R> func
    ) {
        // ...
    }
}

использование в java:

AClass ac = new AClass();
ArrayList<String> al = ac.myMethod(
                            new Func<String, String> (
                                public String f(String s) {
                                    return s + "!";
                                }
                            })

Вышесказанное не совсем удачно (на самом деле больше похоже на устрашающий взгляд с точки зрения скалы).Есть ли способ вызвать магию скалы, чтобы можно было сделать что-то вроде следующего в scala:

var ac = new ACLass
var al = ac.myMethod(str => str + "!")             // alternative 1
al = ac.myMethod { case: str:String => str + "!" } // alternative 2

Я какое-то время баловался со следствиями, но не мог разобраться с вещами = P.

Ответы [ 3 ]

14 голосов
/ 20 сентября 2011

С неявными преобразованиями:

object FuncConversions {
  implicit def func2function[A,R]( fn: (A) => R ) =
    new Func[A,R] {
      def f(a: A) = fn(a)
    }
}

Не забудьте импортировать преобразование в своей области видимости:

import FuncConversions._

Вы также можете реализовать обратное преобразование.

6 голосов
/ 20 сентября 2011

Расширить парадигматический ответ.Вот как вы постигаете неявное.Неявные преобразования вступают в игру, когда типы не проверяются.Когда это происходит, компилятор будет искать неявное преобразование для использования, чтобы типы соответствовали.

После небольшой очистки вашего примера в REPL компилятор покажет:

scala> ac.myMethod((s:String) => s + "!")
<console>:9: error: type mismatch;
 found   : String => java.lang.String
 required: Func[java.lang.String,?]
              ac.myMethod((s:String) => s + "!")

Таким образом, компилятор сообщит вам, что нашел (String) => (String), но ему нужно Func[String, ?].Поэтому вы хотите обеспечить неявное преобразование между типом found и типом required .Таким образом, подпись должна выглядеть примерно так:

implicit def fun2Func(fun: (String) => String): Func[String,String]

Затем следующим шагом будет осознание того, что неявное преобразование может быть обобщено с типами A и R.

Интересно, что касается идентификатораесли бы вам было лучше, если бы вы снова использовали что-то с полки, например http://code.google.com/p/guava-libraries/.

3 голосов
/ 20 сентября 2011

Я не знаю точно, но, возможно, функциональная Java http://functionaljava.org/ может помочь вам и вашим коллегам.Какие именно функции вы пытаетесь собрать в своей библиотеке 'pseudo-fp'?

...