LINUX.ORG.RU

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

> многие не любят, как выглядит Tk (хотя эта ситуация, наверное, скоро изменится)

Именно это и погубило его в моих глазах. А как фанател от него в свое время...

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

>Раз уж зашла такая речь, может еще подскажете стандартные аналоги Lex/Yacc для Lisp? Я понимаю, что налабать свой собственный транслятор с нуля на Lisp -- самое оно для "настоящих мущин". Но хотелось бы без особого геморроя и, по возможности, в рамках известной технологии.

Без проблем. Причем генерация всяких LALR, LR и пр. парсеров -- это задача красивейшим образом решаемая на LISP без отсылки к другим средствам. Если для C Lex, Yacc -- это внешние костыли, то в LISP парсинг делается без отсыла куда-либо еще. Сам генератор парсеров сделан на LISP, грамматика описывается на LISP, лексические формы описываются на LISP, и генерируется готовая LISP-программа парсера по твоей грамматике.

Ссылка: http://www.cliki.net/parser

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

>Именно это и погубило его в моих глазах. А как фанател от него в свое время...

А чего в нем страшного? В виндах, насколько я знаю, он выглядит неотличимо от нативного интерфейса. В Маках тоже использует их кнопочки. а в Linux вот чего ребята тут демонстрировали:

http://www.linux.org.ru/jump-message.jsp?msgid=1478170

Они пишут, что это какая-то тестовая ветка Tk8.5a3. Выглядит очень прилично. Думаю, что будет красиво. Да и некрасивый Tk можно красиво оформить. Главное -- это вкус иметь :)

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

> Больше, чем все? 8-O

Конешно больше, и намного

> А можно поинтересоваться: Лисп -- это единственный грамотно сконструированный язык?

ИМХО нет. Например я считаю достаточно грамотно сконструированной жабу, но предпосылки, заложенные в ней (примитивность и ограничения), мне не нравятся. С также достаточно хорош для свох задач, имеет минимум "роялей в кустах", хотя ещё есть куда, но весьма низкоуровнев, увы. С++ наоборот неудачен.

Вообще, ИМХО попытки сочетать традиционные разделения на примитивные типы (целое, вещественное итд) и обекты и затем использовать для операций с частью из них традиционные записи операторов, инфиксные +-*/ совместно с функциями, а для объектов функции - корявое и неудачное. Создатели лиспа сделали смелый шаг - отказались от традиционных нотаций, которые в программировании неудобны. Из-за чего появился хороший язык, и кучя народу, которому он не нравицо из-за непривычности.

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

Ладно, напишу. Однако два clg я знаю, древний для гтк1 и второй, clg-0.9... Который пашет с гтк2. Насколько я помню, clg неработает с clisp. Нужен cmucl которое я юзаю или sbcl.

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

> Они пишут, что это какая-то тестовая ветка Tk8.5a3.

Три года назад он все еще выглядел кошмарно. А в прошлом году я уже успел присесть плотно на gtk. И не вижу причин отказываться от него. Только, пожалуйста, без флейма. Просто сейчас это мой выбор.

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

>> Больше, чем все? 8-O

> Конешно больше, и намного.

Ну да. Банан велик, а кожура еще больше :-).

> ИМХО нет.

