LINUX.ORG.RU

Лисперы, что я делаю не так?


1

3

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

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

Может я чего не понимаю и все делаю не так. Я в основном занимаюсь обработкой данных, моделированием, железки делаю на ПЛИСах ну там всякой фигней иногда. Для меня хватает С# плюс ANTLR и StringTemplate в качестве костылей когда надо сгенерить код. В четвертом дотнете есть Expression, ежели кодогенератор нужен в рантайме. Плюс это все статически типизировано и упрощает мне сильно жизнь, что возможно связано с моим малым объемом головного мозга. Кошер в виде сборки мусора, шустрого манагера памяти, всякого синтаксического сахара тоже в комплекте.

Прикинуть алгоритм очень удобно в вольфрамовой математике из которой выплевываю код в тот же С#.

Так вот вопрос, что люди (тысячи их!) делают на лиспе?

> Прикинуть алгоритм очень удобно в вольфрамовой математике

Язык которой - диалект лиспа. Enjoy.

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

Так же я вижу что есть средства которые решают свои задачи лучше

Бесспорно. И это касается не только лиспа.

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

>я не понимаю, почему это недостаток. поясни

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

Кстати говоря, это понимает любой быдлоявакодер, интуитивно конечно. А вот объяснить это людям, страдающим лиспом головного мозга не получилось даже у людей куда более достойных чем я.

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

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

Но почему на практике не выливается?

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

> Language-oriented programming это мощнейшая метода, мощнее всех прочих известных. Ну а чтобы не прибивать эти eDSL-и к рантайму Лиспа, надо строить Лиспы над нужными тебе рантаймами (например, JVM или .NET).

А Clojure подойдет? Слышал в JVM проблемы с этим подходом.

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

> А в первую - семантика. И компилятор для этой семантики проще и надежнее всего делать в виде тех самых макр в Лиспе.

Зависит. Для DSL, наверное, не стоит использовать шизофреничную семантику и не менее шизоидный синтаксис как в С++. Так же мне кажется что для семантического анализа проще и элегантнее использовать ML с его паттерн мачингом и статической типизацией.

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

ebantrop
() автор топика

Зарабатывают деньги, зачем он еще нужен то? В лиспе были рантаймовая кодогенерация и сборка мусора лет за 20 до того, как они появилась в C#. И, сюрприз, программы в то время писать надо было тоже.

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

> В лиспе были рантаймовая кодогенерация и сборка мусора лет за 20 до того, как они появилась в C#. И, сюрприз, программы в то время писать надо было тоже.

Карандаш и бумага появились еще раньше. Люди делали самолеты и космические корабли. И что? Поставить лисперам памятник?

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

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

Tark ★★
()

Для меня хватает С# плюс ANTLR и StringTemplate в качестве костылей когда надо сгенерить код.

ну вот сравни свой код с таким подходом, например: как написать интерпретатор за один день cайт — интерпретатор простого языка на Flex/Bison + Guile Scheme

Flex+Bison немного усложняют детали реализации парсера, но обрати внимание на идею: парсером генерируется код, который прозрачно транслируется в схему

или, второй вариант: когда разбираешь AST на ANTLR,

  
 CharStream input = new ANTLRFileStream(aFilename);
            SimpleCLexer lex = new SimpleCLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lex);
            SimpleCParser parser = new SimpleCParser(tokens);
            SimpleCParser.program_return r = parser.program();

			String content =  ";;file:"+aFilename+"; -*- lisp: tree=\n"+
			((Tree) (r.tree))
			.toStringTree()
			+"\n ;;;;;;;;;;;;\n" ;

далее, идут ненужные детали про грамматику на ANTLR, код транслятора на Java/ANTLR

в итоге из такого кода

void main() {
	int fib;
	int fib_p;
	
	int n;
	int i;
	int tmp;

        int runs;
        int j;

        runs=10000;

        for (j=1;j<runs;j=1+j) { 

		fib=1; 
		fib_p=1;

		n=39;
		for (i=1;i<n;i=i+1) {
			tmp = fib;
			fib = fib+fib_p;
			fib_p = tmp;
		}
	
	printf ("fib(%d)=%d over %d runs.  \n :LISP: fib(~A)=~A  over ~A runs.  ~%", n, fib,j);
        }
          
}

генерируется вот такой AST:

