Які переваги та недоліки у підходах C #, Java та Scala до закриттів / Lambdas /…?


30

Цікаво, чим відрізняються технічна реалізація між C # та Scala і як обидва рішення порівнюються з ідеями та проблемами впровадження, озвученими в електронному листі лямбда Peek Past від Брайана Геца, надісланого до списку розсилки Project Lambda (JSR 335) ?

З електронного листа:

Ми дослідили дорогу "можливо, лямбдаси повинні бути просто екземплярами внутрішнього класу, це було б дійсно просто", але врешті-решт прийшли до положення "функції є кращим напрямом для майбутнього мови".

і далі:

Погляд лямбда-об'єктів на світ суперечить цьому можливому майбутньому. Погляд на світ лямбда-є-функцій не відповідає, а збереження цієї гнучкості є одним із моментів на користь того, щоб не обтяжувати лямбдів рівним виглядом об'єктності.

Висновок:

Lambdas-are-function відкриває двері. Лямбда-це-об'єкти їх закриває.
Ми вважаємо за краще бачити ті двері відчиненими.

І деякі коментарі від людини щодо теми Reddit говорять:

Я насправді надіслав електронною поштою Нілу Гафтеру з цього приводу і на моє обмежене розуміння його пояснень C # та поточного дизайну Java досить схожий тим, що Делегати - це фактично об'єкти, а не типи функцій. Схоже, він вважає, що Java повинна вчитися на недоліках лямбдів C # і уникати їх (подібно до того, як C # дізнався з недоліків Java і уникав їх на початку).

Чому підхід "Лямбда-функції-функції" надає більше можливостей у майбутньому, ніж "Лямбда-це-об'єкти"? Чи може хтось пояснити, які існують відмінності та як вони впливатимуть на те, як буде написаний код?

Бачачи, що в Scala речі "просто працюють", я продовжую думати, що мені щось не вистачає щодо підходів, запропонованих / запропонованих у C # / Java (8), ймовірно, це пов'язано з проблемами щодо зворотної сумісності?


1
Це цікаво. Зважаючи на те, що система типу Javas не має поняття функцій на даний момент, це означає, що потрібно було запровадити це першим. Можливо, мова стане занадто складною з цим.
Інго

Чи не мають функції екземпляри якогось інтерфейсу? Що в них такого особливого?
soc

Lisp / Scheme / Clojure може моделювати об'єкти, тоді як Java / C # не може моделювати довільне вкладання функцій. Однак, схоже, у Python є найкраще з обох світів.
Робота

Відповіді:


15

Я думаю, що дискусія щодо об'єктів проти функцій - це червона оселедець. Якщо питання: "Чи лямбда - це функція чи об'єкт?" відповідь має бути так .

У цьому суть першокласних функцій: вони не трактуються інакше, ніж будь-який інший тип. Java вже встигає ігнорувати відмінності між об'єктними та примітивними типами (а Scala робить ще краще), тож чи лямбда є підкласом Object, чи це новий примітивний тип чи щось інше, не дуже важливо для мови. Важливо те, що ви можете розміщувати ваші лямбдахи в колекціях, передавати їх навколо, щоб їх називати, називати їх та робити все, що ви хочете зробити з об'єктом чи методом.

Scala виконує це за допомогою об'єкта обгортки, який має метод, applyякий називається, до якого можна викликати справедливі (), роблячи це схожим на виклик методу. Це чудово працює; більшу частину часу вам навіть не потрібно дбати про те, чи є у вас метод чи викликуєте застосування об’єкта функції.


9

З того, що я розумію, мова йде більше про те, як лямбди розглядаються на рівні первинної мови. Як зазначено в електронному листі,

Ви можете подумати, що поточний дизайн щільно прив’язаний до об'єктної коробки для лямбда - типів SAM - що робить їх ефективними об'єктами в будь-якому випадку. Але це було ретельно приховано від поверхні поверхні, щоб ми могли в майбутньому розглянути «голі» лямбдати, або розглянути інші контексти перетворення для лямбда, або більш інтегрувати лямбда в контрольні конструкції. Ми цього не робимо, і у нас навіть немає конкретного плану для цього, але можливість, можливо, робити це в майбутньому є важливою частиною проекту.

Я думаю, що це підсумовує ваше запитання досить добре. Якщо ви заявляєте, що "лямбда - це об'єкти", то вони просто об'єкт певного класу, і ви до цього застрягли. З іншого боку, якщо ви заявляєте, що "лямбда - це функції", то семантично ви маєте набагато багатше ігрове поле. Java 1.7 може компілювати їх до об'єктів, тому вони практично однакові на той момент.