И это радует. Для меня Лисп прошел сугубо по касательной. А функциональную парадигму я изучал по айверсоновскому APL/J. Об этом языке тоже ходили легенды. Например, что модель ядра OS/360 может быть записана на этом языке в 120 символов ;-). Сам я этого не видел, зато сам написал программу поиска простых чисел в 17 символов и решение задачи о 8 ферзях где-то в десяток строк. Хотя у товарища на прологе все-равно получилось короче :-(. Я даже умудрялся писать на этом языке неплохие инструментальные штучки, с SQL-биндингдами к Access и обработкой текста. А потом бросил.

Примерно тогда мы с товарищами сошлись во мнении, что любой алгоритм имеет фиксированную информационную емкость, а его запись на различных языках отличается только уровнем энтропии. Отсюда следствие, что на написание любой программы определенной сложности необходимо примерно одно и то же время. Различается только способ разработки. В "низкоуровневых" языках (то есть, с высокой энтропией, или, как любят здесь говорить, "быдлоязыки"), мысль разворачивается согласно канонам классической литературы: экспозиция, завязка, кульминация, развязка. Такой стиль близок большинству людей, поэтому эти языки популярны. А вот в "высокоуровневых" языках (с низкой энтропией) мысль может быть выражена весьма четко и ясно, фактически, с лапидарностью афоризма. Тут само решение рождается с помощью некого "мысленного скачка", когда автор долго думает, а потом программа рождается, как будто из ничего. Это, конечно же, завораживает, и не может не привлекать. Однако, Вы можете представить себе человека, который говорит исключительно афоризмами? Вот и получается, что в любом, даже самом функциональном языке, есть куски императивной парадигмы, чтобы хоть как-то дать разработчику костыли для привычного мышления. Что-то вроде строительных лесов. И Лисп, насколько я знаю, тут не исключение -- кроме рекурсии в нем есть и циклы и ветвления. Другое дело, что это считается моветоном, и в законченной программе должно быть устранено. А вот за что мне нравится Питон, так это за то, что в нем, начав писать императивно, несложно отрефакторить окончательное решение в чисто функциональном стиле.

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

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

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

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

Вообще-то они еще не были традиционными _в программировании_ (программирования как профессии еще практически не существовало). А против нотации Лиспа люди "проголосовали ногами".

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

>>Именно это и погубило его в моих глазах. А как фанател от него в свое время...

>А чего в нем страшного?

Выглядит он корявенько

> В виндах, насколько я знаю, он выглядит неотличимо от нативного интерфейса.

Как лицо дауна неотличимо от лица нормального человека

> Они пишут, что это какая-то тестовая ветка Tk8.5a3. Выглядит очень прилично. Думаю, что будет красиво.

Наконец-то его доведут до ума...

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

> Ну да. Банан велик, а кожура еще больше :-).

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

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

Это неправильное следствие. В какой-то степени. Потому что одна и та же задачя, выраженная в одних терминах, решается легче, чем выраженная в других терминах. Я приводил примеры - нахождение множества всех перестановок и доступ к бд. Если решать чисто низкоуровневым способом - при помощи циклов, получится конкретная бяка. С помощю контейнеров, предоставляемых С++, уже намного легче. Питольим способом - с рекурсиями и возможностью выделения подпоследовательностей - наименее сложный из низкоуровневых вариантов. А вот лисп - предоставляет возможность описания терминов и оперирования ими, из-за чего для решения задачи можно использовать наиболее оптимальную терминологию, без привлечения лишних сущностей, каковыми в моём примере являются индексы элементов. Таким образом, если задачу ослободить от ненужной шелухи, конечно, она может решиться намного быстрее и проще.

> В "низкоуровневых" языках (то есть, с высокой энтропией, или, как любят здесь говорить, "быдлоязыки"),

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

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

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

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

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

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

>> В виндах, насколько я знаю, он выглядит неотличимо от нативного интерфейса.

>Как лицо дауна неотличимо от лица нормального человека

http://tktable.sourceforge.net/tile/screenshots/windowsxp.html

http://www.muonics.com/Products/MIBSmithy/screens.php

http://installbase.sourceforge.net/screenshots.shtml

Ну и что тут такого даунистического?

Zubok ★★★★★
()

Надо запостить на lorquotes эти перлы:

"Лисп это круто (tm), программа это данные и всё такое, но за пределами иподрома для сферических коней рулит Питон."

">>> в Лиспе есть всё

>> На самом деле там есь гораздо больше.

> Больше, чем все? 8-O

Конешно больше, и намного."

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

> Ну и что тут такого даунистического?

Тут - ничего. Но, я подозреваю, это самоновейшие версии Tk. А репутацию свою он испортил гораздо раньше.

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

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

Зато эту бяку проще развернуть во времени, что более естественно для человеческого мышления. В функциональном подходе это тоже можно сделать с помощью серии последовательных приближений, но каждый раз это будет "решение целиком", то есть, преодоление "смыслового разрыва" одним скачком. Это не до всех доходит. Лично я всегда вначале выписываю цикл, а потом сворачиваю его в функциональный вызов. То есть, преодолеваю ту же пропасть в два шага. Грубо говоря, есть также подозрение, что процедурная декомпозиция намного более естественна, чем функциональная. Правда, меня можно обвинить в том, что я не крутой перец. С другой стороны, а почему бы мне не предположить, что Вы делаете то же самое, только прячете от меня промежуточные результаты?

