LINUX.ORG.RU
ФорумTalks

лямбды в новых язычках - PR или реальные полезняшки?

 , ,


7

7

Народ, а поясните пожалуйста, что конкретно имеется ввиду, когда некто, описывая всякие плюшки новорожденного языка восторженно заявляет «там есть лямбды!».

Ну что есть lambda в каком-нибудь lisp я представляю и даже понимаю зачем оно и как им пользоваться. В lisp'е. А что имеется ввиду под «лямбдой» например, в C#?

Хотелось бы увидеть не только цитаты из википедии, а простенькие примеры того, как эта лямбда сильно упрощает жизнь, удобство даёт и всё такое. В виде примера кода, разумеется, с пояснениями почему тут именно лямбда крута и без неё некузяво.

Только чтобы это не было аналогом перлового однострочника типа

perl -e 'print sub{ $_[0] + $_[1]; }->(1,2)."\n";'
ибо в этом никаких новшеств и преимуществ нету.

Просто сдаётся мне что «лямбда» в нынешних сишарпах это пиарное название допотопных безымянных функций которые даже в перле есть и никаких новшеств в этом на самом деле нету.

★★★★★
Ответ на: комментарий от linuxnewb

Даже похапешники используют лямбды

вот на сишечке

#include <stdio.h>

void increment(int *x)
{
	(*x)++;
}

void output(int *x)
{
	printf("%d\n", *x);
}

int array[] = { 1, 2, 3, 4, 5, 0 };

void ff(int *a, void (*foo)(int*))
{
	int j;
	for(j = 0; a[j]; j++)
		foo(&a[j]);
}

int main(void)
{
	ff(array, increment);
	ff(array, output);
	return 0;
}
писалось специально так, что-бы было понятно любому пхпшнику.

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

чем плох сишный указатель на функцию

Очевидно, тем что он сишный, а пример на пхп (да, он говно итд итп)? Но ты прав, данный пример — довольно простой. Приведен как иллюстрация на вопрос «зачем» — в пхп до 5.3, где этого не было, самый простой способ кодреюза для таких ситуаций был копипаст.

>А в php получится НЁХ В пхп прототип функции приходится точно и явно указать ровно так же, ибо не из астрала же он возьмется.

открой для себя man 3 qsort

Ты о чем?

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

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

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

Функцию ff не менять

это что за искусственные ограничения? в С вполне себе принято передавать одним дополнительным параметром «пользовательские» данные

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

чем плох сишный указатель на функцию, который делает в точности тоже самое?
qsort

разный код получается. Кому-то нравится в одном стиле писать, кому-то - в другом //К.О.

Вот совсем недавно Страуструп ругался на следующее:

Библиотека реализована как стандартный C++11 код с шаблонным мета-программированием и несколькими макросами. Оно работает примерно также быстро, как эквиваленты на OCaml или Haskell, и даже иногда приближается по быстродействию или даже становится быстрее написанного руками C++ кода, который использует Visitor дизайн-паттерн.
Библиотека Mach7 и идеи в ней были мотивирована нашим неудовлетворительным опытом работы с различными C++-ными фронт-эндами и фреймворками для анализа программ. Проблема была не с самими фреймворками, но с фактом, что мы должны были использовать шаблон проектирования Visitor для того, чтобы смотреть, обходить и обогощать абстрактные синтаксические деревья целевых языков. Мы нашли Visitor-шаблоны неподходящими для прямого выражения логики приложения, удивительно сложными для обучения студентов, и часто более медленными, чем решения для обхода, написанные вручную. Вместо них, пользователи опирались на динамические приведения типов во многих местах, часто многоуровневые, таким образом предпочитая более короткий, более ясный, и более прямой код, нежели чем Visitor'ы. Соответствующий проигрыш в производительности был обычно незамечаем до более поздних стадий кодирования, когда уже было поздно что-то менять.

подробнее тут: http://lionet.livejournal.com/119147.html

callback функции придумали задолго до лямбд

чтобы иметь полноценную callback-функцию (а не паттен Команда - класс с методом run), нужно иметь лямбды (lambda functions, lambda expressions == closures). Твою фразу можно переписать как «лямбды придумали задолго до лямбд». Поделил на ноль :)

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

это что за искусственные ограничения?

Чтобы продемонстрировать разницу между указателями на функции и лямбдами, не?

