Что такое лямбда в программировании
Перейти к содержимому

Что такое лямбда в программировании

  • автор:

Что такое лямбда-функции в программировании

Функции в языках программирования — это такие небольшие автономные программы, которые работают внутри основного кода. При запуске они могут взять какие-то стартовые параметры, обработать их, получить свой результат и отдать этот результат в основной код.

Чтобы вызвать функцию, нужно указать её имя, но бывают такие функции, у которых нет имени, но их всё равно можно вызывать. Рассказываем, как это работает.

Мы будем рассказывать про лямбда-функции на примере языка Python. В других языках лямбда-функции выглядят немного иначе, но принцип работы у них точно такой же.

Как работает обычная функция

Классическая функция выглядит так:

  1. Имя функции.
  2. Тело функции.
  3. Может быть: результат, который она возвращает, но может и не возвращать.

Запишем это на Python, чтобы было наглядно:

def add(x, y): result = x + y return result print(add(2,3))

У этой функции есть имя add . Есть то, что она делает внутри: складывает два числа. И есть результат, который она возвращает, — он хранится в переменной result . Чтобы вызвать эту функцию, мы указываем её имя и аргументы, которые ей нужно обработать: print(add(2,3)) .

Сейчас функция кажется избыточной, мол, сложение чисел можно сделать и так. Но саму эту функцию внутри можно сделать намного сложнее. Например, что могла бы делать эта функция:

  • Проверять, какие данные ей подали на вход, и в зависимости от их типа складывать их по-разному. Например, если ей дадут две строки, она может выдать ошибку; а может соединить строки.
  • Складывать не числа, а массивы из чисел. Правила сложения массивов нужно будет прописать.
  • Вести учёт всех сложений, которые она делала.
  • Преобразовывать входящие или исходящие данные.
  • Возвращать данные не в виде числа, а в виде целого объекта с кучей свойств, если это нужно программе.

И это только банальное сложение. Всю эту логику удобно упаковать внутрь функции и вызывать с помощью простого слова add() .

Что такое лямбда-функция

Лямбда-функция выглядит иначе: у неё нет имени, но есть ключевое слово lambda — оно показывает, что дальше пойдёт безымянная функция. В общем виде лямбда-функция выглядит так:

lambda переменные: значение функции

Чтобы эта функция могла куда-то вернуть своё значение, лямбда-функции присваивают переменным — и после этого их можно использовать как обычные функции. Перепишем наш пример со сложением в виде лямбда-функции:

result = lambda x, y: x + y print(result(2,3))

Если мы запустим оба фрагмента кода, то в обоих случаях увидим на экране число 5.

Может показаться, что во втором случае у нас всё равно получилась функция result, просто записанная иначе, и нет никакой разницы с первым способом. Но на самом деле различия есть: обычные функции не получится использовать на месте переменных, а лямбда-функции — можно. Про это расскажем чуть ниже.

Ограничение лямбда-функций

Значение лямбда-функции в Python должно быть записано в одну строку. Это значит, что внутри лямбда-функций не может быть циклов, других функций и всего остального, что требует для записи нескольких строк.

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

Также в лямбдах нет присваивания — это простое выражение, которому не нужно ничего промежуточно хранить, а нужно лишь посчитать.

Откуда такое название

Название лямбда-функций пришло в программирование из математического λ-исчисления, где λ — это как раз греческая буква «лямбда». Смысл там в том, что всё построено на переменных и их взаимодействии друг с другом. Условно, чтобы посчитать одно выражение, нужно найти значение всех его значений, тоже выраженное каким-то формулами, а потом подставить нужный параметр вместо переменной.

В лямбда-функциях всё то же самое:

  • есть выражение, заданное с помощью переменных;
  • есть общее значение, которое зависит от этого выражения;
  • когда мы подставляем в лямбда-функцию какое-то значение, функция обрабатывает его и получает определённый результат;
  • этот результат будет влиять на итог общего значения.