(FUNC_DEF (FUNC_HDR void main) (BLOCK (VAR_DEF int fib) (VAR_DEF int fib_p) (VAR_DEF int n) (VAR_DEF int i) (VAR_DEF int tmp) (VAR_DEF int runs) (VAR_DEF int j) (= runs 10000) (for (= j 1) (< j runs) (= j (+ 1 j)) (BLOCK (= fib 1) (= fib_p 1) (= n 39) (for (= i 1) (< i n) (= i (+ i 1)) (BLOCK (= tmp fib) (= fib (+ fib fib_p)) (= fib_p tmp))) (printf "fib(%d)=%d over %d runs.  \n :LISP: fib(~A)=~A  over ~A runs.  ~%" n fib j)))))

который с небольшими изменениями в парсере (свой pretty printer вместо ANTLR-овского .toStringTree() ) превращается в такой (ну или можно натравить indent ) :

(FUNC_DEF 
          (FUNC_HDR void main) 
          (BLOK 
                 (VAR_DEF int fib) 
                 (VAR_DEF int fib_p) 
                 (VAR_DEF int n) 
                 (VAR_DEF int i) 
                 (VAR_DEF int ttmp) 
                 (VAR_DEF int runs) 
                 (VAR_DEF int j) 
                 (= runs 10000) 
                 (for 
                      (= j 1) (< j runs) 
                      (= j (+ 1 j)) 
                      (BLOK 
                             (= fib 1) 
                             (= fib_p 1) 
                             (= n 39) 
                             (for 
                                  (= i 1) (< i n) 
                                  (= i (+ i 1)) 
                                  (BLOK 
                                         (= tmp fib) 
                                         (= fib (+ fib fib_p)) 
                                         (= fib_p tmp))) 
                             (printf "fib(%d)=%d over %d runs.  \n :LISP: fib(~A)=~A  over ~A runs.  ~%" 
                                     n fib j)))))

 ;;;;;;;;;;;;

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

написать макросы FUNC_DEF, FUNC_HDR, VAR_DEF, BLOK, printf, for.

развернуть макросы, и сделать compile-file.

далее, тест: 1. запускаем в лиспе (compile-file fib.lisp)(time 'main) 2. собираем gcc С версию, запускаем /usr/bin/time -v ./fib (или /usr/bin/time -f '%U' ./fib)

сравниваем, видим: разница небольшая.

Вот так небольшими усилиями написали компилятор своего языка. Не нужно писать кодогенератор, нужно всего лишь написать макросы, которые переведут семантику токенов AST языка в семантику готовых примитивов лиспа.

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

> Ну а чтобы не прибивать эти eDSL-и к рантайму Лиспа, надо строить Лиспы над нужными тебе рантаймами (например, JVM или .NET).

ну или можно взять вместо лиспа схему с более минимальным рантаймом

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

> Наверное метода мощна, только в чем разница скажем с библиотекой функций (классов, модулей, you name it) и интерфейсом к какому-либо языку общего назначения

в том, что библиотека реализована в семантике конкретного языка и принятой там парадигмы программирования (ООП/структурное/и т.п.), а язык может быть любой парадигмы, хоть вообще декларативным

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

> Например ребята сделали на камле:

http://fprog.livejournal.com/1605.html


Синтаксис камелев с его паттерн матчингом позволяет сделать многие вещи очень лаконично. Альсо статическая типизация, что мне кажется довольно серьезным плюсом.


ну на LLVM свой язык на Ocaml тоже выглядит не очень сложным в реализации. А если взять вместо OCaml HLVM, то ещё и быстрым. К тому же, есть реализации схемы на Ocaml, так что можно перейти от одной реализации транслятора к другой просто.

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

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

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

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

> Наверное потому что так не делают?

Делают. Другие варианты?

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

> Так же мне кажется что для семантического анализа проще и элегантнее использовать ML с его паттерн мачингом и статической типизацией.

Если дсл реализуется при помощи макросов, то никаких «семантических анализаторов» просто не нужно.

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

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

anonymous
()

> Мне интересно что в лиспе есть такого что проблематично сделать другими средствами.

замыкания и продолжения? green threads поверх продолжений сигнальный протокол ошибок, CLOS и MOP

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

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

А такого контрпримера существовать не может.

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

> green threads поверх продолжений

Я знаю только один диалект, в котором есть полноценные продолжения с green threads, а ты?

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

> тут любопытно было бы привести контрпример, когда раскрутки макрами

недостаточно для реализации полноценного семантического анализатора


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

Есть ещё любопытные примеры, когда библиотеки, изначально построенные на макросах (например, BKNR.DATASTORE), в итоге переписываются на базе MOP, потому что сопровождать и отлаживать «навороченные макросы» у разработчиков желание пропадает (см. документацию на ту же BKNR.DATASTORE).

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

> CL, постороенные на основе макросов

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

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

> Если дсл реализуется при помощи макросов, то никаких «семантических анализаторов» просто не нужно.

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

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

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

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

> а как сделать дсл с нормальной обработкой ошибок

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

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

> все известные библиотеки для парсинга на CL, постороенные на основе макросов - страшны как смертный грех

META от Henry Baker довольно прозрачная, хотя и страшноватая

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

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

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

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

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

Gambit да, забыл про него. А в остальном продолжения/треды поддерживаются именно на уровне рантайма или в виде отдельных костылей поверх ядра языка реализованы?

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

> генерируется вот такой AST

Спасибо за пример.

Это все понятно, что AST любого языка программирования ложится на s-выражения как паровоз на рельсы. Только потом один хрен разбирать нужно все возможные косяки. Скажем если «int tmp;» заменить на «string tmp;». Сий факап обнаружится только в строке «tmp = fib;»

Либо про семантику С++. Что делает код «a = b << 1;»? А если «b» поток? Какой тип у «a»?

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

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

> Существенное использование дсл - это просто некая парадигма программирования, такая же как ООП или процедурное. И «необхдимость» в этой парадигме такая же, как во всех других.

Спасибо. Подумаю об этом на досуге.

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

> А Clojure подойдет? Слышал в JVM проблемы с этим подходом.

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

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

> Так же мне кажется что для семантического анализа проще и элегантнее использовать ML с его паттерн мачингом и статической типизацией.

pattern matching и в Лиспах есть.

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

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

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

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

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

любое иное решение всегда менее элегантно.

любое

всегда

Вот так и набирают в секту %)

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

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

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

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

