LINUX.ORG.RU
ФорумTalks

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

 , ,


7

7

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

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

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

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

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

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

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

Я слышал, что у сишников в крови экономить каждый байт

ну и тебе кстати кто-то соврал, ну или ты себе что-то сам придумал, задачка на сообразительность (может у вас она таки немного есть):

{
	0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
};

для чего может быть нужен такой массив?

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

Вопрос ТСа из серии «Я слышал звон...» Любой парадигме свое место - просто полезно знать, что в языке есть и когда его удобно применять - никто не принуждает решать задачи модным способом, если старый работает (помню, в одном проекте загонялись чинить не сломанное - код с делегатами на лямбды переписывать и т.д. вслед за ростом версий C#. Та еще дурь и бесполезная трата времени (хотя, надо ж чем-то жуниаров было занимать до кризиса :)), но в новом коде - почему бы и нет, если код получается менее многословным).

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

просто стало интересно - скормил твой код на несколько строк кложуре:

WARNING: reader macro ^ is deprecated; use meta instead
WARNING: reader macro ^ is deprecated; use meta instead
WARNING: reader macro ^ is deprecated; use meta instead
WARNING: reader macro ^ is deprecated; use meta instead
Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol (1.cl:1)
	at clojure.lang.Compiler.analyze(Compiler.java:4420)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:4580)
	at clojure.lang.Compiler.analyze(Compiler.java:4405)
	at clojure.lang.Compiler.access$100(Compiler.java:35)
	at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:373)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:4592)
	at clojure.lang.Compiler.analyze(Compiler.java:4405)
	at clojure.lang.Compiler.analyze(Compiler.java:4366)
	at clojure.lang.Compiler.eval(Compiler.java:4646)
	at clojure.lang.Compiler.load(Compiler.java:4972)
	at clojure.lang.Compiler.loadFile(Compiler.java:4939)
	at clojure.main$load_script__7405.invoke(main.clj:213)
	at clojure.main$script_opt__7442.invoke(main.clj:265)
	at clojure.main$main__7466.doInvoke(main.clj:346)
	at clojure.lang.RestFn.invoke(RestFn.java:413)
	at clojure.lang.Var.invoke(Var.java:359)
	at clojure.lang.AFn.applyToHelper(AFn.java:173)
	at clojure.lang.Var.applyTo(Var.java:476)
	at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
	at clojure.lang.LazySeq.sval(LazySeq.java:47)
	at clojure.lang.LazySeq.seq(LazySeq.java:56)
	at clojure.lang.RT.seq(RT.java:440)
	at clojure.lang.RT.count(RT.java:509)
	at clojure.lang.Cons.count(Cons.java:47)
	at clojure.lang.Compiler.analyze(Compiler.java:4396)
	... 18 more
Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
	at clojure.lang.RT.seqFrom(RT.java:479)
	at clojure.lang.RT.seq(RT.java:442)
	at clojure.core$seq__4245.invoke(core.clj:105)
	at clojure.core$every_QMARK___5041.invoke(core.clj:1704)
	at clojure.core$fn__5710$psig__5712.invoke(core.clj:2946)
	at clojure.core$map__5053$fn__5055.invoke(core.clj:1762)
	at clojure.lang.LazySeq.sval(LazySeq.java:42)
	... 23 more

два вопроса:

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

б) у вас вменяемый сообщения об ошибках есть или так живете?

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

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

Давай тогда аналог (на clojure подобно будет)

facs = scanl (*) 1 [2 ..]
main = mapM_ print facs

на си. Список формируется в одном месте, печатается в другом. Расход времени:

$ time ./f-ghc-O3 | head -n 10000 > /dev/null
./f-ghc-O3  17,53s user 0,20s system 99% cpu 17,879 total
head -n 10000  0,32s user 0,51s system 4% cpu 17,878 total

Памяти - примерно константно, порядка 1MB.

Вот это:

#include <gmp.h>

int main()
{
    mpz_t cnt, next, prev;
    mpz_init(cnt);
    mpz_init(next);
    mpz_init(prev);
    mpz_set_ui(cnt, 1);
    mpz_set_ui(prev, 1);

    while (1) {
        mpz_mul(next, prev, cnt);
        gmp_printf("%Zd! = %Zd\n", cnt, next);
        mpz_set(prev, next);
        mpz_add_ui(cnt, cnt, 1);
    }

    // mpz_clear(cnt);
    // mpz_clear(next);
    // mpz_clear(prev);
}

