Лямбда-вирази java 8

Лямбда-вирази java 8

Якщо коротко - звичайно так.

Щоб дати більш розгорнуту відповідь, давайте все-таки розберемося: а навіщо ми з ними працюємо?

По суті, лямбда-вирази потрібні тому, що вони описують, які обчислення повинні бути виконані, а не як їх виконувати. Традиційно ми працювали з зовнішньої итерацией, при якій чітко вказували всю послідовність операцій, а також як вони робляться.

Зовнішня ітерація виконується в циклі for. причому цей цикл в точності вказує, як вона робиться. Такий код надлишковий і неодноразово відтворюється в програмах. Однак з циклом forEach ми наказуємо програмі викликати speak (тут - за допомогою посилання на метод, яка більш лаконічна, ніж лямбда) для кожного елемента, але нам не доводиться описувати, як працює цикл. Ітерація обробляється внутрішньосистемних, на рівні циклу forEach.

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

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

У чисто функціональному мовою програмування є і інші обмеження, зокрема - інваріантність даних. Тобто, у вас немає змінних, тільки незмінні значення. На перший погляд це обмеження здається надмірним (як взагалі працювати без змінних?), Але виявляється, що, по суті, за допомогою значень можна досягти все те ж саме, що і зі змінними (хочете переконатися - спробуйте Scala, ця мова не є чисто функціональним , але передбачає можливість всюди користуватися значеннями). Інваріантні функції приймають аргументи і видають результат, не змінюючи оточення; тому ними значно простіше користуватися при паралельному програмуванні, адже інваріантна функція не блокує колективні ресурси.
До виходу Java 8 можна було створювати функції під час виконання тільки одним способом: генерувати і завантажувати байт-код (це досить заплутана і складна робота).

Для лямбда-виразів характерні дві такі риси:

  1. Більш лаконічний синтаксис при створенні функцій
  2. Можливість створювати функції під час виконання; потім ці функції можуть передаватися іншим кодом, або інший код може ними оперувати.

Замикання стосуються саме другий можливості

Що таке замикання?

При замиканні використовуються змінні, розташовані поза області дії функції. У традиційному процедурному програмуванні це не викликає особливих проблем - ви просто використовуєте змінну - але проблема виникає, як тільки ми починаємо створювати функції під час виконання. Щоб проілюструвати цю проблему, спочатку наведу приклад з Python. Тут make_fun () створює і повертає функцію під назвою func_to_return. яка потім використовується в іншій частині програми:

Отже, ми стикаємося з такою проблемою: якщо просто повернути func_to_return. що буде з n. що знаходяться поза області видимості func_to_return. Як правило, слід було б очікувати, що n вийде з зони видимості і стане недоступним, але якщо це станеться, то func_to_return не працюватиме. Для підтримки динамічного створення функцій func_to_return повинна "замкнутися" навколо n і забезпечити, щоб воно «дожило» до повернення функції. Звідси і термін «замикання».

Щоб протестувати make_fun (). ми двічі його викликаємо і зберігаємо результат функції в x і y. Той факт, що x і y дають абсолютно різні результати, демонструє, що що при кожному виклику make_fun () виникає цілком самостійна функція func_to_return з власним замкнутим сховищем для n.

Лямбда-вирази в Java 8

Розглянемо той же приклад на Java з використанням лямбда-виразів:

Виявляється, що лямбда-вирази в Java замикаються тільки навколо значень, але не навколо змінних. Java вимагає, щоб ці значення були незмінні, як якщо б ми оголосили їх final. Отже, вони повинні бути final незалежно від того, оголошували ви їх таким чином чи ні. Тобто, «фактично фінальними». Тому в Java є «замикання з обмеженнями», а не «повноцінні» замикання, які, тим не менш, досить корисні.

Все компілюється без проблем, щоб в цьому переконатися можете просто поставити ключове слово final в визначення n. Зрозуміло, якщо застосувати такий хід з будь конкуренцією, то виникне проблема із змінним розділяються станом.

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

Я поцікавився, чому ж ці структури назвали «Лямбда», а не просто «замиканнями» - адже за всіма ознаками це чисті замикання. Мені відповіли, що «замикання» - невдалий і перевантажений термін. Коли хтось говорить «справжнє замикання», то найчастіше має на увазі такі «замикання», які попалися йому в першому освоєному мовою програмування, де були сутності, іменовані «замиканнями».

Я не вбачаю тут спору «ООП проти ФП», втім, і не збирався його влаштовувати. Більш того, я навіть «проти» тут не бачу. ООП добре підходить для абстрагування даних (і нехай навіть Java змушує вас працювати з об'єктами, це ще не означає, що будь-яке завдання вирішується за допомогою об'єктів), а ФП - для абстрагування поводжень. Обидві парадигми корисні, і, на мій погляд, тим більше корисні, якщо їх змішувати - і в Python, і в Java 8. Нещодавно мені довелося попрацювати з Pandoc - конвертером, написаному на чисто функціональному мовою Haskell, причому у мене залишилися від цього самі позитивні враження. Отже, чисто функціональні мови, також заслуговують місця під сонцем.

Схожі статті