Зачем нужны лямбда-функции

Самая популярная область применения лямбда-функций — в качестве аргументов в других функциях. Мы с этим ещё столкнёмся в новых проектах, а пока пара примеров.

Допустим, у нас есть список с числами, из которого нам нужно отобрать только чётные. Для этого можно писать классическую функцию, которая переберёт каждый элемент списка и, если он чётный, добавит его в итоговый результат. А можно использовать лямбду и встроить фильтр сразу в момент создания нового списка:

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9] new_lst = list(filter(lambda x: (x%2 == 0) , lst)) print(new_lst)

Смотрите, что тут произошло:

  1. Мы сделали список с разными числами.
  2. Потом мы создали новый на основе старого, используя команду filter() — она выбирает из списка нужные элементы по критерию.
  3. В качестве такого критерия мы указали, что элемент можно брать, только если он чётный.
  4. Значения этих элементов берутся из старого списка lst.

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

Вот пример посложнее, но нагляднее: вывести словарь в порядке убывания суммы каждого значения. Алгоритму нужно сначала найти сумму значений каждого элемента словаря, отсортировать их по убыванию, а потом запомнить новый порядок вывода. Для этого используют функцию sorted() — она сортирует словарь по определённому критерию, но вот сам критерий проще всего определить с лямбдой:

bigrams = sorter = sorted(bigrams, key=lambda key: sum(bigrams[key]), reverse=True) for key in sorter: print(key, bigrams[key])

Здесь key — это как раз критерий фильтра, в котором мы используем лямбда-функцию. Эта функция считает сумму значений каждого элемента словаря и превращает это в критерий сортировки. Функции остаётся только быстро пробежать по всему словарю, используя готовые суммы, и отсортировать его в обратном направлении:

Что такое лямбда-функции в программировании

А вот если бы мы сделали это в виде обычной функции, получилось бы сложнее и не так очевидно. Сравните этот код с предыдущим — он делает то же самое, но выглядит более громоздко:

from functools import partial def sort_func(key, dict): return sum(dict[key]) bigrams = partial_sort = partial(sort_func, dict=bigrams) sorter = sorted(bigrams.keys(), key=partial_sort, reverse=True) for key in sorter: print(key, bigrams[key])

Ещё лямбда-функции иногда используют для создания замыканий — функций внутри функций, которые тоже зависят от входных параметров:

def addition(x): return lambda y: x + y add_to_ten = addition(10) print(add_to_ten(8)) print(add_to_ten(6))

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

Лямбда-выражения в Java — что это такое, зачем нужны и как выглядят

Лямбда-выражения или анонимные функции встречаются во многих языках программирования. Рассказываем про лямбда-выражения в Java с примерами.

Лямбда-выражения встречаются в разных языках программирования: JavaScript, PHP, C# и других. В этой статье поговорим о лямбда-выражениях в Java.

Для чего хорош Java?

Лямбда-выражения или анонимные функции — это блоки кода с параметрами, которые можно вызвать из другого места программы. Они называются анонимными, потому что в отличие от функций, у них нет имён. Слово «лямбда» пришло из лямбда-исчисления, которое придумал профессор Алонзо Чёрч. Он использовал греческую букву лямбда (λ), чтобы отметить параметры.

Лямбда-выражения в Java

  • Присутствуют начиная с 8 версии.
  • Являются анонимными классами, реализующими метод функционального интерфейса.
  • Имеют доступ только к final (или effectively final) переменным из охватывающей области видимости (для потокобезопасности).
  • Не могут возвращать значение в каких-то ветках, а в других не возвращать.
  • Позволяют уменьшить количество кода и повысить его читаемость.

Примеры синтаксиса лямбда-выражений в Java

Лямбда-выражения в Java состоят из параметров и стрелки —> отделяющей тело функции. Скобки нужны, если параметров 0 или больше одного. Для однострочных лямбд ключевое слово return не обязательно.

