LINUX.ORG.RU
ФорумTalks

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


2

5

В последнее время только и слышу о новых ЯП с поддержкой лямбда-выражений, это что - мода такая или оно действительно резко стало нужно?

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

смысл у лямбда-выражения такой же, как и у функции. собственно, это и есть функция

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

jtootf ★★★★★
()
Ответ на: комментарий от Reset

>Сейчас во всех языках лямбды поддерживаются, ну кроме Си ассемблера и фортрана :)

Грубо говоря это анонимная функция.

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

SebastianPoeiro
()
Ответ на: комментарий от LongLiveUbuntu

>Насчет полотенца тоже верно.

Раздельные полотенца для головы и тела одно из требований к цивилизованному человеку

DNA_Seq ★★☆☆☆
()

Сначала, прочитай вот это: (из Википедии)

Motivation

Functions are a fundamental concept within computer science and mathematics. The λ-calculus provides simple semantics for computation with functions so that properties of functional computation can be studied.

Consider the following two examples. The identity function I(x) = x takes a single input, x, and immediately returns x (i.e. the identity does nothing with its input), whereas the function sqadd(x, y) = x*x + y*y takes a pair of inputs, x and y and returns the sum of their squares, x*x + y*y. Using these two examples, we can make some useful observations that motivate the major ideas in the lambda calculus.

The first observation is that functions need not be explicitly named. That is, the function sqadd(x, y) = x*x + y*y can be rewritten in anonymous form as (x, y) ↦ x*x + y*y, (read as “the pair of x and y is mapped to x*x + y*y”). Similarly, I(x) = x can be rewritten in anonymous form as x ↦ x, where the input is simply mapped to itself.

The second observation is that the specific choice of name for a function's arguments is largely irrelevant. That is, x ↦ x and y ↦ y express the same function: the identity. Similarly, (x, y) ↦ x*x + y*y and (u, v) ↦ u*u + v*v also express the same function.

Finally, any function that requires two inputs, for instance the before mentioned sqadd function, can be reworked into an equivalent function that accepts a single input, and as output returns another function, that in turn accepts a single input. For example, (x, y) ↦ x*x + y*y can be reworked into x ↦ (y ↦ x*x + y*y). This transformation is called currying, and can be generalized to functions accepting an arbitrary number of arguments.

Currying may be best grasped intuitively through the use of an example. Compare the function (x, y) ↦ x*x + y*y with its curried form, x ↦ (y ↦ x*x + y*y). Given two arguments, we have:
((x, y) ↦ x*x + y*y)(5, 2)
= 5*5 + 2*2 = 29.
However, using currying, we have:
((x ↦ (y ↦ x*x + y*y))(5))(2)
= (y ↦ 5*5 + y*y)(2)
= 5*5 + 2*2 = 29
and we see the uncurried and curried forms compute the same result. Notice that x*x has become a constant.
Потом посмотри, как выглядят анонимные функции на любимом ЯП: *ссылка на Википедию*, замыкания: *ссылка на Википедию* и каррирование:*ссылка на Википедию*

kermzyxer
()

В последнее время только и слышу о новых ЯП с поддержкой циклов и процедур, это что - мода такая или оно действительно резко стало нужно? Я всю жизнь пользовался goto и мне хватало, все эти новшества по-моему один синтаксический сахар.

queen3 ★★★★★
()
Ответ на: комментарий от SebastianPoeiro

>> Это будут не лямбды.

яйца одни и теже, только вид сбоку.

Ты программист или прос^Wспециалист по яйцам?

tailgunner ★★★★★
()
Ответ на: комментарий от queen3

В случае ассемблера тебе хватит je/jne и jmp ))

А на самом деле на мой вкус хороший ЯП должен иметь: проработанные основные алгоритмические конструкции - if, while, for, процедуры; иметь не переусложненную объектную модель (основные концепции ООП, дженерики), управляемый сборщик мусора.

LongLiveUbuntu ★★★★★
() автор топика
Ответ на: комментарий от LongLiveUbuntu

> В случае ассемблера тебе хватит je/jne и jmp ))
Я такой асм видел только 1 раз: когда автор книги описывал архитектуру проца, упрощенную сильно. Больше операторов перехода, полезных и разных!
Раз уж на то пошло, хватит одного je.

kermzyxer
()
Ответ на: комментарий от tailgunner

>Ты программист или прос^Wспециалист по яйцам?

Звучит как «Ты что, не коммунист?».

Я не программист, я кодер, тупой, обезбашенный кодер со стажем если уже на то пошло.

SebastianPoeiro
()
Ответ на: комментарий от LongLiveUbuntu

>управляемый сборщик мусора.

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

SebastianPoeiro
()
Ответ на: комментарий от SebastianPoeiro