не будет аналогом, так как всё в одно месте. Хотя работает в два раза быстрее и ест на порядок меньше памяти.

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

я неленивый, обновил кложуру до самой последней версии:

Exception in thread "main" java.lang.IllegalArgumentException:  recur arg for primitive local: res is not matching primitive, had: Object, needed: long, compiling:(/home/igor/1.cl:1)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6465)
	at clojure.lang.Compiler.analyze(Compiler.java:6265)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6446)
	at clojure.lang.Compiler.analyze(Compiler.java:6265)
	at clojure.lang.Compiler.access$100(Compiler.java:40)
	at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:521)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6458)
	at clojure.lang.Compiler.analyze(Compiler.java:6265)
	at clojure.lang.Compiler.analyze(Compiler.java:6226)
	at clojure.lang.Compiler.eval(Compiler.java:6518)
	at clojure.lang.Compiler.load(Compiler.java:6955)
	at clojure.lang.Compiler.loadFile(Compiler.java:6915)
	at clojure.main$load_script.invoke(main.clj:283)
	at clojure.main$script_opt.invoke(main.clj:343)
	at clojure.main$main.doInvoke(main.clj:427)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.lang.Var.invoke(Var.java:415)
	at clojure.lang.AFn.applyToHelper(AFn.java:161)
	at clojure.lang.Var.applyTo(Var.java:532)
	at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException:  recur arg for primitive local: res is not matching primitive, had: Object, needed: long
	at clojure.lang.Compiler$RecurExpr.emit(Compiler.java:6092)
	at clojure.lang.Compiler$IfExpr.doEmit(Compiler.java:2588)
	at clojure.lang.Compiler$IfExpr.emit(Compiler.java:2547)
	at clojure.lang.Compiler$BodyExpr.emit(Compiler.java:5665)
	at clojure.lang.Compiler$ObjMethod.emitBody(Compiler.java:5384)
	at clojure.lang.Compiler$FnMethod.doEmitPrim(Compiler.java:5153)
	at clojure.lang.Compiler$FnMethod.emit(Compiler.java:5068)
	at clojure.lang.Compiler$FnExpr.emitMethods(Compiler.java:3603)
	at clojure.lang.Compiler$ObjExpr.compile(Compiler.java:4236)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3735)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6456)
	... 19 more

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

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

(sum* 0 1 n)

да. не заметил, что ты опять сразу сделал через одно место

Про хвостовую рекурсию не в курсе? Так и знал.

А у тебя была бы очередная копипаста с циклом?

для нахождения произведения 1..N? да - это более читабельно чем (sum* 1 1 n *))

Ты, видимо, не врубился, что задача sum* совпадает с задачей твоего цикла. Читабельность в порядке.

и эти люди пишут про быдлокод, давая невнятные названия функциям

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

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

Про хвостовую рекурсию не в курсе? Так и знал.

речь не о том вообще

(sum* 1 1 n *)
Читабельность в порядке.

окай, конечно же любой, увидя этот код, сразу скажет, что он делает

У меня хоть именованные сущности в отличии от твоего нереюзабельного копипаста

конечно, любой цикл от 1 до N - это копипаста, не просто похожий код, а именно копипаста

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

да плевать всем на то, что вычисления ленивые,

Говорить «мы» может только человек с глистами.

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

Ты наглядно только показал код в стиле копипаста. Про скорость обработки больших объемов операций я тебе уже разжевывал, но, видимо, ты не проглотил.

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

Вот у тебя в программе действительно для получения одного элемента вычисляется список факториалов «static int r[ MAX_F ];», который висит в памяти, пока приложение не выгрузят

а у тебя жаба в памяти висит, я ж не придираюсь

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

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

всем
Говорить «мы» может только человек с глистами.

вы таки о чем-то своем

ты сам переписывал код

Про скорость обработки больших объемов операций я тебе уже разжевывал

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

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

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

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

прошу таки кода на кложуре

Видимо

