Подтвердить что ты не робот

Почему стирание осложняет реализацию типов функций?

Я читал из интервью

EDIT: Другое место, где я встретил подобное выражение, было в сообщении Brian Goetz , где он говорит, что lambdas легче обрабатывать, когда они это просто анонимные классы с синтаксическим сахаром:

Но мое возражение против типов функций было не в том, что мне не нравятся типы функций - я люблю типы функций, но эти типы функций плохо сражались с существующим аспектом системы типа Java, стиранием. Стираемые типы функций являются наихудшими из обоих миров. Поэтому мы удалили это из дизайна.

Может ли кто-нибудь объяснить эти утверждения? Зачем мне нужна информация о времени выполнения с lambdas?

4b9b3361

Ответ 1

То, как я это понимаю, заключается в том, что они решили, что благодаря стиранию было бы грязно идти по пути " типов функций", например. делегаты в С#, и они могут использовать лямбда-выражения, что просто упрощает синтаксис одного абстрактного метода.

Делегаты в С#:

public delegate void DoSomethingDelegate(Object param1, Object param2);
...
//now assign some method to the function type variable (delegate)
DoSomethingDelegate f = DoSomething;
f(new Object(), new Object());

(здесь еще один пример http://geekswithblogs.net/joycsharp/archive/2008/02/15/simple-c-delegate-sample.aspx)

Один аргумент, который они указали в документах Project Lambda:

Стираются общие типы, которые выставляют дополнительные места, где разработчики подвергаются стиранию. Например, это не было бы можно перегрузить методы m (T- > U) и m (X- > Y), что было бы запутанным.

раздел 2 в: http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html

(Окончательный синтаксис лямбда-выражений будет немного отличаться от приведенного выше документа: http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html)

(x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); }

В целом, мое лучшее понимание заключается в том, что только часть синтаксиса, которая может, на самом деле, будет использоваться. То, что Neal Gafter, скорее всего, имело в виду, заключалось в том, что невозможность использования делегатов затруднит адаптацию стандартных API-интерфейсов к функциональному стилю, а не к тому, что обновление javac/JVM будет более сложным.

Если кто-то поймет это лучше меня, я буду рад прочитать его отчет.

Ответ 2

Goetz расширяет рассуждения в Состояние лямбды 4-е изд.:

Альтернативный (или дополнительный) подход к типам функций, предложенные некоторыми ранними предложениями, заключались бы в том, чтобы представить новую, тип структурной функции. Тип типа "функция из строки и Объект int" может быть выражен как (String, Object) → int. идея была рассмотрена и отвергнута, по крайней мере на данный момент, из-за нескольких Недостатки:

  • Это добавит сложности в систему типов и продолжит смешение структурных и номинальных типов.
  • Это приведет к расхождению стилей библиотеки - некоторые библиотеки будут продолжать использовать интерфейсы обратного вызова, в то время как другие будут использовать структурные типы функций.
  • Синтаксис может быть несовместимым, особенно когда отмечены исключения.
  • Маловероятно, что было бы представление во время выполнения для каждого отдельного типа функции, что означает, что разработчики будут и ограничен стиранием. Например, это было бы невозможно (возможно удивительно) к методам перегрузки m (T- > U) и m (X- > Y).

Итак, вместо этого мы выбрали путь "использовать то, что вы знать", поскольку существующие библиотеки широко используют функциональные интерфейсы, мы кодифицируем и используем этот шаблон.

Чтобы проиллюстрировать, вот некоторые из функциональных интерфейсов в Java SE 7 которые хорошо подходят для использования с новыми языковыми особенностями; следующие примеры иллюстрируют использование нескольких из них.

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener
  • ...

Обратите внимание, что стирание является лишь одним из соображений. В общем, лямбда-подход Java идет в другом направлении от Scala, а не только от типизированного вопроса. Это очень Java-ориентированный.

Ответ 3

Возможно, потому, что вы действительно хотели бы быть типом Function<R, P...>, который параметризуется с типом возврата и некоторой последовательностью типов параметров. Но из-за стирания у вас не может быть такой конструкции, как P..., потому что она может превращаться только в Object[], которая слишком свободна, чтобы ее можно было использовать во время выполнения.

Это чистая спекуляция. Я не теоретик типа; я даже не играл по телевизору.

Ответ 4

Я думаю, что он имеет в виду в этом заявлении, что во время выполнения Java не может отличить эти два определения функций:

void doIt(List<String> strings) {...}
void doIt(List<Integer> ints) {...}

Потому что во время компиляции информация о том, какие типы данных содержит список, стирается, поэтому среда выполнения не сможет определить, какую функцию вы хотите вызвать.

Попытка скомпилировать оба этих метода в одном классе вызовет следующее исключение:

doIt(List<String>) clashes with doIt(List<Integer); both methods have the same erasure