(список параметров) -> тело лямбды

Без параметров

@FunctionalInterface interface MyFunctionalInterface < //метод без параметров public String sayHello(); >public class Example < public static void main(String args[]) < // лямбда выражение MyFunctionalInterface msg = () ->< return "Привет мир"; >; System.out.println(msg.sayHello()); > > 

Этот код выведет в консоль текст: «Привет мир!».

C параметром

import java.awt.*; public class ButtonListenerNewWay < public static void main(String[] args) < Frame frame=new Frame("ActionListener java8"); Button b=new Button("Click Here"); b.setBounds(50,100,80,50); b.addActionListener(e ->System.out.println("Привет мир!")); frame.add(b); frame.setSize(200,200); frame.setLayout(null); frame.setVisible(true); > > 

В этом примере лямбда-выражение используется для обработки нажатия кнопки.

С несколькими параметрами

interface StringConcat < public String sconcat(String a, String b); >public class Example < public static void main(String args[]) < StringConcat s = (str1, str2) ->str1 + str2; System.out.println("Result: "+s.sconcat("Hello ", "World")); > > 

Здесь лямбда-выражение склеивает строки.

Что такое лямбда-выражения?

@niki-timofe, это слабое оправдание. Если вы не приложите усилий, чтобы задать хороший вопрос, то не можете ожидать, что мы приложим усилия, чтобы дать хороший ответ. Таким образом вам придется удовлетвориться копипастой из ссылки выше, что несколько глупо для программиста, ибо подразумевает выполнение машинной работы вручную.

19 мая 2012 в 20:23

4 ответа 4

Сортировка: Сброс на вариант по умолчанию

Лямбда-функции — это функции, у которой фактически нет имени. Таким образом математики упростили до невозможности формат записи функции, а вообще лямбда-исчислениями пытались формализовать вычисления

λ — означает, что это лямбда-функция. Всё что после неё — список аргументов, в идеале абсолютно любого типа, в том числе может быть и другая лямбда-функция. После точки идёт «тело функции», а уже потом, собственно, идёт аргумент, который будет передан. Т.о.

λx.x+2 2 // вернёт 4 
λx.x 2 λy.y+1 // результат 3 

Здесь в качестве параметра x выступает другая лямбда-функция λy.y + 1 , в которую передаётся параметр 2. То есть любая лямбда функция является функцией высшего порядка, может принимать в качестве аргумента другую функцию и возвращать функцию:

λx.λy.y+x+3 2 // вернёт λy.y+5, т.к. x был равен двум. λx.λy.y+x+3 2 3 // вернёт 8. Фактически это каррирование: сначала функция принимает аргумент 2 и возвращает функцию, которая принимает ещё один аргумент и возвращает результат. 

Если интересно, я когда-то писал аналогичные вещи на C#

Теперь давайте посмотрим, как же все наши примеры будут выглядеть на C#. Здесь в качестве лямбда-функции я использую Func, где T — тип аргумента, а U — тип возвращаемого значения:

1) Func func = x=>x; 2) var result = new Func(x=>x+2)(2); 3) var result = new Func(x=>x(2))(new Func(y=>y+1)); 4) var result = new Func(x=>y=>y+x+3)(2); 5) var result = new Func(x=>y=>y+x+3)(2)(3); 

Сложность составляет только явное указание типа аргументов и возвращаемого значения.

Объяснение лямбда-выражений

Объяснение лямбда-выражений

У меня возникли вопросы о лямбда-выражениях и RxJava. Эти вопросы в основном касаются не полного понимания лямбда-выражений или RxJava. Я попытаюсь объяснить лямбда-выражения как можно проще. RxJava я опишу отдельно.

Лямбда-выражения и RxJava

