Интересно, каковы технические различия между C # и Scala в реализации и как оба решения сравниваются с идеями и проблемами реализации, озвученными в электронном письме Peek Past lambda Брайана Гетца, отправленном в список рассылки Project Lambda (JSR 335) ?
Из электронной почты:
Мы исследовали путь «возможно, лямбды должны быть просто экземплярами внутреннего класса, это было бы действительно просто», но в итоге пришли к позиции «функции - лучшее направление для будущего языка».
и далее:
Взгляд мира на лямбды-объекты противоречит этому возможному будущему. Лямбда-это-функция видения мира не делает, и сохранение этой гибкости является одним из пунктов в пользу того, чтобы не отягощать лямбды даже появлением объектности.
Вывод:
Lambdas-are-functions открывает двери. Lambdas-are-объекты закрывают их.
Мы предпочитаем, чтобы эти двери оставались открытыми.
И некоторый комментарий от человека в ветке Reddit говорит:
На самом деле я написал по электронной почте Нилу Гафтеру об этом и, насколько я понимаю, его объяснение C # и нынешний дизайн Java очень похожи в том, что делегаты на самом деле являются объектами, а не типами функций. Похоже, он считает, что Java должна учиться на недостатках лямбд в C # и избегать их (так же, как C # учился на недостатках Java и избегал их в начале).
Почему подход «Лямбда-ан-функции» дает больше возможностей в будущем, чем «Лямбда-ан-объекты»? Может кто-нибудь объяснить, какие существуют различия и как они повлияют на то, как будет написан код?
Видя, что вещи в Scala «просто работают», я продолжаю думать, что мне что-то не хватает в подходах, предложенных / предложенных в C # / Java (8), возможно, это связано с проблемами обратной совместимости?
Ответы:
Я думаю, что обсуждение объектов и функций - это красная сельдь. Если вопрос: «Является ли лямбда-функция или объект?» ответ должен быть да .
В этом смысл первоклассных функций: они не обрабатываются иначе, чем любой другой тип. Java уже успевает в основном игнорировать различия между типами Object и примитивами (а Scala работает даже лучше), поэтому, является ли лямбда подклассом Object или новым примитивным типом, или что-то еще не очень важно для языка. Важно то, что вы можете помещать свои лямбды в коллекции, передавать их для вызова, вызывать их и делать все, что вам захочется, с помощью объекта или метода.
Scala выполняет это с помощью объекта-обертки, у
apply
которого есть вызываемый метод, который можно вызывать просто()
, что делает его похожим на вызов метода. Это прекрасно работает; Большую часть времени вам даже не нужно заботиться о том, есть ли у вас метод или вы вызываете метод применения функционального объекта.источник
Из того, что я понимаю, это больше о том, как лямбды рассматриваются на уровне основного языка. Как говорится в электронном письме,
Я думаю, что это довольно хорошо подводит итог вашего вопроса. Если вы объявляете, что «лямбды - это объекты», то это просто объекты определенного класса, и вы застряли с этим. С другой стороны, если вы объявляете «лямбды-функции», то семантически у вас гораздо более богатое игровое поле. Java 1.7 может скомпилировать их в объекты, так что на этом этапе они практически идентичны.
Но Java 1.8 или 1.9 могут вносить изменения в язык (такие как усовершенствованные структурные типы), чем позволить использовать функции гораздо более гибкими способами. Если бы «лямбды были объектами», эти изменения не были бы обратно совместимыми, и вам пришлось бы вводить новую концепцию, чтобы не нарушать существующий код людей. Но если бы
javac
просто тихо конвертировать лямбды в объекты за кулисами, новыеjavac
могут преобразовывать их во что угодно, пока семантика все еще держится.источник
foreach
,map
,filter
в коллекцию.В основном, он просто не хочет что-то делать слишком рано. Я не вижу никакой причины, кроме той, которую он представил, но это действительно очень веская причина.
Рассмотрим эти методы в Scala
Regex
:Было бы проще, если бы они были просто так:
К сожалению, это невозможно, потому что эти две функции идентичны при стирании. Но, хорошо, эти функции делают несколько разные вещи, поэтому другое имя может быть достаточно справедливым.
Тем не менее, a
Match
- это что-то очень полезное, но в большинстве случаев вам нужен либо соответствующий,String
либо список подгрупп. Мы хотели бы иметь это:Невозможно из-за стирания. Я выбрал этот конкретный пример, потому что был непосредственно связан с ним, но я видел по крайней мере полдюжины вопросов о переполнении стека, где люди спрашивают, почему перегрузка недопустима, вызванная именно этой проблемой.
Кроме того, учтите, что сопоставление с образцом в Scala и Java
instanceof
фактически бесполезны из-за стирания.Я думаю, что было бы справедливо отложить типы функций, пока эта проблема не будет решена. В конце концов, в JVM есть много языков, и Java не является быстро развивающимся языком.
источник