(def facs (reductions *' (rest (range))))
(defn main [] (doall (map println facs)) nil)

но java же - 178MB used (и это я ещё пользователь минималистичных _JAVA_OPTIONS).

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

Наоборот, у тебя все повторяется, кроме имен переменных, условия и накапливаемого выражения. Каркас абсолютно одинаков.

гениально, это говорят про функцию из одной строки, это даже не цирк, это «Кащенко»

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

Mакось это ОС. ОС это система близкая к железу. Это тоже перечитай 2 раза. Не, лучше 3, а то опять в луже пойдут пузыри.

не надо свою тупость переносить на других, а посмотри на чем написано _прикладное_ ПО под OS X в большей своей части, просто погугли - Obj-C там, Xcode, все дела

Безграмотный ты наш. Эппл очень активно продвигает инфраструктуру для разработки приложений для своей операционки. Разработанные т.о. приложения выглядят и ведут себя нативно при минимальных усилиях, что очень важно в коммерческой разработке. Хотя, есть много сторонних приложений и на джаве и на других языках. Взять к примеру Aqua Data Studio: вроде работает, но по сравнению с видом и поведением других приложений - небо и земля.

З.Ы. Если не понятно, перечитай 2 раза.

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

просто стало интересно - скормил твой код на несколько строк кложуре:

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

Ritmik
()
Ответ на: комментарий от quasimoto
#include <gmpxx.h>
#include <list>

int main() {
    std::list<mpz_class> l;
    mpz_class n(1);
    for( int i=2 ; i<10000 ; ++i )
        l.emplace(l.begin(), n*=i);
}

на С++, чтоб просто не писать лишний код - 0.038сек

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

Уверен, что если бы паттерн был сложнее, то ты все равно не смог бы вытащить его отдельно для реюза

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

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

рад, что ты догадался сам

wota ★★
()
Ответ на: комментарий от quasimoto
#include <gmpxx.h>
#include <list>

int main() {
    std::list<mpz_class> l;
    mpz_class n(1);
    for( mpz_class i=2 ; i<10000 ; ++i )
        l.emplace(l.begin(), n*=i);
}

никакой разницы с вариантом с int, все те же 0.036-0.038сек, памяти 67Мб занимает

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

Да ты что?! Правда?!

да - ты налажал

Как ты я уже не смогу налажать. Сравни скорость с указанием типов и без них.
Ты пример выражения: чем меньше знаний, тем больше чсв.

Ritmik
()
Ответ на: комментарий от wota
#include <gmpxx.h>
#include <list>

int main() {
    std::list<mpz_class> l;
    mpz_class n(1);
    for( mpz_class i=2 ; i<10000 ; ++i )
	    l.emplace_back(n*=i);
}

0.031сек, и более правильно

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

Как ты я уже не смогу налажать. Сравни скорость с указанием типов и без них.

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

Ты пример выражения: чем меньше знаний, тем больше чсв.

переход на личности? вы такие одинаковые

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

Как ты я уже не смогу налажать. Сравни скорость с указанием типов и без них.

написать нерабочий код...

То есть по теме опять нечего сказать. Видимо не смог сравнить.

Если ты не можешь скомпилить простой пример из нескольких строк, то это твои половые проблемы. Я тебе уже советовал спрашивать нормально с текстом кода и ошибкой. Видимо ты даже в любимом своем деле копипасты не силен и не так перенес мой код.

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

Я тебе уже советовал спрашивать нормально с текстом кода и ошибкой.

я б советовал протереть глаза - выше тебе полный дамп ошибок от двух версий кложуры (1.1 и 1.4), и что забавно - они весьма сильно отличаются, а код твой - 1:1 отсюда:

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

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

Уверен, что если бы паттерн был сложнее, то ты все равно не смог бы вытащить его отдельно для реюза

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

Мог бы - сделал. На простых задачах у тебя реюз должен было получиться просто. А ты даже там не осилил.


посмотри на чем написано _прикладное_ ПО под OS X в большей своей части, просто погугли - Obj-C там, Xcode, все дела

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

Тогда к чему был твой высер про «прикладное_ ПО под OS X»? Если ты понимал бы это, то не приводил бы этот пример в качестве аргумента.

рад, что ты догадался сам

Тут вообще без комментарий.

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

не вижу смысла это делать

Мог бы - сделал.

можешь попрыгать на одной ноге, снять видео и выложить на ютуб? сделаешь?

А низкоуровневые языки могут быть только использованы для близких к железу задач.
Тогда к чему был твой высер про «прикладное_ ПО под OS X»?

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

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

Семейства языков Си" не существует

Молодец, ты прозрел.

ЩИТО?

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

не вижу смысла это делать

Мог бы - сделал.

можешь попрыгать на одной ноге, снять видео и выложить на ютуб? сделаешь?

Пойми, если бы код в твоих функциях подсчета количества до m и нахождения max до m был бы больше, то ты все равно бы не смог вынести его в общую функцию из-за способа получения последовательности, меньшей m. Не упирайся, а просто подумай над этим. Потом посмотри на способ, используемый в моих решениях. Сравни. Не требую от тебя признать это, т.к. это видимо для тебя смерти подобно, т.к. ты тут уже наизворачивался как мог. О результатах размышлений можешь не писать сюда.

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

Clojure - не лисп.

Можешь раскрыть свою мысль? Если возможно, опираясь в критике на пункты http://clojure.org/lisps.

Классические cons-ы заменены на что-то с неопределенной стратегией оптимизации.

Аргументы у функций map-ом. Что при реализации принципа «программа которая пишет программу» несколько утяжеляют процесс лишними конструкторами нарушающими единообразие.

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

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

я уже писал, напишу еще раз - я _за_ реюз, но без всяких надуманных «если бы», я не буду портить код ради ничего, давай задачу, где в С действительно нельзя вынести общий код, а цикл 1..N с разными переменными и условиями - не общий код, ну это ж очевидно

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

на С++

Это не то. Нужно чтобы твой бинарник просто писал факториалы в stdout, то есть бесконечно долго, а выбирать нужные можно с помощью head / tail и т.п. Причём получение последовательности натуральных чисел, последовательности факториалов и печать этой последовательности должны быть независимы, то есть должна быть проведена декомпозиция. std::list это данные, то есть конечные по своей природе, тут нужны коданные, то есть бесконечные данные, то есть потоки, генераторы, итераторы и т.п. В C++ нужно писать классы ISeq (абстрактный), RangeSeq и FacSeq с нужными конструкторами и методом next, а также классы MapSeq, FoldSeq и т.п., которые принимают функции (как раз лямбды пригодятся), объекты абстрактного ISeq и делают отображения любых последовательностей-потомков ISeq оперируя их методами next с помощью переданных им функций. Всё это может разрастись до сотен и тысяч строк, чтобы в итоге писать

    FacSeq facs;

    while (true)
        gmp_printf("%Zd\n", facs.next());

или

    FacSeq facs;
    MapSeq map_gmp_print([] (mpz_t n) { gmp_printf("%Zd\n", n) });
    map_gmp_print.apply(facs);

FacSeq можно написать в терминах RangeSeq и FoldSeq. Или вот он сам по себе:

class FacSeq : public ISeq {
    mpz_t cnt, nxt, prv;
  public:
    FacSeq() {
        mpz_init(cnt);
        mpz_init(nxt);
        mpz_init(prv);
        clear();
    }

    ~FacSeq() {
        mpz_clear(cnt);
        mpz_clear(nxt);
        mpz_clear(prv);
    }

    void clear() {
        mpz_set_ui(cnt, 1);
        mpz_set_ui(prv, 1);
    }

    mpz_ptr next() {
        mpz_mul(nxt, prv, cnt);
        mpz_set(prv, nxt);
        mpz_add_ui(cnt, cnt, 1);
        return &nxt[0];
    }
};

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

Вот в Haskell / Clojure [1 ..] / (rest (range)) это генератор бесконечного списка [1, 2, 3, ...], scanl / reductions это функция которая из одного бесконечного списка делает другой, но не полным проходом по входу и возвращением выхода (что невозможно), а итеративно, то есть на уровне рекуррентных соотношений для элементов потока, mapM_ print / doall (map println также итеративно отображает элементы потока в действия IO, которые итеративно же выполняются. В итоге, в случае коданных / потоков / генераторов / итераторов, память тратится константно, хотя выглядит как работа с бесконечными списками вида reduce . mapAgain . map . genList.

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

Clojure - не лисп.

Можешь раскрыть свою мысль? Если возможно, опираясь в критике на пункты http://clojure.org/lisps.

Классические cons-ы заменены на что-то с неопределенной стратегией оптимизации.

Cons остался для списков. Появился conj, который работает для всех видов коллекций. Например, для списков от добавляет элемент в начало, для массивов - в конец. Т.е. иногда можно писать коллекционезависиммый алгоритм.

Аргументы у функций map-ом. Что при реализации принципа «программа которая пишет программу» несколько утяжеляют процесс лишними конструкторами нарушающими единообразие.

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

Все от лиспа осталось. Добавили то, чего так не хватало:
1. лисп остался
2. опциональгная ленивость, коллекции
3. прекрасная интеграцию с могучей платформой,
4. чистота функций и нативных коллекций
5. киллер фича: механизмы для координации доступа к данным в многопоточных приложениях

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

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

Опять просить тебя дать код?!! Я еле этот получил. Судя по всему, ты не понял, что я имею в виду.

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

Нужно чтобы твой бинарник просто писал факториалы в stdout, то есть бесконечно долго, а выбирать нужные можно с помощью head / tail и т.п

еще проще:

#include <gmpxx.h>
#include <iostream>
#include <list>

int main() {
    mpz_class n(1), i(1);
    while(1)
	    std::cout << (n*=i++) << '\n';
}
~$ time ./a.out | head -n 10000 > /dev/null

real	0m2.869s
user	0m2.972s
sys	0m0.048s

и повторюсь - практически все время это вывод и форматирование, а не вычисление, а вот в варианте на хаскеле очевидно уже нет

Причём получение последовательности натуральных чисел, последовательности факториалов и печать этой последовательности должны быть независимы

надуманные ограничения, опять, и непонятно зачем, но даже с ними код будет выполняться дольше «аж» на сотые, если не тысячные секунды дольше (в данном случае), как было в примере с std::list

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

Опять просить тебя дать код?!!
Я еле этот получил.

да ладно, просто ты постоянно выдвигал новые требования, и все что смог - придраться к «копипасте» в виде использования циклов в разных задачах

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

Clojure создавался с учетом недостатков лиспов, особенно CL.

Или наоборот создали по принципу «я так вижу», а потом постфактум объявив что CL полон недостатков в первую очередь потому что он не Clojure.

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

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

Clojure создавался с учетом недостатков лиспов, особенно CL.

Или наоборот создали по принципу «я так вижу», а потом постфактум объявив что CL полон недостатков в первую очередь потому что он не Clojure.

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

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

gmpxx

mpz_class n(1), i(1);

std::cout << (n*=i++) << '\n';

Вот это хорошо. Лучше чем код на Си тут.

надуманные ограничения, опять, и непонятно зачем

Это не ограничения, а просьба. То есть «так надо». Функции C/C++ сами по себе дают дополнительную свободу для проведения декомпозиции. Никто же не спорит что все задачи можно решить на языке _без_ функций. Точно так же ФВП дают дополнительную свободу, анонимные функции и замыкания - тоже, ленивые данные - тоже. Я прошу продемонстрировать именно эти дополнительные свободы на С++, дело же не в факториалах. При этом примерно представляю как это будет выглядеть, вербозно, да.

как было в примере с std::list

В случае с std::list ничего не было, так как std::list тут ни при чём.

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

а на С++ - 196Кб для последнего варианта

А на С++ совсем другая программа. Если переписать с генераторами, то тоже будет быстрее и тоньше, конечно, на то он и C++, но писать будешь не одну строчку а over 500.

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

Язык clojure создан в 2007 и соответствует спекам clojure.

Т.е. лисп развивается полной ломкой совместимости.

А js использует C-шный синтаксис для арифметики и if-ов, а java вобще сперла new и классы из плюсов. И они полностью сломали совместимость, вот гадство. Вот clojure по отношению к лиспу примерно такого же уровня явление. А лисп живет вполне сам по себе без больших ломок.

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

Clojure создавался с учетом недостатков лиспов, особенно CL.

Или наоборот создали по принципу «я так вижу», а потом постфактум объявив что CL полон недостатков в первую очередь потому что он не Clojure.

Я тебя понимаю. Сам испытывал точно такие же чувства и мысли при первом знакомстве с clojure после CL. Это от незнания матчасти clojure.

Ввдение протоколов как призрака CLOS,

отсутствие сигнального протокола,

Этого нет. Но это же чисто специфика CL, а не всех лиспов, не правда ли?

непонятки с shadow говорят,

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

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

Ты еще не перечислил, что тебе не понравилось в clojure? Так вот почитать чьи-то впечатления это не то.

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

Ввдение протоколов как призрака CLOS

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

ИМХО если писать на clojure без требования взаимодействия с джавой, то ОО вообще не нужен.

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