Кстати, а как обстоит дело с пошаговой отладкой в Лисп-средах? То есть, я догадываюсь, что она, скорее всего, не нужна. Однако, я подозреваю, что в практической жизни человек все же чаще мыслит алгоритмически, "шаг за шагом", а функции использует только для оптимизации. Так проще. Отсюда и более высокая популярность императивных языков.

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

На самом деле, Вы просто умело прячете эту шелуху "под коврик". А выработка "оптимальной терминологии" -- не более, чем разработка "оптимальной библиотеки/фреймворка" в императивных языках. Вот и получается, что все то время, пока Вы придумываете "оптимальную терминологию", вполне можно успеть изготовить приличную императивную штуку, решающую поставленную задачу. Это я и имел ввиду, когда говорил об "информационной емкости". То есть, пока одни думают, другие пилят. Иногда выигрывают одни, иногда другие -- это зависит от степени фанатизма (помните "Записки жены программиста"? ;-). В среднем же получается паритет, что и было выражено в виде гипотезы.

Правда, это все не касается возможностей повторного использования кода. Создание "оптимальной терминологии" позволяет эффективно повторно использовать код. Так же, как и написание качественной библиотеки. Однако, создать уникальную библиотеку для уникальной задачи, а потом вычесть из общего времени решения создание библиотеки -- это, согласитесь, передергивание. У нас в таких случаях обычно вспоминают знаменитое "Лучше день потерять, но потом за пять минут долететь" ;-).

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

> Надо запостить на lorquotes эти перлы:

ИМХО не пройдут. Лучше весь топик прокачять, чтобы вошед в аналы истории, как РФВС, стандарты и гномореестр.

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

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

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

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

> С другой стороны, а почему бы мне не предположить, что Вы делаете то же самое, только прячете от меня промежуточные результаты?

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

> Кстати, а как обстоит дело с пошаговой отладкой в Лисп-средах?

Весьма неплохо. Есть трассировка и ещё всякое.

> На самом деле, Вы просто умело прячете эту шелуху "под коврик".

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

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

>> А репутацию свою он испортил гораздо раньше.

> Испортил, говорите?... А в чьих глазах? :)

Широких масс людей, которые пишут программы с GUI. Что автоматически сделало его выбором тех, кто хотят быть "не как все" :-P

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

> Если для C Lex, Yacc -- это внешние костыли, то в LISP парсинг делается без отсыла куда-либо еще. Сам генератор парсеров сделан на LISP, грамматика описывается на LISP, лексические формы описываются на LISP

То есть "внешнекостыльность" Lex и Yacc проявляется в том, лексемы описываются как регулярные выражения, а грамматика описывается не на Си, а как БНФ ?

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

> Попробуй перестановки наборов произвольной длины, без контейнеров и рекурсий, только циклами. Результат сюды пожалста.

Самое смешное, что мы решали эту задачку на олимпиадных сборах по информатике еще в лохматом 1988 году ;-). Сейчас уже и не вспомню суть, но, кажется, решения было чисто императивным, писали мы его на РАЯ ;-). Помню только, что решение было изящным и остроумным, я потом по блату раздавал знакомым в институте. Почему, собственно, меня и заинтриговал пример. Впрочем, могу и ошибаться. Попробую вечером добраться до своих школьных тетрадок, посмотрю.

Кстати, если Вам еще не надоело, то раз уж зашла речь о рекурсиях, то вот еще один вопрос: какую глубину выдерживает вычисление функции Аккермана, ну, например, в Common-Лиспе? В принципе, интерпретатор у меня есть. Можете написать здесь корректное решение?

Вообще говоря, в подавляющем большинстве случаев рекурсия нормально заменяется циклами. Взять хотя бы такую задачку. Функция f(n) для целых неотрцательных n определена так: f(0)=0, f(1)=1, f(2n)=f(n), f(2n+1)=f(n)+f(n+1). Для данного N найти и напечатать f(N). Обязательное услове: N столь велико, что недопустимо заводить массив, длина которого растет с ростом числа N).

Задачу нужно было решить на Фортран-77, где принципиально нет рекурсии. А дополнительное условие специально запрещало создавать стек. Я долго не мог решить ее именно в таком виде. И решил на удивление быстро в рамках исчисления Дийкстры: самым сложным оказалось найти подходящий инвариант. Поверьте, кайфу было не меньше, чем от перестановок на Лиспе!

О! Сейчас посмотрел в условия олимпиады 1980 года, там оказывается есть Ваша задача! Вот ядро решения на Паскале:

for i:=m-1 downto 1 do if (P[i]<P[i+1]) then begin n:=P[i]; for j:=m downto i do if (n<P[j]) then begin P[i]:=P[j];P[j]:=n; k:=1; while i+k<m-k+1 do begin n:=P[i+k]; P[i+k]:=P[m+1-k]; P[m+1-k]:=n; k:=k+1; end; j:=i; end;

Достаточно длинно, не спорю, целых 17 строк. На C короче -- ядро уместилось в восемь строк ;-). На Бейсике -- десять. Длиннее всего на Фортране -- около 25 строк. А вот и описание:

Чтобы по данной перестановке P=(p1, p2, ..., pm) чисел 1, 2, ..., m построить не- посредственно следующую мы будем просмат- ривать числа p1, p2, ..., pm с конца. И остановимся, когда впервые попадется член pi, меньший стоящего правее него (pi<pi+1). Если такого члена нет, то пе- рестановка P имеет вид (m,m-1,...,1), то есть является последней. Ясно, что члены pi+1>pi+2>...>pm образуют убывающую пос- ледовательность. Найдем среди них первый (если их рассматривать с конца) член pj, уже больший чем pi, и поменяем их местами. Остается переставить члены pi+1, pi+2, ..., pm в порядке возрастания, и искомая перестановка (назовем ее Q=(q1,...,qm)) будет получена.

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

Опаньки! Форматирование записало все решение в одну строку ;-).

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

> Кстати, если Вам еще не надоело, то раз уж зашла речь о рекурсиях, то вот еще один вопрос: какую глубину выдерживает вычисление функции Аккермана, ну, например, в Common-Лиспе? В принципе, интерпретатор у меня есть. Можете написать здесь корректное решение?

Вы имели в виду cLisp? Это "СИ-лисп", поскольку большая часть его внутренностей написана на си. Много не выдержит - несколько сотен или тысяч. Аккерман "плох" тем, что не сворачивается в хвостовую рекурсию. Но если "развернуть" его, то у вас памяти не хватит для вычисления хотя-бы от (4, 2) :)

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

> Сейчас уже и не вспомню суть, но, кажется

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

:D

> какую глубину выдерживает вычисление функции Аккермана,
ну, например, в Common-Лиспе?

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

> Можете написать здесь корректное решение?

Не спец по функциям Аккермана. Вот что произвелось, 
но не утверждаю то моё оптимально

(declaim (optimize (speed 3) (safety 0)))