> Я не программист, я кодер, тупой, обезбашенный кодер

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

tailgunner ★★★★★
()
Ответ на: комментарий от post-factum

Вот пример.

Стоит цель: обойти список элементов и выполнить некие действия над ними. В функциональных ЯП для этого используются лямбда-выражения. Это позволяет абстрагироваться от метода обхода (всякие итераторы, счетчики) и систем передачи результата наружу. Т.е. существует некоторый код обработки, и есть некоторый обходчик (предоставлен самим ЯП или самописный). Мы в обходчик списков передаем только код обработки одного элемента, и при этом не реализуем сам обход списка. Таким образом, в коде просто отсутствуют рутинные вещи типа циклов.

Пример кода на абстрактном императивном языке. Код делает обход списка list1, увеличивает каждый элемент на N и сохраняет результат в другой список list2:

N = 1;

for i in [0..length(list1)] {
    list2[i] = list1[i] + N;
}

А вот например на эрланге:

N = 1,
List2 = lists:map(fun(E) -> E+N end, List1).

В последнем примере объявлено лямбда-выражение: анонимная функция fun(E) -> E+N end, тело которой (выражение E+N) порождает результирующие значение нового элемента. Эта функция будет вызвана для каждого элемента списка, а из её результатов будет создан новый список. Т.е. лямба-выражения позволяют четко отделить частый рутинный код от непосредственной логики программы. И обрати внимание на переменную N: она передалась в тело лямбда-функции извне и как бы стала частью кода функции. Если функция верхнего уровня завершится, то тело лямбда-функции всё равно будет иметь доступ к N.

Далее, в эрланге, лямбда-функцию можно к примеру передать на другой узел кластера на другом континенте, и она там выполнится точно также даже если запускать через час/день/год. Лямбда-функции можно динамически генерировать и делать из них списки (например список юнит-тестов, где каждый элемент - действие). Ну в общем, лучше один раз увидеть, чем сто раз услышать.

shahid ★★★★★
()
Ответ на: комментарий от SebastianPoeiro

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

kermzyxer
()
Ответ на: комментарий от tailgunner

начни повышение профессионального уровня с усвоения разницы между функцией и лямбдой

Алонзо Чёрч ворочается в гробу

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> Алонзо Чёрч ворочается в гробу

Стесняюсь спросить, откуда ты это знаешь %)

P.S. «лямбда» в данном случае - конструкция ЯП, а не математическая абстракция. Впрочем, ты же это знаешь...

tailgunner ★★★★★
()
Ответ на: комментарий от Begemoth

На самом деле штука удобная. Я частенько пользую. Но, зараза, получается искючительно как костыль.
Например, месяц строишь uml. Ну кажется все продумал. Патернов нацеплял. Красиво шо пипец получается. Чуствуешь себя умным, ну прям старшира сверхсрочник.
И в один прекрасный момент делая new() для красивейше реализованного класса. Краса и гордость всего проекта, понимаешь, что этому классу нужен доступ к приватным свойствам хозяйского класса. Аж пот прошибает! Билиать!!!.. Вот зараза!
Городить какой-то новый огород как -то совсем не в тему. Остается внутри скобочек new() описать наследника зашибительского класса, перекрыв пару пустячных метода. Фублин.. Отпустило.
А вот заранее так запроектировать чтоба эти лямды изначально задумать, ни разу не удалось.

vada ★★★★★
()
Ответ на: комментарий от shahid

 for i in [0..length(list1)] {
    list2[i] = list1[i] + N;
}

А вот например на эрланге:


 N = 1,
 List2 = lists:map(fun(E) -> E+N end, List1)

Ну и что легче читается? Угадайте с 3-х раз..

gandjubas
()
Ответ на: комментарий от gandjubas

Не зная эрланга (видел одну программу на нем написанную) могу сказать: однозначно, второй пример легче читается. Особенно после прочтения книги по OCaml.

delete83 ★★
()
Ответ на: комментарий от gandjubas

Для тех кто чужого кода никогда не видел: можно вынести лямбду за пределы вызова map(), куда-нибудь в другую функцию, модуль, и т.д.:

F = fun(E) -> E+N end,
lists:map(F, List2).
или вообще реализовать отдельной функцией:
do(List) ->
    F = fun lamda_body/1,
    lists:map(F, List).

lamda_body(E) -> E+N.
Мой пост - это лишь простой тупой пример использования. Как только в цикле появляются всякие вложенности, подциклы, if и т.д. чтение лямбда-функций начинает казаться легким и непринужденным даже без предшествующего опыта.

shahid ★★★★★
()
Ответ на: комментарий от gandjubas

> Ну и что легче читается? Угадайте с 3-х раз..
Лол. Ты думаешь, основной критерий при разработке ЯП - это чтобы код легко читался?