Что такое лямбда-выражения? Лямбда-выражения – это «всего лишь» новый способ сделать то же самое, что мы всегда могли сделать, но в более чистом и менее многословном новом способе использования анонимных внутренних классов.

Анонимный внутренний класс в Java – это класс без имени, он должен использоваться, если вам необходимо переопределить методы класса или интерфейса. Анонимный внутренний класс может быть создан из класса или интерфейса.

abstract class Animal < abstract void speak(); >Animal a = new Animal() < void speak() < System.out.println("Woff"); >>;

В Android мы обычно используем анонимный внутренний класс в качестве слушателя, например, для кнопок такого рода:

Button btn = findViewById(R.id.button); btn.setOnClickListener( new View.OnClickListener() < @Override public void onClick(final View view) < // Do some fancy stuff with the view parameter. >> );

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

new View.OnClickListener() < @Override public void onClick(final View view) < // Do some fancy stuff with the view parameter. >>

Лямбда-выражения могут использоваться только в том случае, если вам нужно переопределить не более одного метода. К счастью для нас, View.OnClickListener содержит только один. Посмотрите на код ниже. Как думаете, какую его часть нам придётся убрать?

new View.OnClickListener() < @Override public void onClick(final View view) < // Do some fancy stuff with the view parameter. >>

После удаления практически всего кода, нам нужно добавить ->, как в приведенном ниже коде. Входящий параметр view может использоваться внутри функции так же, как и раньше.

(view) -> < // Do some fancy stuff with the view parameter. >

В некоторых случаях вам может потребоваться добавить тип к параметру, если компилятору не удается его угадать, вы можете сделать это, добавив его перед параметром:

(View view) -> < // Do some fancy stuff with the view parameter. >

Вы также можете использовать многострочный код:

(view) ->

Если у вас есть интерфейс с методом, принимающим два параметра…

interface MyInterface

…лямбда-выражение будет выглядеть следующим образом:

Если метод имеет возвращаемый тип…

interface MySecondInterface

…лямбда-выражение будет выглядеть следующим образом:

Но это еще не все, есть некоторые специальные случаи, которые делают код еще меньше. Если тело вашего метода содержит только одну строку кода, вы можете удалить фигурные скобки <>. Если вы удаляете фигурные скобки, вам также необходимо удалить точку с запятой, оставив следующее:

(a, b) -> return a + b

Есть еще одна вещь, которую мы можем сделать. Если у нас только одна строка кода, то компилятор может понять, нужна ли возвращаемая часть или нет, поэтому мы можем оставить ее следующим образом:

(a, b) -> a + b

Если бы у нас был многострочный код, это свелось бы к следующему:

Так что же мы сделали? Мы взяли это:

new MySecondInterface() < @Override public int onSecondMethod(final int a, final int b) < return a + b; >>;

и превратили вот в это:

(a, b) -> a + b

Осталось только одна вещь, ссылки на методы. Допустим, у нас есть интерфейс, как и раньше, и метод, который этот интерфейс принимает как параметр:

public interface Callback < public void onEvent(int event); >public void myMethod(Callback callback)

Без лямбда-выражения это выглядело бы так:

myMethod(new Callback() < @Override public void onEvent(final int state) < System.out.println(state); >>); 

Добавив лямбда-выражение, как мы это делали раньше, получим следующее:

myMethod(state -> System.out.println(state));

Но это еще не все. Если используемый код – однострочный и вызываемая функция принимает один параметр, мы можем передавать ссылку на метод в таком виде:

myMethod(System.out::println);

Параметр будет передаваться автоматически, без необходимости использования другого кода! Удивительно, правда? Надеюсь, вы узнали что-то новое!

  • android development
  • android
  • java
  • rxJava
  • реактивное программирование
  • перевод с английского
  • программирование
  • разработка
  • devcolibri
  • андроид
  • джава
  • никто не читает теги
  • Программирование
  • Java
  • Разработка мобильных приложений
  • Разработка под Android

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *