LINUX.ORG.RU
ФорумTalks

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

 , ,


7

7

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

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

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

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

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

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

★★★★★

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

Не изменился, а появился. Clojure создан был в 2007.

Т.е. он соответствует спекам 1963 года.
Как интересно!

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

А в чем проблема разработки вэб приложений на схеме, common lisp-е, clojure?

Нет библиотек

Правда? Ни одной? чудеса.

и программистов.

А сколько платите?

Нужна работа с вэб-сервисами

Писал на лиспе массу SOAP-сервисов, ЧЯДНТ?

работа с БД и желательно не на уровне ODBC/JDBC а какой-то persistence layer.

Ты про ORM? OMG! За что ты себя так не любишь?

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

Не изменился, а появился. Clojure создан был в 2007.

Т.е. он соответствует спекам 1963 года.
Как интересно!

Язык clojure создан в 2007 и соответствует спекам clojure. А вы про спеки какого языка?

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

Дели в тривиальном кольце.

это которое из одного нуля?

Ещё, говорят, в wheels можно, а они включают все коммутативные кольца, так что...

а ещё говорят, что в моськве кур доят.

...

нет.

Любой алгоритм выдаст мусор, если его кормить мусором. Я надеюсь это очевидно.

Нет.

почему?

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

Так и запишем: «многопоточно код использовать нельзя».

можно. нельзя в первый раз запустить инициализацию в несколько потоков. что в этом плохого?

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

это которое из одного нуля?

Да.

почему?

Потому что [в языке] не должно быть возможности кормить алгоритм мусором.

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

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

для меня это было странным и нудным, но мне было интересно - что в ЭТОМ нашли интересного математики.

А могло бы быть нужным, кстати.

ну... есть такой анек про эстонца и ворону - не пригодилась.

А вот за всякие действительно достойные быть ЯП широкого применения lisp'ы обидно.

почему? ты вот сам как-то неправильно предложения строишь. (:

глядишь, и на C++ писать будешь функционально с помощью (:

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

Так и запишем: «многопоточно код использовать нельзя».

можно. нельзя в первый раз запустить инициализацию в несколько потоков. что в этом плохого?

Да не, ничего особенного. Просто заметил, что в таком простом примере уже такие ограничения. А вообще это не важно. мне нужны были решения на Си, которые автор никак не может предъявить.

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

после

int main() {

напиши fact(0);

и не мучай себя и окружающих.

Этот код - очень хороший дробовик =)

сдуру и йух можно сломать(ц)

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

Отметьте подходящие варианты:

  • всё так и есть.

    $fact=function($x){return array_reduce(range(1,$x), function($v,$w){$v*=$w;return $v;},1);}; $fact_list=function($x,$f){return array_map($f,range(1,$x));}; echo $fact(5); echo var_export($fact_list(5,$fact));

    я бы это записал так:
    #!/usr/bin/php
    <?php
    $fact=function($x)
    {
    	return array_reduce(
    		range(1,$x),
    		function($v,$w)
    		{
    			$v*=$w;
    			return $v;
    		},
    		1
    	);
    };
    
    $fact_list=function($x,$f)
    {
    	return array_map(
    		$f,
    		range(1,$x)
    	);
    };
    
    echo $fact(5);
    echo var_export($fact_list(5,$fact));
    ?>
    
    ну и кто из нас пишет «простыню»?

    императивный код на пхп (N):

    чем мой код не угодил?

    повторю:

    #!/usr/bin/php
    <?php
    $n = 2;
    $m = 5;
    while($n <= $m)
    {
    	$x = $n++;
    	for($f = 1; $x; $x--)
    		$f *= $x;
    	$a[] = $f;
    }
    print_r($a);
    ?>
    
    сравни с
    $fact=function($x){
      $f=1;
      foreach(range($f,$x) as $i){
        $f*=$i;}
      return $f;};
    
    $fact_list=function($x){
      $f=1;$a=array();
      foreach(range($f,$x) as $i){
        $f*=$i;
        $a[]=$f;}
      return $a;};
    
    echo $fact(5);
    echo var_export($fact_list(5));
    я ещё и придраться могу «оно не работает!» ибо обвязку ты забыл, как и sha-bang. Но даже с ними мой код короче и проще. Такие дела.

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

ты все еще не скопипастил примеры, ты чего-то боишься?

Странная логика. Я свои примеры привел и не заставлял тебя что-то там подставить, скопипастить откуда то. Скинь ссылку на полное описание функций по работе с последовательностями, которые я просил. Их нет. Ты этого по какой-то причине сделать их не можешь уже сколько времени. Вывод очевиден.

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

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

Во «времена Shell и С++» он мог бы стать популярным, но появился жемчужный перл, настоящий прорыв своего времени, сравнимый с прорывом asm -> lisp, asm -> fortran, asm -> basic: никаких тебе глупые ограничений на каждом шагу, свобода и тимтоуди, динамическая типизация, ооп (вау - это как есл бы анонимные функции появились только вчера и уже их бы включили в С++, только в сто раз круче), регулярными выражениями искарообки, более менее привычый синтаксис, замашка на декларативность (и по сравнению со своими современниками все это именно так и было). Затем в каменный век человеческого бытия стремительно ворвался интернет, а с ним статичный html, который хоть как-нибудь нужно было _срочно_ научиться скриптовать именно «за 24 часа» -> появился php. Очень правильное, соответствующее духу времени решение - простой, доступный, искаробочный (вставил в html-разметку и забыл) язык для написания домашних страниц, под его натиском из веба начал уходить перл (именно в силу популяризации пхп - не руби и не питона) с характерным perl-бородачи vs php-школокуны, что «было уже в веках» (asm vs C, fortran vs pascal, C vs cpp). Начинается эпоха экспериментов, проб и ошибок - тут появляется java со своими апплетами в каждую щель и прочим запросом интерпрайза, уставшего это илитного задротства байтиков и гимнастики мемликов. А тем временем _никакого_ современного языка (кроме реально матанового ML и ооочень мебленного и примитивного смолтолка) нет, ну то есть CL появился только в 1994-м и сертифицировался для оборонки, ынтерпрайз испугался скобок и запилил схемку с си-синтаксисом и модным, гламурно-трендовым ооп. Одну такую схемку впихнули для реализациии задач документаоборота и прочих клент-банков (java), другую в браузер (javascript) - эпоха на столько была бесчеловечно трендовая, что маркетоидность проникала даже в названия языков, логичное ее завершение - бум доткомов привел даже к серьезному экономическому спаду в одной известной сверхдержаве с постэффектом холодного душа из серной кислоты похлеще AI-winter: теперь лолоснули тунцов не только матанозадроты-футурологи, а и обычные прохаванные комерсы с небыдлом. Серьезно начали опять вкладывать в интернет-бизнес только через 3-4 (четыре!!) года - в 2005м. Вплоть до 2004-го все компании занимались «десктопом» и джава была тормозным неюзабельным УГ для инопланетных масштабов обладающего ресурсами ынтерпрайза. 2003-2006 C++ и джаву очень теснили угадайтекто - VB и Delphi - последний умер и возродился фениксом в C#. Где-то в году 2003м, помню, среди продвинутых хакиров поползли разговоры о питоне - нужна была замена всем трем языкам (vb, мертвому дельфи и надвигающемуся прибитому к одной оси, как и оба предыдущих кандидата C#), обладающая высокой степенью читабельности и юзерфрендли, но с более продуманным дизайном, чем VB и зачатками функционального стиля, этакий лисп для масс. Им и стал питон. Закономерность развития и популяризация языков _абсолютно_ логична в исторической ретроспективе. Единственным «выскочкой» стал руби: по какому-то случайному стечению обстоятельств Rails написали именно на нем, а не на питоне, до Rails и MVC руби никому не был нужен, а если бы раньше вышла джанга, то сейчас им пользовались бы на уровне Io.

Расскажи мне, где во всей этой истории место для лиспа?

Чтобы стать популярным сейчас ты должен предложить что-то ну ооочень крутое, в сравнении с тем же руби и питоном. Можно с уверенностью сказать, что этого не случится до тех пор, пока преимущества лиспа как языка не станут способствовать решению повседневных задач, а его недостатки не получится исправить или смириться в силу каких-то там потенциальных мега киллер-фич. Готов предположить, что кроме как для решения задач, связанных с созданием новых языков - e(DSL) в прототипном обкаточном варианте (DSL без «e» после завершения фазы прототпирования пишутся на «обычных» системных языках, потому что производительность) Lisp и не понадобится больше нигде и никогда. И то, до тех пор, пока не запилят какой-нибудь нормальные N2 со статической типизацией, пригодной для _легкого_ создания произвольных DSL. Lisp будет необходим и востребован (по крайней мере в блажайшие лет шесть) в тех областях критичных к требованию быстрого прототипирования, относительно быстрой скорости работы этих прототипов для _сложных_ херовоизученных или слабодетерминированных задач, в которых может внезапно понадобится выпрыгивающий из монады пролог или какая-то обновленная система исчисления высказываний в семиструннов варианте вселенной + тайпчекеры на любой вкус. Беда в другом - популярные лиспы хоть и лучше других языков, но все-таки _хреново_ подходят и для этих задач. Метапрограммирование будет развиваться, и я думаю, на базе лиспов с усложненной или переосмысленной семантикой и развесистем суперфичастым райнтаймом с глубочайшей, доходящей до уровня шизофрении терминальной стадии интроспекциией.

если бы его не превратили в матан.

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

В некоторых случаях функциональщина вполне полезна и оправдана.

Из современных диалектов лиспа шаг в сторону функциональщины в нынешнем понимании сего термина сделал лишь Clojure. Scheme это такой лиспопетон наших сирых дней, а CL - плюсы от лиспов на метане и прочих стероидах.

// все случайные совпадения рецептов веществ den73 для написания поста действительно случайны и лицензированы минздравом коммон ли^W сенс

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

Нет в C# метода String.length(), Length - это Property

Вопрос не по теме, но: зачем эти лишние сущности?

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

class Test
{
	public int Property { get; private set; }
}
чем такой:
class Test
{
	private int property;

	private void setProperty(int value) {
		property = value;
	}

	public int getProperty() {
		return property;
	}
}
А вот property указываемые явно - довольно спорная вещь, в геттер и сеттер можно засунуть произвольную логику и это может запутать код.

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

нет. НЕ очевидно. Зачем оборачивать x+y в функцию, если можно записать x+y в цикле?

/0

в рамках ФП - да.

Потому что может не быть заранее известно, что будет именно x+y, а не x*y или x-y, а просто представлено формальным параметром или замыканием,

вот и напишу x*y или x-y. Компилятору будет проще.

Как раз объявление функции меня не интересует, а интересует тело функции.

т.е. обвинение в «простыне» ты не поддерживаешь?

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

Конкретный такой ответ. Подробный и с примерами.

подробно и с примерами мы уже разобрали вычисление факториала. Невооруженным глазом видно, что ФП здесь === унылое говно. Будут другие примеры?

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

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

ты врешь:

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

кинь ссылку на полное описание функций по работе с последовательностями, которые я просил. Их нет

ты врешь:

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

Вывод очевиден.

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

// специально для Ritmik, чтоб были константы (мало имеет общего с началной задачей, но ладно)
int* fact_all(){
  static int r[ MAX_F ];
  // специально для Ritmik, он против glib, но очевидно за pthread
  if( !*r[MAX_F-1] ) for( int i=0 ; i<MAX_F ; r[i] = i > 1 ? r[i-1]*(i+1) : 1, ++i );
  return r;
}

int fact( int n ) {
  return fact_all()[n-1];
}

void factorials( int* a, int m, int n ) {
  memcpy( a, fact_all()+m-1, (n-m+1)*sizeof*r );
}

// специально для Ritmik - функция из одной строки
int fact_count( int m ) {
    int c=0; for( ; fact(c+1)<m ; ++c ); 
    return c;
}

// специально для Ritmik - функция из одной строки
int fact_max( int m ) {
    int r=0; for( int i=1 ; fact(i)<m ; r=fact(i), ++i ); 
    return r;
}

// специально для Ritmik - функция из одной строки
void fact_n( int* a, int n ) {
   factorials( a, 1, n );
}

// специально для Ritmik - функция из одной строки
void fact_m_n( int* a, int m, int n ) {
   factorials( a, m, n ); // быссмысленно, но специально для Ritmik, он так любит
}

А ТЕПЕРЬ БОЛЬШАЯ ПРОСЬБА - если у тебя есть претензии, пиши их сразу, обдумай все, чтоб опять через пару страниц не было - «а теперь опять мне покажи этот код», «а почему тебе лень это делать», «вывод очевиден» и пр.

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

«Семейства языков Си» не существует. А асли вопрос «это Си или Си++» кажется тебе странным, у тебя проблемы.

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

Не ты ли считал факториал вложенными циклами?

я. а что? тебя раздражает O(N*M) что-ли? Ну ежели ты такой экономный, то

#include <stdio.h>
#define N 2
#define M 5
int main()
{
	int y;
	int n;
	int a[256];
	int *sp = a;
	for(n = N; n <= M; n++)
	{
		int x = n;
		for(y = 1; x; x--)
			y *= x;
		*sp++ = y;
	}
	sp = a;
	for(n = N; n <= M; n++)
		printf("%d! = %d\n", n, *sp++);
	return 0;
}
080482f0 <main>:
 80482f0:       55                      push   ebp
 80482f1:       89 e5                   mov    ebp,esp
 80482f3:       53                      push   ebx
 80482f4:       83 e4 f0                and    esp,0xfffffff0
 80482f7:       81 ec 10 04 00 00       sub    esp,0x410
 80482fd:       b9 02 00 00 00          mov    ecx,0x2
 8048302:       89 c8                   mov    eax,ecx
 8048304:       ba 01 00 00 00          mov    edx,0x1
 8048309:       8d b4 26 00 00 00 00    lea    esi,[esi+eiz*1+0x0]
 8048310:       0f af d0                imul   edx,eax
 8048313:       48                      dec    eax
 8048314:       75 fa                   jne    8048310 <main+0x20>
 8048316:       89 54 8c 08             mov    DWORD PTR [esp+ecx*4+0x8],edx
 804831a:       41                      inc    ecx
 804831b:       83 f9 06                cmp    ecx,0x6
 804831e:       75 e2                   jne    8048302 <main+0x12>
 8048320:       bb 02 00 00 00          mov    ebx,0x2
 8048325:       8b 44 9c 08             mov    eax,DWORD PTR [esp+ebx*4+0x8]
 8048329:       89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 804832d:       89 5c 24 04             mov    DWORD PTR [esp+0x4],ebx
 8048331:       c7 04 24 50 85 04 08    mov    DWORD PTR [esp],0x8048550
 8048338:       e8 83 ff ff ff          call   80482c0 <printf@plt>
 804833d:       43                      inc    ebx
 804833e:       83 fb 06                cmp    ebx,0x6
 8048341:       75 e2                   jne    8048325 <main+0x35>
 8048343:       31 c0                   xor    eax,eax
 8048345:       8b 5d fc                mov    ebx,DWORD PTR [ebp-0x4]
 8048348:       c9                      leave  
 8048349:       c3                      ret    
давай сравним с твоим lisp'ом?

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

Ну например:

Множество «компы» состоит не только и не столько из писюков, серверов и ынтерпрайза. Есть ещё огромный, в разы больший, между прочим, мир, называемый embedded.

lisp, как бы это странно не звучало, неплохо подошёл бы для этого самого embedded. Не всегда и не везде, конечно, но был бы вполне годным. Просто в силу того, что на нём проще и точнее (с меньшей вероятностью оставить кучу дыр и необработанных состояний, скажем так) реализуется задуманная логика работы железки. Часто это очень важно. Но из-за того, что никто из этой области и не думал о том, что ФП не матан, а всего лишь прикладуха, задача которой не в последнюю очередь - работать быстро и давать маленький код, lisp не получил нормальных компиляторов для всевозможных платформ от 8-миразрядных однокристаллок до всяких 64-битных SoC.

Если бы об этом применении ФП задумались, то к моменту появления того же, без сомнения достойного перла, уже существовало бы большое количество быстрого лиспового кода со всей системной требухой от какого-нибудь "(set_gpio_pin 1)" до полноценного IO для всех возможных способов этого IO. И лисп не был бы «белой вороной» для обобщённого программиста того времени.

На лиспе реально _удобно_ писать софт для однокристалок. При этом само собой получается, что в этом софте практически отсутствуют непредусмотренное поведение, которое практически всегда бывает при написании на C. Что сильно экономит время разработки фирмвари. Я давно ещё этой фишкой несколько раз пользовался, писал софтину на lisp (кстати, оно у меня правильно работало сразу, а не после часов отладки как обычно с C/asm) а потом переводил вручную в код на C. Я бы и сейчас не отказался от lisp для этого, но отсутствие годных инструментов и необходимость делать двойную работу действительно делает лисп неюзабельным.

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

дык, до 5.3 с его условно-нормальным ФП все так писали, когда не могли избежать. Оказывалось, что насдрочиь кирпич монолитного ro кода методом копипаста — проще и быстрей, чем бороться с недофичами языка, особенно учитывая его область применения.

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

А в чем проблема разработки вэб приложений на схеме, common lisp-е, clojure?

технических нет, есть инфраструктурные и организационные

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

тебя раздражает O(N*M) что-ли?

Просто если делать сразу список факториалов, то следующий в нём элемент это произведение предыдущего на счётчик:

#include <stdio.h>
#include <assert.h>

int main()
{
#   define N 1
#   define M 20
#   define MAX_M 20

    assert(N > 0 && M <= MAX_M);

    // * [n .. m]
    const unsigned n = N, m = M;

    // * [n! .. m!]
    unsigned long long facs[MAX_M];

    // * * facs[0] = n!
    facs[0] = 1; {
        unsigned tmp = n;
        for (; tmp > 0; --tmp) facs[0] *= tmp;
    }

    // * * folding the rest
    for(unsigned i = n + 1; i <= m; ++i)
        facs[i - n] = i * facs[i - n - 1];

    // * print it out
    for(unsigned i = n; i <= m; ++i)
        printf("%d! = %llu\n", i, facs[i - n]);
}

аналогично

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

(программа которая бесконечно долго печатает сколь угодно большие факториалы).

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

Потому что может не быть заранее известно, что будет именно x+y, а не x*y или x-y, а просто представлено формальным параметром или замыканием,

вот и напишу x*y или x-y. Компилятору будет проще.

Т.е. ты будешь дублировать одинаковую логику каждый раз.

Как раз объявление функции меня не интересует, а интересует тело функции.

т.е. обвинение в «простыне» ты не поддерживаешь?

Конечно поддерживаю. Но проблема не только в «простыне».

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

Конкретный такой ответ. Подробный и с примерами.

подробно и с примерами мы уже разобрали вычисление факториала. Невооруженным глазом видно, что ФП здесь === унылое говно. Будут другие примеры?

Можно ссылку или какие-нибудь примеры? Или как обычно?

Ritmik
()
Ответ на: комментарий от drBatty
#include <stdio.h>
#include <stdlib.h>
#define N 5

int *
mapIntArray(int *a, int n, int (*func)(int)) {
  int *tmp;
  int i;

  tmp = malloc(sizeof(int)*n);

  for (i = 0; i < n; ++i) {
    tmp[i] = func(a[i]);
  }
  return tmp;
}

void
printIntArray(int *a, int n) {
  int i;
  for (i = 0; i < n; ++i) {
    printf("%d ", a[i]);
  }
  printf("\n");
}

int
plusOne(int a) {
  return a + 1;
}

int
plusTwo(int a) {
  return a + 2;
}


int
plusX(int x, int a) {
  return a + x;
}

int
main(void) {
  int a[N] = {1,2,3,4,5};
  int *res;

  printIntArray(a, N);

  res = mapIntArray(a, N, plusOne);
  printIntArray(res, N);
  free(res);

  res = mapIntArray(a, N, plusTwo);
  printIntArray(res, N);
  free(res);

  // а с лямбдами можно было всё сделать без лишней писанины
  // res = mapIntArray(a, N, func(X) -> X + 1)

  // такая конструкция тоже не пройдёт
  // res = mapIntArray(a, N, plusX(4));



  return 0;
}

Где будешь x*y писать?

Теперь сравни с haskell:

> map (\x -> x + 1) [1,2,3,4,5]
[2,3,4,5,6]
> map (\x -> x + 2) [1,2,3,4,5]
[3,4,5,6,7]
> let plusX x a = a + x
> map (plusX 54) [1,2,3,4,5]
[55,56,57,58,59]

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

> А в чем проблема разработки вэб приложений на схеме, common lisp-е, clojure?

Нет библиотек и программистов.

Библиотеки есть. С персоналом напряженка, да. С другой стороны, их много и не требуется, достаточно обеспечить нормальную «смену поколений».

Нужна ... авторизация в ActiveDirectory,

Для веба задача нетипичная.

работа с БД и желательно не на уровне ODBC/JDBC а какой-то persistence layer.

Кто мешает? Для CL точно есть mysql, pg, mongo, и, кстати, ldap

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

// а с лямбдами можно было всё сделать без лишней писанины

а «на С» было бы так:

int main() {
  int n = 5, p = 4;

  int a[n] = {1,2,3,4,5};
  int b[n], i;
  for( i=0; i<n ; ++i ) b[i]=a[i]+p;

:)

и именно так реальный код и пишется в сишных библиотеках - простой цикл, быстро, просто, очевидно

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

Кто мешает? Для CL точно есть mysql, pg, mongo, и, кстати, ldap

там часть ссылок дохлая, часть - заброшенные поделки на google code и пр., помнится Archimag негативно высказывался про CLiki и качество проектов указанных в нем

wota ★★
()
Ответ на: комментарий от wota
// специально для Ritmik, чтоб были константы (мало имеет общего с началной задачей, но ладно)
int* fact_all(){
  static int r[ MAX_F ];
  // специально для Ritmik, он против glib, но очевидно за pthread
  if( !*r[MAX_F-1] ) for( int i=0 ; i<MAX_F ; r[i] = i > 1 ? r[i-1]*(i+1) : 1, ++i );
  return r;
}

int fact( int n ) {
  return fact_all()[n-1];
}

void factorials( int* a, int m, int n ) {
  memcpy( a, fact_all()+m-1, (n-m+1)*sizeof*r );
}

// специально для Ritmik - функция из одной строки
int fact_count( int m ) {
    int c=0; for( ; fact(c+1)<m ; ++c ); 
    return c;
}

// специально для Ritmik - функция из одной строки
int fact_max( int m ) {
    int r=0; for( int i=1 ; fact(i)<m ; r=fact(i), ++i ); 
    return r;
}

// специально для Ritmik - функция из одной строки
void fact_n( int* a, int n ) {
   factorials( a, 1, n );
}

// специально для Ritmik - функция из одной строки
void fact_m_n( int* a, int m, int n ) {
   factorials( a, m, n ); // быссмысленно, но специально для Ritmik, он так любит
}

А ТЕПЕРЬ БОЛЬШАЯ ПРОСЬБА - если у тебя есть претензии, пиши их сразу

Комментарии к каждой функциии не имеют отношение к коду. Если ты так же делаешь в своих проектах, то ахтунг.

Претензии:

1.Создается массив r[ MAX_F ] и занимает память в независимости от того, нужен он дальше или нет. Если я хочу получить последовательность fact_m_n(a, 100, 101), то мне нафиг не нужны остальные элементы.

2. Функции fact_n и fact_m_n не возвращают новую последовательность, а модифицируют переданный. У меня возвращался новый. Необходимо модифицировать.

3. Смотрим алгоритмы функций fact_count и fact_max (остальные функции согласно пункту #2 не готовы): код не реюзабелен. В моем случае:

;; сколько элементов последовательности n! меньше числа m
(defn min-n-size-fact [m]
  (count (take-while (fn [fact] (< fact m)) (lazy-fact 1 1))))

;; какой самый максимальный факториал до числа m
(defn max-fact-befor [m]
  (last (take-while (fn [fact] (< fact m)) (lazy-fact 1 1))))

Для реюза достаточно общий код вынести в min-n-fact:

;; список элементов последовательности n! меньше числа m
(defn min-n-fact [m]
  (take-while (fn [fact] (< fact m)) (lazy-fact 1 1)))

;; сколько элементов последовательности n! меньше числа m
(defn min-n-size-fact [m]
  (count (min-n-fact m)))

;; какой самый максимальный факториал до числа m
(defn max-fact-befor [m]
  (last (min-n-fact m)))
Ritmik
()
Ответ на: комментарий от Ritmik

Комментарии к каждой функциии не имеют отношение к коду. Если ты так же делаешь в своих проектах, то ахтунг.

они исключительно для тебя - чтоб пресечь претензии вроде «а раньше было не так»

1.Создается массив r[ MAX_F ] и занимает память в независимости от того, нужен он дальше или нет.

спасибо - рассмешил, человек пишущий на Clojure (JVM) вычисление факторила придирается к использованию «лишних» нескольких десятков байт

Функции fact_n и fact_m_n не возвращают новую последовательность, а модифицируют переданный. У меня возвращался новый. Необходимо модифицировать.

нет - не надо, объясню популярно почему - это оптимизация, которая тебе не доступна, я могу переиспользовать один и тот же буфер, я могу создать буфер на стеке, я могу просто использовать malloc/free - мое решение универсально и оптимально

Для реюза достаточно общий код вынести в min-n-fact:

жжешь:

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

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

g_list_foreach

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

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

ну и кто из нас пишет «простыню»?

Кто две простые строчки разосрал на пол-экрана? Ты разосрал. Еще б картинки туда вставил.

Ты хотел видеть подстрочник лиспокода на пхп, это он и есть, в чем вопрос?

чем мой код не угодил?

А ты считаешь это нормальным, вычислять факториал за N^2? Тогда ничем. Если не придираться к читабельности, но тут у каждого свой вкус.

Но даже с ними мой код короче и проще. Такие дела.

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

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

поделка там, если судить по статусу alpha, только CL-LDAP, в нашем контексте подойдет.

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

а) реюзабелный код не надо модифицировать

речь о реюзе lazy-fact же. Если так сделать и вызывать min-n-fact, которая вызывает lazy-fact, степень реюза lazy-fact будет больше или меньше?

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

речь о реюзе lazy-fact же.

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

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

Комментарии к каждой функциии не имеют отношение к коду. Если ты так же делаешь в своих проектах, то ахтунг.

они исключительно для тебя - чтоб пресечь претензии вроде «а раньше было не так»

Прочитай что ли свои комментарии к функциям.

1.Создается массив r[ MAX_F ] и занимает память в независимости от того, нужен он дальше или нет.

спасибо - рассмешил, человек пишущий на Clojure (JVM) вычисление факторила придирается к использованию «лишних» нескольких десятков байт

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

Функции fact_n и fact_m_n не возвращают новую последовательность, а модифицируют переданный. У меня возвращался новый. Необходимо модифицировать.

нет - не надо, объясню популярно почему - это оптимизация, которая тебе не доступна, я могу переиспользовать один и тот же буфер, я могу создать буфер на стеке, я могу просто использовать malloc/free - мое решение универсально и оптимально

Тебе каждый раз перед вызовом функции приходится создавать самостоятельно массив для хранения результата? Т.е. здесь тоже не можем избавиться от копипасты. Ок.

Для реюза достаточно общий код вынести в min-n-fact:

а) реюзабелный код не надо модифицировать

У тебя код двух функций

int fact_count( int m ) {
    int c=0; for( ; fact(c+1)<m ; ++c ); 
    return c;
}

int fact_max( int m ) {
    int r=0; for( int i=1 ; fact(i)<m ; r=fact(i), ++i ); 
    return r;
}

практически идентичен

int ...( int m ) {
    int ...=0; for( ...; fact(...)<m ; ++...); 
    return ...;
}

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

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

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

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

Прочитай что ли свои комментарии к функциям.

зачем, я и так помню - «специально для Ritmik...»

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

100000 элементов для факториала, который влазит в int? действительно Ппц

практически идентичен
int ...( int m ) {
int ...=0; for( ...; fact(...)<m ; ++...);
return ...;
}

это просто цирк :)

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