Але Java 1.8 або 1.9 може внести зміни в мову (наприклад, модифіковані структурні типи), ніж надати можливість використовувати функції набагато гнучкішими способами. Якби "лямбда були об'єктами", ці зміни не були б сумісними назад, і вам доведеться запровадити нову концепцію альтертер, щоб не порушити існуючий код людей. Але якщо javacпросто тихо перетворювали лямбда в предмети за кадром, то нове javacможе перетворити їх у все, що завгодно, доти, доки семантика все ще дотримується.


lamdas в C #! = від делегатів. У компіляторі є можливість компілювати їх або до делегатів, або до дерев Expression. обидва дійсно об'єкт графіка , але вони не компілюється в «певний клас» , ні навіть клас конкретного спадкового дерева
Rune FS

Якщо я правильно розумію, то компілюючи лямбда вниз до внутрішнього класу об'єкта, пов'язаного з його зв'язком, з цим об'єктом, тож у майбутньому, якщо Java вводить функції вищого порядку (функції на одному рівні об'єктів), то ви не вдалося використати внутрішню класну реалізацію, і була б невідповідність. Я не думаю, що у Java незабаром з’являться функції вищого порядку.
mwolfetech

@mwolfetech: Наскільки я знаю, вони вже заплановані для Java 8 із захисними методами. Вони хочуть додати такі речі, як foreach, наприклад map, filterдо колекцій.
soc

@soc Добре, що важко йти в ногу з кількістю JSR та чи дійсно вони будуть завершені та складе цільову версію JDK. Схоже, методи захисників можуть бути частиною того ж СП. Що стосується цього СП , я вважаю, що стан Брайана Геца з посади Ламбда є корисним - пояснює типи SAM та сучасні думки щодо впровадження лямбдаських виразів.
mwolfetech

"Поточні думки" mhhh, чи не є ця посада з 2010 року застарілою?
soc

5

Здебільшого, він просто не хоче занадто рано щось робити. Я не бачу жодної причини поза стиранням, яку він представив, але це справді дуже вагома причина.

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

Розглянемо ці методи у Скалі Regex:

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

Було б простіше, якби вони були просто такими:

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

На жаль, це неможливо, оскільки ці дві функції однакові під час стирання. Але, чудово, ці функції роблять дещо різні речі, тому інша назва може бути досить справедливою.

Однак, a Match- це щось дуже корисне, але більшу частину часу ви хочете або відповідати, Stringабо списку підгруп. Ми хотіли б мати це:

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

Неможливо через стирання. Я вибрав саме цей приклад, тому що я безпосередньо брав участь у ньому, але я побачив щонайменше півдесятка питань щодо переповнення стека, де люди запитують, чому перевантаження незаконне, викликане саме цією проблемою.

А потім врахуйте, що відповідність шаблонів Scala та Java instanceofфактично марні через стирання.

Я думаю, що справедливо затягувати типи функцій, поки не буде вирішено це питання. Зрештою, на JVM є багато мов, і це не так, як Java - це швидко розвивається мова.


Ну а якщо стирання типу є єдиною проблемою, що вони планують робити? Порушення кожного коду на цій планеті вже було невизначено для Java 5 ...
soc

@soc Я так рада, що я не в їхньому взутті! Але це було Сонце, це Оракул. Oracle ніколи не мав жодних спільних зусиль у здійсненні кардинальних змін між основними (і навіть незначними) версіями свого основного продукту.
Даніель К. Собрал

Можливо, вони повинні змінити назву мови і почати розробляти нову мову, відмовляючись від відсталої сумісності. Таким чином, можна було б мати переваги нової мови без необхідності грати зі старшою та усталеною мовою. Зрештою, це зробили Скала і Клуджуре.
Джорджо

@Giorgio Це було б трохи безглуздо. Ну, деякі з людей, які відповідають за те, що Java сьогодні, зробили це, але, як ви сказали, є альтернативи. Але люди, відповідальні за Яву, повинні вдосконалити саму Яву - вони за це відповідають . Єдина альтернатива - просто відмовитися від Java та відмовитися від усіх переваг, що виникають внаслідок її контролю.
Даніель К. Собрал

@Daniel C. Sobral: мова програмування IMO трохи схожа на програмне забезпечення: на початку він може бути чистим і добре продуманим, але чим більше ви граєте з ним, тим більше стає брудно. Тому я думаю, що розробникам було б цікаво заморозити Java як мову і сконцентрувати розвиток на (1) створенні нових бібліотек або вдосконаленні існуючих, (2) вдосконаленні JVM (якщо можливо), (3) розробці нових мов . Але, як ви сказали, є люди, які відповідають за Java і хочуть продовжувати продавати оновлення. Тож вони збираються продовжити його, щоб зберегти його «круто». Всього мої 2 копійки.
Джорджіо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.