> Любопытно на самом деле другое - все известные библиотеки для парсинга на CL, постороенные на основе макросов - страшны как смертный грех, а использовать Esrap, в которой всего один макрос, да и тот используется в роли синтаксического сахара, на практике намного удобней.

О, вот и макроненавистник вступил в разговор. Тебе б на жабе кодить, таким как ты Лисп соврешенно не в тему.

Дурачок, Infix - страшен?

CL-PEG страшен?

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

Мало ли идиотов в мире? Идиоты не умеют делать не-навороченные макры, потому делают навороченные и потом жалуются, что мол «все сложно». А макры должны быть простыми и тупыми. И так программировать очень просто. Но идиоты не умеют.

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

> Вот так и набирают в секту %)

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

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

> Ну то, что в CL макросы надо использовать предельно осторожно - это же факт известный.

Кому это «известный»? Косолапым и криворуким недопрограммистам? Да кого вообще их мнение волнует?

Макры ничуть не опаснее в применении, чем замыкания и прочая дребедень. К ним просто надо применять все те же принципы разработки - не должно быть сложных макр, которые делают больше чем какую-то одну, тривиальную вещь. Так же как не должно быть сложных и длинных функций, и т.д. Если этому следовать, то код с макрами отлаживать и поддерживать ничуть не сложнее любого другого. Грэм не зря утверждает, что макры должны составлять около 20% от всего кода.

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

> у более разумных/скептических настроенных людей

ой-ой, это ОНО себя, небось, к «разумным» причисляет? После такого позорного слива на тему алгебры и символьных вычислений?

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

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

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

> Ну да, Hans Hübner идиот, а ты кто?

Конечно он идиот. Рядом с Грэмом и Зибелем - полнейший идиот. А я передаю тебе их мудрые слова в доступной тебе форме. Доходит?

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

А кто тебе сказал, что на макросах сложно систему типов реализовать? Да проще простого, на самом деле. Я видел несколько реализаций ML поверх Лиспа, полностью на макрах сделано.

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

Стоп. Начинается переход на личности, что в итоге закончится говносрачем, чего совсем не хочется.

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

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

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

Вот в ANTLR например, есть синтаксические и семантические предикаты.

И что? Поздравляю с этим пользователей Antlr.

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

> Стоп. Начинается переход на личности, что в итоге

закончится говносрачем


Ты просто ещё не понял, с каким придурком общаешься.

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

> С какой такой радости? Макросы - это все те же самые «обычные средства», только еще и доступные во время компиляции. Твои «обычные средства» - это лишь подмножество того, что можно делать макросами, а вовсе не наоборот.

Вопрос не в том что можно сделать. Вопрос в maintainability макросов.

Хотя есть уникумы на басике ваяют шо мама не горюй.

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

> Ты просто ещё не понял, с каким придурком общаешься.

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

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

> Ты просто ещё не понял, с каким придурком общаешься.

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

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