(defun ack (m n &optional (hash (make-hash-table :test #'equal)))
    (let* (
        (arg (list m n))
        (val (gethash arg hash)))
    (if (null val)
        (setf (gethash arg hash)
            (cond 
                ((= 0 m) (+ 1 n))
                ((= 0 n) (ack (- m 1) 1 hash))
                (t (ack (- m 1) (ack m (- n 1) hash) hash))))
        val)))  
        
(compile 'ack)

> в подавляющем большинстве случаев рекурсия нормально 
заменяется циклами.

Заменяется, да. 

> Достаточно длинно, не спорю, целых

Какая фих разница сколько строк? Главное что это решение явно
гиморнее для человека. С ним и сложнее разобраться, 
и сложнее выдумать. И противоестественнее. Решение же на лиспе -
попросту запись _человечьего_ определения 
в терминах и синтаксисом лиспа.

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

> Попробуй перестановки наборов произвольной длины, без контейнеров и рекурсий, только циклами. Результат сюды пожалста.

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

Я же не требую чтобы ты писал на лиспе без списков.

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

Недавно писал сочетания без рекурсии. Получилось страшно:

def generate_combination(m, n):
    combination = range(n)

    while True:
#        print combination
        yield combination
        
        index = n - 1
        while True:
            combination[index] += 1
            
            if combination[index] < m - (n - index - 1):
                break
            else:
                if index > 0:
                    combination[index] = combination[index - 1] + 2
                else:
                    return
            
            index -= 1
        
        val = combination[index] + 1
        for i in xrange(index + 1, n):
            combination[i] = val
            val += 1

Но опять таки религия рекурсией пользоваться не запрещает, и
если надо в Питоне всегда её можно использовать.


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

> А почему без контейнеров?

Исключительно чтобы проверить тезис о том что низкоуровневое программирование с меньшей степенью абстракций более естественно.

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

А в сях нету

> как без контейнеров передать аргумент (список значений для перестановки) в функцию?

Как массив+длина

> Я же не требую чтобы ты писал на лиспе без списков.

И правильно. Хотя можно вполне без них обойтись, потому что в лиспе есть и массивы и хеши и ещё всякое. Только если не использовать более абстрактные конструкции, код на лиспе станет питоноподобным. А раз уж разговор тут перетёк в тему "высокоуровневое vs низкоуровневое программирование", дальнейшее обсуждение потеряет смысл.

> понятно что фигня получится.

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

> Но опять таки религия рекурсией пользоваться не запрещает, и если надо в Питоне всегда её можно использовать.

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

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

Что-то я уже перестал понимать, о чём спор идёт. Мы про высокоуровневое vs низкоуровневое программирование или про функциональщину vs императивщину? Или просто LISP против всех? :)

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

чел предположил что

> функциональном подходе это тоже можно сделать с помощью серии последовательных приближений, но каждый раз это будет "решение целиком", то есть, преодоление "смыслового разрыва" одним скачком. Это не до всех доходит. Лично я всегда вначале выписываю цикл, а потом сворачиваю его в функциональный вызов. То есть, преодолеваю ту же пропасть в два шага. Грубо говоря, есть также подозрение, что процедурная декомпозиция намного более естественна, чем функциональная. Правда, меня можно обвинить в том, что я не крутой перец. С другой стороны, а почему бы мне не предположить, что Вы делаете то же самое, только прячете от меня промежуточные результаты?

> Вот и получается, что все то время, пока Вы придумываете "оптимальную терминологию", вполне можно успеть изготовить приличную императивную штуку, решающую поставленную задачу.

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

bugmaker ★★★★☆
()
Ответ на: комментарий от ero-sennin

> Да мне и лисп, и питон нравятся, фигли тут спорить. :)

Ну как же! А на первое место мы попасть не собираемся?

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

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

Дыкть, пишется все это ровно один раз ;-).

> Главное что это решение явно гиморнее для человека. С ним и сложнее разобраться, и сложнее выдумать. И противоестественнее.

Неочевидно, что с решением на Лиспе проще разобраться. Лично для меня оно тоже противоестественно :-).

> Решение же на лиспе - попросту запись _человечьего_ определения в терминах и синтаксисом лиспа.

Я Вам тоже дал _человечье_ определение, которое оказалось достаточно записать в терминах и синтаксисом Паскаля. Кстати, можете повторить свое "человечье" определенье? Или хотя бы ссылку напомнить?

eugine_kosenko ★★★
()
Ответ на: комментарий от ero-sennin

> Или просто LISP против всех? :)

А мне еще особенно интересно послушать серию "Lisp против Forth". А че? Метапрограммирование в Форте есть? Есть. Простота структур данных есть? Есть? Языком системного программирования является? Является. Синтексис извращенный предлагает? Предлагает. Маргинален? Очень даже маргинален. Ну и, чем же Лисп лучше Форта?

;-)

> Ну как же! А на первое место мы попасть не собираемся?

А то! Мы еще тему логического программирования не затрагивали... ;-)

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

> Маргинален? Очень даже маргинален. Ну и, чем же Лисп лучше Форта?

Дык тем, что он _еще_ маргинальнее 8)

А вообще хотелось бы увидеть пример и/или ссылку на примеры метапрограммирования в Лисп (или Питон 8) ). А то я слышу "метапрограммирование", "синтаксис, идеальный для метапрограммированя", а что это - никто внятно не объясняет. И в Сети внятных примеров пока не нарыл.

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

> Дыкть, пишется все это ровно один раз ;-).

дык если всё требуемое по разу но цельную неделю...

> Неочевидно, что с решением на Лиспе проще разобраться. Лично для меня оно тоже противоестественно :-).

достаточно очевидно ИМХО. Потому что намного меньше подробностей есть. Другое дело, что непривычно может быть. Но отрицать что запись с меньшим количеством незначащих подробностей читаецо луче ИМХО глупо.

> Я Вам тоже дал _человечье_ определение, которое оказалось достаточно записать в терминах и синтаксисом Паскаля.

Всё правильно. Только вот разница в длине и замысловатости определений преогромна. Моё можно сыскать в этом же треде пару страниц назад.

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

> Синтексис извращенный предлагает?

Ну, за извращёным синтаксисом это к питону в первую очередь

> чем же Лисп лучше Форта?

Тем что в форте ашыпки практически неуловимы.