в С вполне себе принято передавать одним дополнительным параметром «пользовательские» данные

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

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

Еще раз повторяю — я не знаю С# и никогда на нем не писал. А то что ты привел в качестве примера это C++. Указанные вещи очень помогают когда, например, пишешь код в асинхронном стиле на колбеках. Колбек определяешь и передаешь в функцию прям на месте. Это очень удобно. Посмотри, например, примеры для boost::asio. Там так и напрашиваются лямбды.

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

писалось специально так, что-бы было понятно любому пхпшнику.

function lol($query,$f)
...
return($return);

пхпшники теперь зазнаются

void ff(

// блин, ну повнимательнее же! тупаком и так тред полон.

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

Очевидно, тем что он сишный, а пример на пхп (да, он говно итд итп)? Но ты прав, данный пример — довольно простой. Приведен как иллюстрация на вопрос «зачем» — в пхп до 5.3, где этого не было, самый простой способ кодреюза для таких ситуаций был копипаст.

это phpпроблемы. На вопрос «зачем нужны лямбда-функции?» ответа так и нет.

Ты о чем?

я о том, что проблема из твоего примера уже лет 40 решается без всяких лямбда-функций. Причём решается куда как безопаснее и надёжней, чем в этом твоём php.

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

У меня в методе объекта используется для работы с коллекциями 5-6 разных функций. Ты предлагаешь на каждый предикат вида x => x > 5 добавлять новый метод?

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

На вопрос «зачем нужны лямбда-функции?» ответа так и нет.

Ты читать не умеешь? Тебе уже привели два юз-кейса:

лямбды в новых язычках - PR или реальные полезняшки? (комментарий)

лямбды в новых язычках - PR или реальные полезняшки? (комментарий)

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

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

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

Вот тебе вариант с глистами (:

#include <stdio.h>
#include <stdarg.h>

void increment(int *x, va_list vl)
{
	(*x)++;
}

void output(int *x, va_list vl)
{
	printf("%d\n", *x);
}

void add(int *x, va_list vl)
{
	*x += va_arg(vl, int);
}

int array[] = { 1, 2, 3, 4, 5, 0 };

void ff(int *a, void (*foo)(int*, va_list), ...)
{
	int j;
	for(j = 0; a[j]; j++)
	{
		va_list vl;
		va_start(vl, foo);
		foo(&a[j], vl);
		va_end(vl);
	}
}

int main(void)
{
	ff(array, increment);
	ff(array, add, 17);
	ff(array, output);
	return 0;
}

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

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

разный код получится если ты будешь юзать нормальные лямбда-функции. А я писал про phpшные callback-костыли. Они ничем не лучше сишных указателей на функции, только работают хрен знает как.

чтобы иметь полноценную callback-функцию (а не паттен Команда - класс с методом run), нужно иметь лямбды (lambda functions, lambda expressions == closures). Твою фразу можно переписать как «лямбды придумали задолго до лямбд». Поделил на ноль :)

не спорю. Но вот я не могу найти пример, в котором применения лямбд давала бы какой-то профит. Страуструп вот нашёл... Ну пойду по ссылке, почитаю...

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

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

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

с юзом - это не лямбда, это замыкание

... я рад что вы в курсе..

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

Чтобы продемонстрировать разницу между указателями на функции и лямбдами, не?

не. В C есть функции с переменным числом параметров. Ничего революционного в этом нет.

Я, в принципе, так себе это и представляю: функция ff принимает контекст (указатель на void) и передает ее функции-аргументу. Но это будет уже другой код, не тот, который предложил drBatty.

не обязательно. См. выше - если применять функции с переменным числом параметров, то всё работает. Можешь скопилять и проверить. УМВР. В php ВСЕ функции с переменным числом параметров, а в C это надо специально объявить. Вот и вся разница.

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

Еще раз повторяю — я не знаю С# и никогда на нем не писал. А то что ты привел в качестве примера это C++.

нет. Это обычный C без плюсов. Писать так на плюсах == быдлокод. В C++ есть свои методы для таких вещей, а именно виртуальные функции и абстрактные классы.

Указанные вещи очень помогают когда, например, пишешь код в асинхронном стиле на колбеках. Колбек определяешь и передаешь в функцию прям на месте. Это очень удобно. Посмотри, например, примеры для boost::asio. Там так и напрашиваются лямбды.

дык ТЕБЕ напрашиваются, вот ТЫ и покажи. Мне не напрашиваются почему-то.

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

блин, ну повнимательнее же! тупаком и так тред полон.

я всё равно не понял - $return это массив. Я что, в сишечке массив вернуть не могу? Что это меняет-то?

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

Здесь нет лямбд.

а в php коди они есть?

напомню:

function lol($query,$f)
{
  $return=array();
  $result=mysql_query($query);
  while($row=mysql_fetch_assoc($result))
    {
    $return[]=$f($row);
      }
  return($return);
}

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

Писать так на плюсах == быдлокод. В C++ есть свои методы для таких вещей, а именно виртуальные функции и абстрактные классы.

Бред. В этом случае у тебя получится нагромождение, лапша и очень много слов.

Мне не напрашиваются почему-то.

Естественно, ты же только трыдеть горазд, а толком ни в чем не разбираешься и ничего не умеешь.

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

Вот http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/example/porthopper/c...

только тут бустовая лямбда, поэтому немого громоздко выглядит, но с наследованиями и абстрактыми методами вообще ад будет

Reset ★★★★★
()
Последнее исправление: Reset (всего исправлений: 1)
Ответ на: комментарий от encyrtid

У меня в методе объекта используется для работы с коллекциями 5-6 разных функций. Ты предлагаешь на каждый предикат вида x => x > 5 добавлять новый метод?

а ты разве не видел, что у меня C код? Причём тут какие-то «методы»? В C нет и не будет никаких методов. А использовать Cшный код как доказательство убогости C++ - убого по сути.

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

Ты читать не умеешь? Тебе уже привели два юз-кейса:

ты мои ответы на эти посты читал? повторить?

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

а ты разве не видел, что у меня C код? Причём тут какие-то «методы»? В C нет и не будет никаких методов. А использовать Cшный код как доказательство убогости C++ - убого по сути.

Да какая разница? В сишке тебе придется на каждый предикат отдельную функцию заводить.

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

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

фишка в том, что в ИП это НЕ НУЖНО. А вот в ФП - таки нужно, ибо в ФП функция влияет ТОЛЬКО сама на себя. Вот и приходится её на что-то замыкать. А в ИП функция влияет на какие-то «данные», которые этой функции НЕ принадлежат, потому-то её и не нужно на эти данные замыкать. Это плохо в двух случаях:

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

2. сложнее писать функции, для работы с другими функциями, а не жёсткие алгоритмы вроде конечных автоматов. К счастью, IRL такие функции не нужны, и даже в случае если и нужны, всегда можно написать свой ЯП для данного конкретного случая. ИМХО перетачивать под данный случай какой-то готовый ФП далеко не всегда проще написания своего ФП.

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

Странное ты какое-то чудо, здесь тебе люди вообще-то помочь хотели - писали определения и примеры кода.

А мне помогать не надо было. Надо было просто ответить на вопрос заданный в топике. Всего лишь 2 варианта:

1. Нет, «лямбды» в сисярпах не являются новшеством и ничего не дают по сравнению с реализациями анонимных функций в других языках.

2. «лямбды» в сисярпах отличаются тем, что например на перле и пр. в приниципе невозможно реализовать вот это:

тут должен был идти простой и понятный пример кода который только на C# реализуем.

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

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

это phpпроблемы.

окэи

На вопрос «зачем нужны лямбда-функции?» ответа так и нет

это drBattyпроблемы

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

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

Решается в точности так же. И прекрати уже сравнивать си с пхп, вопрос был не «чем C лучше PHP», а «какие приемущества от использования лямбд», так что для большей достоверности давай сравнивать в рамках одного языка.

Причём решается куда как безопаснее и надёжней, чем в этом твоём php

Это манипуляции с адресами-то безопасней? А как же «стрелять себе в ногу»?

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

Бред. В этом случае у тебя получится нагромождение, лапша и очень много слов.

а что ты хочешь сделать? что по твоему «этот случай»?

Естественно, ты же только трыдеть горазд, а толком ни в чем не разбираешься и ничего не умеешь.

да-да. А ты умеешь только трыдеть о том, чего я не умею, и в чём я не разбираюсь. (;

А сам-то ты что умеешь?

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

только тут бустовая лямбда, поэтому немого громоздко выглядит, но с наследованиями и абстрактыми методами вообще ад будет

а зачем тут лямбда?

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

Исключительно для сокращения кода и удобочитаемости.

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

Да какая разница? В сишке тебе придется на каждый предикат отдельную функцию заводить.

да. А есть такой ЯП без матриц, в котором можно сделать новый тип Matrix, а потом написать

Matrix A, B;
A=...
B=...
Matrix C = A * B;

без определения умножения?

ХОЧУ!!!

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

Можешь, но не делаешь, это и меняет — у тебя принцип работы другой получается. Будь внимательнее.

могу и делаю, будь внимателен - аргумент int *a у меня не только входной, но и выходной. void increment(int *a) возвращает не только void, но и ещё увеличенный массив. В php такой эффект будет если передать ссылку на массив, а вот в C это делается «автоматически».

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

ну и чем это принципиально отличается от

Простейший пример - ничем. Но ни на что более сложное Си не способен (в отличие от Питона).

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

Писать так на плюсах == быдлокод. В C++ есть свои методы для таких вещей, а именно виртуальные функции и абстрактные классы.

Хватит тупак генерировать.

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

Решается в точности так же. И прекрати уже сравнивать си с пхп, вопрос был не «чем C лучше PHP», а «какие приемущества от использования лямбд», так что для большей достоверности давай сравнивать в рамках одного языка.

а я и не сравнивал си и пхп. Этот код на си эквивалентен твоему коду на пхп. И в нём нет никаких лямбд.

Это манипуляции с адресами-то безопасней?

подумай сам что безопаснее:

1. ты передаёшь хрен знает что, а потом используешь это как указатель на функцию.

2. я передаю указатель на конкретную функцию и использую его как указатель на конкретную функцию.

Я тоже могу передать «хрен знает что» как void*, а потом его кастануть во что угодно. Это разве безопаснее? Уж лучше мой второй вариант, в котором я передал не указатель на функцию, а указатель на функцию у которой не менее двух параметров. Сколько именно - хрен знает, но согласись, это получше твоего void*.

А как же «стрелять себе в ногу»?

сишечка - такое ружьё, которое надо взять в руки определённым образом, направить дуло на ноги, и нажать вполне определённый курок. Тогда нога будет отстреляна. Иначе программа не соберёться. ПХП - это такое ружьё, которое можно взять как угодно, навести на что угодно, и нажать что угодно. И оно отстрелит. Что угодно.

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

тут должен был идти простой и понятный пример кода который только на C# реализуем.

Фееричный бред. Про тьюринг-полноту доводилось слышать?

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

Исключительно для сокращения кода и удобочитаемости.

Колбеки на наследовании и абстрактых методах.

попроще и покороче пример можно? (можешь ответить «нет», я пойму)

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

А есть такой ЯП

Есть такой язык, в котором можно написать

arr map(toInt) select(more(20)) sort uniq map(toString) join(", ")
А теперь напиши это же на сишечке и сравни объем кода.

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

Обоснуй.

Да десятки примеров и в учебниках, и выше по треду. Сделай мне на Си так (лямбда и карринг):

>>> add = lambda x, y: x + y
>>> add(1, 2)
3
>>> incr = lambda y: add(1, y)
>>> incr(3)
4

Или так (замыкание):

>>> def f(x): return lambda y: x+y
...
>>> incr = f(1)
>>> incr(1)
2
tailgunner ★★★★★
()
Ответ на: комментарий от drBatty

не. В C есть функции с переменным числом параметров. Ничего революционного в этом нет.

Т.е. ты будешь утверждать что разницы между указателем на функцию и ламбдой (замыканием) нет?

В php ВСЕ функции с переменным числом параметров, а в C это надо специально объявить.

Да что ты к php прицепился? Лямбды - не эклюзивная фича php.

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

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

private IEnumerable<int> func1(IEnumerable<int> list)
{
    return list.Where(x => x > 5);
}

Без лямбд нужно заводить отдельную функцию для каждого предиката.

private IEnumerable<int> func2(IEnumerable<int> list)
{
    return list.Where(predicate);
}

private bool predicate(int x)
{
    return x > 5;
}
Лямбды значительно сокращают код, в сишке ты так не сделаешь.

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