kermzyxer
()
Ответ на: комментарий от kermzyxer

> Ты думаешь, основной критерий при разработке ЯП - это чтобы код легко читался?

Мне побарабану что является основным критерием при разработке ЯП. Я буду использовать те языки, которые легче читаются.

gandjubas
()
Ответ на: комментарий от kermzyxer

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

gandjubas
()
Ответ на: комментарий от kermzyxer

> хватит одного je

Кошмар, и в ассемблере полно синтаксического сахара. Все на брейнфак!

queen3 ★★★★★
()
Ответ на: комментарий от SebastianPoeiro

яйца одни и теже, только вид сбоку.

к слову о яйцах - напиши на C функцию, которая принимает число, и возвращает функцию, возвращающую это число

jtootf ★★★★★
()
Ответ на: комментарий от vada

Например, месяц строишь uml. Ну кажется все продумал.

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

Begemoth ★★★★★
()
Ответ на: комментарий от kermzyxer

>Ээээ... так везде, где есть автоматич. упр. памятью, можно и ручками память освобождать. На сколько я понимаю, это и значит управляемый сборщик мусора. Я не прав?

Да. Ты не прав. Сборщику мусора ты можешь только намекнуть освободить память, но гарантий тебе никто никаких не даст. Он сам по себе, твои хотелки относительно памяти сами по себе.

SebastianPoeiro
()
Ответ на: комментарий от LongLiveUbuntu

Управляемый сборщик - это такой, который я могу запустить в нужный мне момент времени.


Гы. Тогда правильнее такой сборщик мусора назвать free().

Когда в ЯП со сборщиком мусора кодеркам хоть каким то боком надо иметь дело со сборщиком мусора, там ручками его дергать, запускать когда прижимает - все это свидетельствует только о двух вещах:

1. Говяности кодерка
2. Говяности реализации Сборщика мусора в ЯП

SebastianPoeiro
()
Ответ на: комментарий от gandjubas

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

Zenom ★★★
()
Ответ на: комментарий от Zenom

> Обойтись можно даже без одного глаза, девяти пальцев, одной руки, одной ноги и половых органов. Но я не хочу.

Ты как дитё малое. Кстати, характерная черта таких индивидуумов - это дроч на извлечение факториала в одну строку. С возрастом обычно проходит.

gandjubas
()
Ответ на: комментарий от Reset

Вместо того чтобы делать так


void my_callback()

{

// callback code

}

...

doall(my_callback);


Ты делаешь так


doall(lambda () { /*callback code */} );


Я не понимаю, какой смысл офомлять код в виде «callback», если то, что написано в лямбде, используется 1 (один!) раз.

Смысл callback в том, что можно переопределять поведение объекта, подсовывая _разный_ callback код.

В лямбде callback код _один_, ибо функция анонимна. Какой смысл вообще описывать _один_ кусок кода в виде callback, и городить лямбду, если можно написать этот код напрямую?

pat_minus
()
Ответ на: комментарий от kermzyxer

>>Щито??

Потрудись-ка придать обсуждабельную форму своим обезьяньим ужимкам.

Для иллюстрации утверждений теорий особенностей Уитни Арнольду достоточно было мысленно покачать в разные стороны полупрозрачную бутылку (теорема об устойчивости сборки).

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

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

mclaudt
()
Ответ на: комментарий от gandjubas

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

Zenom ★★★
()
Ответ на: комментарий от pat_minus

> Какой смысл вообще описывать _один_ кусок кода в виде callback, и городить лямбду, если можно написать этот код напрямую?

Нужен именно callback. Напиши «код напрямую».

tailgunner ★★★★★
()
Ответ на: комментарий от mclaudt

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

«Сущность математики… представляется теперь как учение об отношениях между объектами, о которых ничего не известно, кроме описывающих их некоторых свойств,— именно тех, которые в качестве аксиом положены в основание теории… Математика есть набор абстрактных форм — математических структур.» (c)

но это, конечно, неводмёк неучам, считающим что они умнее прочих и ищущих геометрические аналогии от внутреннего ощущения собственного бессилия :)

shty ★★★★★
()
Ответ на: комментарий от Zenom

> остаётся только посочувствовать, что дрочь с возрастом прошла.

Может, у него этот возраст еще не наступал.

tailgunner ★★★★★
()
Ответ на: комментарий от Zenom

> Ну если ты не понимаешь для чего нужно повышение уровня абстракции

Когда-нибудь и ты дорастёшь до понимания, что высокий уровень абстракции сам по себе никому не упёрся.

gandjubas
()
Ответ на: комментарий от name_no

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

Вам прописывается курс SICP-о-терапии

shty ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.