> А то! Мы еще тему логического программирования не затрагивали... ;-)

И метапрограммирования тоже

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

Кажется, начинает брезжить тусклый свет понимания... То есть: если макросы могут использовать всю мощь языка для генерации кода, то это уже метапрограммирование? (у нас в PL/I такое было :))

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

Не нарыл - значит и не рыл совсем... :(

Помимо указанной ссылки можешь в любом OS лиспе реализацию loop посмотреть... ;)

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

> Не нарыл - значит и не рыл совсем... :(

Только Википедия, и немного по ссылкам оттуда

> Помимо указанной ссылки можешь в любом OS лиспе реализацию loop посмотреть... ;)

Ну, это слишком круто пока, и по советам людей двигаться как-то проще. Кроме того, мой основной интерес - Python.

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

> А вообще хотелось бы увидеть пример и/или ссылку на примеры метапрограммирования в Лисп (или Питон 8) ). А то я слышу "метапрограммирование", "синтаксис, идеальный для метапрограммированя", а что это - никто внятно не объясняет. И в Сети внятных примеров пока не нарыл.

В comp.lang.python не раз обсуждалась необзодимость макросов в Питоне, как правило это получается диалог типа:

Lisp Lover (LL): В питоне нужны макросы для того чтобы сделать ...

Python Bydlockoder (PB): Это можно сделать при помощи стандартных возможностей языка (классы, замыкания, динамическое создание классов и т.д.).

Т.е. не было приведено вменямых use-case-ов где нужны макросы.

Гвидо придерживается позиции создания специального синтаксиса для закрытия таких use-case-ов, например List comprehensions, with (ну всё фанаты Руби больше не будут приставать со своим chdir-ом :-)

А по поводу того что Питон (да и все остальные языки) со временем всё больше и больше становится похож на Лисп (как говорит Грэм, да и в этой ветке эта мысль уже прозвучала) есть такая ссылка:

http://www.prescod.net/python/IsPythonLisp.html

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

> Т.е. не было приведено вменямых use-case-ов где нужны макросы.

Как бы ты реализовал http://groups.google.com/group/comp.lang.lisp/msg/4fe888b58ffa83b8 ?

> http://www.prescod.net/python/IsPythonLisp.html

"Graham demonstrates the "power" of Lisp compared to Python by comparing tiny code snippets." - сразу видно, практик писал 8) Вот и мне обмен небольшими кусочками кода в этом треде кажется... несерьезным.

Лисп, конечно, был революционным языком, но сегодня его фишками никого не удивишь. Хотя я хочу многострочные ламбды в Питоне! 8)

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

> Хотя я хочу многострочные ламбды в Питоне! 8)

Придумай для них нормальный синтаксис, напиши PEP и всё будет. :)

ero-sennin ★★
()
Ответ на: комментарий от redvasily

> Я знаю только самые основы Схемы. Лисп я читать не могу. Что там надо сделать?

Допёр. Щас сделаю.

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

> Как бы ты реализовал http://groups.google.com/group/comp.lang.lisp/msg/4fe888b58ffa83b8 ?

Вот так:

class Parser:
    pattern_length = 4
    
    def __init__(self, *readers):
        self.readers = {}
        for r in readers:
            self.readers[r.pattern] = r
        
    def parse(self, data):
        for line in data:
            reader = self.readers.get(line[:self.pattern_length], None)
            if reader is not None:
                yield reader.parseString(line)

class LineReader:
    def __init__(self, pattern, class_, fields):
        self.pattern = pattern
        self.fields = fields
        self.class_ = class_
    
    def parseString(self, s):
        obj = self.class_()
        for field in self.fields:
            setattr(obj, field[2], s[field[0]:field[1] + 1])
        return obj

class SystemObject:
    def __str__(self):
        return self.__class__.__name__ + ' ' + str(self.__dict__)
            
class ServiceCall(SystemObject):
    pass

class Usage(SystemObject):
    pass

def main():
    service_call_reader = LineReader('SVCL', ServiceCall, [
        (4, 18, 'customer_name'),
        (19, 23, 'customer_id'),
        (24, 27, 'call_type_code'),
        (28, 35, 'date_of_call_string')])

    usage_reader = LineReader('USGE', Usage, [
        (4, 8, 'customer_id'),
        (9, 22, 'customer_name'),
        (30, 33, 'cycle'),
        (31, 36, 'read_date')])
    
    data = """
SVCLFOWLER         10101MS0120050313......................... 
SVCLHOHPE          10201DX0320050315........................ 
SVCLTWO           x10301MRP220050329.............................. 
USGE10301TWO          x50214..7050329..........................""".splitlines()
    
    parser = Parser(service_call_reader, usage_reader)
    
    for obj in parser.parse(data):
        print obj
    