а теперь моя очередь сравнить С и Clojure:

~$ cat ./1.c
#include <stdio.h>
int main(int argc,char** argv)
{
   long n = atoi(argv[1]);

   long s=0, i=1;
   for( ; i<n ; ++i ) s+=i;
   printf( "%ld\n", s );
}

~$ gcc -Ofast ./1.c && time ./a.out 1000000000
499999999500000000

real	0m0.167s
user	0m0.160s
sys	0m0.004s
~$ time clojure -e "(reduce + (take-while (partial > 1000000000 ) (iterate inc 0)))"
499999999500000000

real	3m37.632s
user	3m41.946s
sys	0m0.592s
~$ 

пришлось задавать N для Си через параметр - иначе компилятор заранее вычисляет значение, жду решение на clojure, которое не так позорно сливает (оно взято из оф. примера )

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

А что используется? Свои велосипеды с for'ами?

$ apt-cache rdepends libglib2.0-0 | wc -l 3285

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

linuxnewb:речь о реюзе lazy-fact же.

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

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

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

Принцип тот же. Передаётся указатель на функцию, а не for.

нет, это и есть for, просто не надо писать код для итерации, а так - 1:1 for, который вызывает функцию

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

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

а ты забавный ) читай:

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

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

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

Так вот, когда речь идёт о foreach,map,filter и прочих очень удобно использовать лямбды.

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