if __name__ == '__main__':
    main()

Суть таже самая. Формат строки объявляем декларативно.
Вот тебе и DSL в Питоне :-)

Т.е. получилось длинее чем у них, но у меня код много чище (ИМХО):

1. Отдельный класс на парсер. У них просто разбирают строки в main-e
У меня есть возсожность использовать Parser повторно

2. Отдельный классы на SystemObject, ServiceCall, Usage. Т.е. возможность объявить разные методы у разных классов.

3. Переопределённый __str__. У них насколько я понял, используется 
стандартное строковое представление объектов.

4. Четвёрка у меня именнованная константа, у них magic number

5. И какой код будет легче поддерживать? :-)

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

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

Да, не удивишь. Но догнать его так никто и не смог...

Или уже есть язык, в котором всю его мощь можно использовать для кодогенерации, причём в теле основной программы, а не внешним/сторонними трансляторами?

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

Хотя, зачем вам такие сложности? Подом сиди и ломай голову - что ты вызываешь, ибо если функцию, то сначала, как и положено, вычисляться параметры, а потом сама функция, а если макро - фиг его знает будут ли параметры вычисляться вообще. А ещё есть макро для компиляции, и результат их "раскрутки" может быть несколько иной, чем в интерпретаторе (где это вообще может быть функцией). Спотыкайся о то, что типы не есть классы, а классы не есть типы. Да, один loop чего стоит, ибо похож больше на питон, чем на лисп (хотя питону такое и не снилось). Опять же, разобрать чужой код, написанный правильно, иногда сродни ребусу: одни макросы вызываются при построении других, а последние просто вызываются один раз при инициализации каких-то данных, причём повторить этот трюк в интерпретаторе просто так нельзя, ибо на эти данные завязана работа самой среды... Охренеть можно. А выкрунтасы с readtable - это даже не макросы (это может быть как макро в си, а может быть интерпретатор другого языка - SQL например, или XML/HTML/всего чего угодно...) Что ещё? Internal type/class могут не наследоваться. А разные области имён для функций и переменных - вообще сказка - как вам такое:

(setf (slot-value foo 'foo) (foo 'foo :foo foo))

И чем дальше в лес, тем толще партизаны... Нафиг, бросайте вы эту дурную затею ;)

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

Ага, страница кода конечно лучше, чем два десятка строк - вопросов нет!.. :)

> 1. Отдельный класс на парсер. У них просто разбирают строки в main-e У меня есть возсожность использовать Parser повторно

А на лиспе кто-то запрещает код использовать повтороно? Там только пример. Переделать на функции - больше кода не станет :)

> 2. Отдельный классы на SystemObject, ServiceCall, Usage. Т.е. возможность объявить разные методы у разных классов.

Ну а там лепи себе defmapping под свои нужды - и всех делов. Хоть ещё для десятка типов. В чём твоё преимущество?

> 3. Переопределённый __str__. У них насколько я понял, используется стандартное строковое представление объектов.

Вот тут я тебя не понял.

> 4. Четвёрка у меня именнованная константа, у них magic number

Это даже не смешно. Это же был пример на скорую руку. Ещё одна строка кода - всего-то. Или более того - вынести не 4-ку, а (subseq line 0 4) (а то и вместе с internal) в функциональную переменную, и определяй себе тип как твоей душе угодно.

> 5. И какой код будет легче поддерживать? :-)

Не твой - 100% :) Если конечно ты не знаешь лисп, ну тогда ССЗБ ;)

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

> Гвидо придерживается позиции создания специального синтаксиса для закрытия таких use-case-ов, например List comprehensions, with (ну всё фанаты Руби больше не будут приставать со своим chdir-ом :-)

Вот-вот, какой Гвидо решил создать синтаксис, таким вы пользоваться и будете. А тут пиши себе свой хоть по одному на каждый день недели... ;)

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

> Ну, это слишком круто пока, и по советам людей двигаться как-то проще. Кроме того, мой основной интерес - Python.

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

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

> если макросы могут использовать всю мощь языка для генерации кода, то это уже метапрограммирование?

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

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