Хорошим и успешным примером, реализующим идею макросов, является TeX. LaTeX не выходит за рамки TeX, но является уже языком более высокого уровня. Сюда же можно и PostScript отнести.
З.Ы. Сейчас опять попросят показать Typesetting in LISP, как в прошлый раз во время флейма про XML. :)
Вы тут так пиарите РФВС, что я его нашёл поиском и прочитал. Фигня какая-то, сплошные пацанячьи разборки и квантовая физика в перемешку с техникой WW2, и немного о слаке.
> Вернусь домой - нарою точную цитату из Дейкстры, общий смысл -
> "Ненавижу, бл#, @#$%ов, которые определяют циклы через рекурсию".
"Можно обойтись этим объяснением, но оно все же не является
исчерпывающим. Я все равно считал себя обязанным ввести повторение
как самостоятельную конструкцию, поскольку мне представлялось, что
это следовало сделать уже давно. Когда языки программирования
зарождались, "динамическая" природа оператора присваивания казалась
не очень приспособленной к "статической" природе традиционной
математики. Из-за отсутствия соответствующей теории математики
ощущали некоторые затруднения, связанные с этим оператором, а
поскольку именно конструкция повторения создает необходимость в
присваиваниях переменным, математики ощущали затруднения и в связи
с повторением. Когда были разработаны языки без присваивания и без
повторений -- такие, как чистый ЛИСП,— многие почувствовали
значительное облегчение. Они снова ощутили под ногами знакомую почву
и увидели проблеск надежды превратить программирование в занятие
с твердой и солидной математической основой. (До сего времени среди
склонных к теоретизированию специалистов по машинной математике все
еще широко распространено мнение, что рекурсивные программы "более
естественны", чем программы с повторениями.)
Другого выхода из положения путем надежного и действенного
математческого обоснования пары понятий "повторение" и "присваивание
переменной" нам предстояло ждать еще десять лет. А выход, как
показано в этой монографии, заключался в том, что семантику
конструкции повторения можно описать с помощью рекуррентных отношений
между предикатами, тогда как для описания семантики общей рекурсии
требуются рекуррентные отношения между преобразователями предикатов.
Отсюда совершенно очевидно, почему я считаю общую рекурсию на порядок
более сложной конструкцией, чем простое повторение; и поэтому мне
больно смотреть, как семантику конструкции повторения
"while B do S"
определяют как семантику обращения
"whiledo(B, S)"
к рекурсивной процедуре (описанной в синтаксисе языка АЛГОЛ 60):
procedure whiledo(условие, оператор);
begin if условие then begin оператор;
whiledo(условие,оператор) end
end
Несмотря на формальную правильность, это мне неприятно, потому, что я
не люблю, когда из пушки стреляют по воробьям, вне зависимости от
того, насколько эффективно пушка справляется с такой работой. Для
поколения теоретиков машинной математики, которые подключались к этой
тематике в течение шестидесятых годов, приведенное выше рекурсивное
определение часто является не только "естественным", но даже "самым
правильным". Однако ввиду того, что без понятия повторения мы не можем
даже описать поведение машины Тьюринга, представляется необходимым
произвести некоторое восстановление равновесия."
> я уж молчу о трансляторе нормального языка, тогда как на лиспе делается элементарно.
Где посмотреть на Лиспе элементарную грамматику SQL-92, а вообще меня больше интересует PL/SQL версии 2. На lex/yacc это и в самом деле ужос, а вот то, что на Лиспе "элементарно" -- серьезно сомневаюсь.
> Я придерживаюсь такой терминологии: если заостряется внимание на том что нужно делать, то это декларативщина, а если на том как мы это будем делать, то императивщина. Естественно любая реальная прога будет содержать как декларативную, так и императивную составляющую. Приведённый алгоритм декларативен, так как он состоит из фраз уровня 'делай шаг, а не 'вычисли адрес указателя.
Гмм, википедия придерживается другой точки зрения.
> Всё чудесно - теперь скажите, на каком языке в пределах одного файла можно переопределить синтаксис, использовать новый синтаксис в определённых местах, снять переопределение, и так сколько угодно раз.
Я уже упоминал Форт. И упоминал, что существуют реализации Лиспа на Форте. А это значит, что Форт -- еще более высокоуровневый ;-).
> А это самый главный вопрос и есть при промышленном программировании. Какой язык позволяет сделать проект быстрее и лучше, тот и выбирается для применения.
> Вот кусок кода. На питоне там нет ни одной лишней сущности, на лиспе целых две. Вместо того чтобы это нормально обсудить ты
хм, ладно, давай обсудим. В лисповой записи (push "/foo" (gethash (list "file.txt" 777) hash)) я вижу: (поместить "/foo" <в> (элемент <сопоставленный с ключём> "список <из> "file.txt" 777" <кладовки> hash). Где тут хоть одна лишняя? Попробуй сократить логическую длину фразы на две ссущности так, чтобы смысл не потерялся. Теперь распиши питоний код аналогично и посмотрим, есть ли там чтонть лишнее.
> Вы тут так пиарите РФВС, что я его нашёл поиском и прочитал. Фигня какая-то
Думаю, его подредактировали. Я в реальном времени читал - очень повеселился. Впрочем, на вкус и цвет...
> А куда делся Луговской? Или его R00T таки нашёл?
Луговской сразу пропал на некоторое время, потом снова возник, но стал появляться гораздо реже, потом пропал окончательно. Периодически появлялись персонажи с очень похожими манерами, но другими никами. Слухи ходят разные - что он нашел работу (за бугром) и зарабатывает неплохие деньги, что он толкает свой проект (что-то с Лиспом и DSL), а что на самом деле - ХЗ.
R00T до него добираться не стал - разум взял верх над чувствами.
Про небесную дискету - я даже и не помню, что это такое :/
> Мне этот топик больше нравится.
Он более полезен с практической точки зрения, однозначно :)
>> А это самый главный вопрос и есть при промышленном программировании. Какой язык позволяет сделать проект быстрее и лучше, тот и выбирается для применения.
> ну и много ты видел, чёбы _выбирали_?
Я видел неоднократно. И сам выбирал - не только языки. Это не всегда получается, и бывает, что за выбор приходится побороться - но ты же треть жизни на работе проводишь, бороться есть за что.
> Ну, собственно, потому, что в C++ совершенно справедливо не определяется никаких отношений упорядочения для пользовательских типов.
Какую ты видиш в этом справедливось и какой сакральный смысл отличять пользовательские типы от всех остальных?
> И не менее справедливо требуется, чтобы такое отношение было определено для типов, являющихся ключами таблицы.
Почему такое справедливо? В лиспе ключи одново и тово же хеша могут иметь какой угодно тип, независимо от тово, какой тип имеют другие ключи. Какой смысел делать такое ограничение?
> Опять же, то, что в языке нет встроенной абстракции, и то, что он не может ею оперировать - это разные вещи.
так С++ может оперировать с абстракцией? Каков будет результат операции "a != b" если a - хеш-таблица, а b - число 3? Очевидно, для достаточно абстрактной операции сравнения результат должен быть логическое 0, ибо оне неэквивалентны. А в с++ как с этим?
> А потом мы добавим в алгоритм обхода разрешение симлинков, и кю.
возможно и так. Прикинь теперь изменения, требуемые для добавления корректной работы с симлинками в лисповой и с++ проге
> Короче, тезис о превосходстве лиспа "на порядки" лично мною отвергается. Даже не в разы.
ну, твоё право. Однако почему всётаки с++ прога получилось на порядки крупнее и сложнее логически?
> Очевидно, для достаточно абстрактной операции сравнения результат должен быть логическое 0, ибо оне неэквивалентны.
"Неэквивалентность" - это сравнение адресов этих объектов, с этим Си++ всё нормально. А операция сравнения на равенство не имеет смысла, так что должна бы возвращать NULL (в терминах SQL).
> А в с++ как с этим?
Нормально. Хочешь сравнивать - определи алгоритм сравнения и оформи его в operator ==. Не определил - компилятор укажет тебе на ошибку.
> Однако почему всётаки с++ прога получилось на порядки крупнее и сложнее логически?
> Я утверждаю, что за исключением необходимости реализации некоторых примитивов, не существующих в стандартной библиотеке,
дык добавление пимитивов удлиняет логику или не?
> Не-а, не так. Любой хаскеллоид тебе расскажет, что много типов под разные задачи - это хорошо и правильно. Главное, чтобы
возможно так и есть. Но я вопрос типов не затрагивал. В лиспе типизация достаточно строгая. Но различия в типах значений проявляюцо _там_где_оно_нужно_ а не где вздумаецо. Например ты вынужден в с++ делать отдельные методы для типо add(int,int), add(float,fload) итд, которые делают одинаковое. В лиспе можно обойтись одним (add a b) который выругаецо либо когда операция к типам a и b не применима либо когда установиш ограничение вручную.
> А определение типа - это еще и документация. Твоя программа как раз низкоуровневая - она ничего не знает про файлы, она оперирует "списками длиной два из числа и строки", которые непонятно чему соответствуют. А в моей прямо на C++ написано, что "мы идентифицируем файл парой <имя, размер>".
бугога, посмешил. Ну назови переменные (file, size) и будет щястье. И (сюрпрайз! сюрпрайз!) в лиспе можно сделать классы и объекты 1:1 к твоим. Но как ты убедился на разнице в размере прог и читаемости, это только усугубит и запутает.
> Да, кстати, в этой конкретной задаче я таки мог воспользоваться прямо готовым pair<string, off_t> - для нее все нужное уже есть (operator<, в смысле).
И потом полностью переписывать если появяцо симлинки например? Или добвлять pair<string, off_t, ???> вручную?
> То говорят, что на С++ и змеюке можно легко реализовать любой уровень абстракции, то говорят, что что-то у них гвоздями прибито. Ведь либо одно, либо другое. Либо можно расширить ЯП, либо можно только производить операции над числами.
ты нефтеме совсем. Реализованная абстракция - не есть истинная абстракция а самая настоящяя конкретика. Как я приводил выше пример с оператором (не)равенства - ты можеш ево реализовать для пары обектов произвольново типа, но вопервых нужно реализовывать, вовторых если появицо обект дополнительно, для которого не успели, будет бяда. А в лиспе просто как в жизни, оно либо одинаковое либо нет.
>> Метапрограммирование не является необходимым для абстрагирования, а всего лишь поставляет синтаксический сахар.
> В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа - гирлянды скобочек и токенов (вариант переписывания парсера не рассматриваем, ибо мошенничество).
> В идеале ты доходишь до такого состояния, что фактически лисповая прога является подстрочным переводом с человеческого описания алгоритма
А оно почти так и есь ужо. Следующий шаг, когда лисповая прога являецо алгоритмом на человечьем языке, достаточно лехко реализуем но никому в сучности не нужен, ибо проги будут намного более многословные.
>> В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа - гирлянды скобочек и токенов (вариант переписывания парсера не рассматриваем, ибо мошенничество).
>ты гледел sweet-code по ссыле намного выше?
Конечно. Поэтому и написал "вариант переписывания парсера не рассматриваем, ибо мошенничество". Переписав парсер, можно придать Си вид Лиспа.
Что-то я не припомню использования psyco в тестах alioth, а без него компилируемы в машинный код Лисп против неторопливого CPython... Надо снова взглянуть.
Судя по тому, что SBCL на shootout идет близко к C/gcc, он использует компиляцию в машинный код. Питон (судя по тому, что он идет близко к Перл) компиляцию в машинный код не испльзует. Так что сравнение некорректно. Если кто-то знает больше - поправьте меня.
Нечего поправлять. Но вроде как об этом уже не один раз здесь говорилось: sbcl даже в режиме интерпретации компилирует в натив (в другое он пока компилировать не умеет?)
>>> А это самый главный вопрос и есть при промышленном программировании. Какой язык позволяет сделать проект быстрее и лучше, тот и выбирается для применения.
>> ну и много ты видел, чёбы _выбирали_?
> Я видел неоднократно. И сам выбирал - не только языки. Это не всегда получается, и бывает, что за выбор приходится побороться - но ты же треть жизни на работе проводишь, бороться есть за что.
я в основном видел "выборы" типо "делфи или васик? Ладно, йух с им, пускай буде делфи" или "на делфях конешно. на чём же ещё?" которые полноценным выбором назвать немогу. Ибо достоинства/недостатки даже не рассматривались.
>> Очевидно, для достаточно абстрактной операции сравнения результат должен быть логическое 0, ибо оне неэквивалентны.
> "Неэквивалентность" - это сравнение адресов этих объектов, с этим Си++ всё нормально. А операция сравнения на равенство не имеет смысла, так что должна бы возвращать NULL (в терминах SQL).
А зачем нам sql? эквивалентнось ты путаеш с "самим себе" а эквивалентнось - если применить к вдум разным любую одинаковую операцию - получиш одинаковый результат. Хм, причём тут адрес?
>>> В Лиспе все его метапрограммные конструкции имеют привычный синтаксис Лиспа - гирлянды скобочек и токенов (вариант переписывания парсера не рассматриваем, ибо мошенничество).
>> ты гледел sweet-code по ссыле намного выше?
> Конечно. Поэтому и написал "вариант переписывания парсера не рассматриваем, ибо мошенничество". Переписав парсер, можно придать Си вид Лиспа.
можно, факт. А где тут мошеничество? Это более-менее "стандартная" возможнось, сравнительно несложная, а в случяе с сями придёцо gcc переписывать - обломаешсё.
>> sbcl даже в режиме интерпретации компилирует в натив
> Тогда сравнение с Python без psyco просто не имеет смысла.
а кто те сказал чё сравнение лиспа с недоделанным плохо имплементированым лиспом вообще имеет смысел? Мы же тут так просто, треплемсё и пиписками меримся. Пока получяецо чё наша таки длиннее.
С чего бы? Эйфель (и куча других) компилируют с Си, и нормально. А Лисп-подобную запись перевести в Си куда легче, чем Эйфель.
>>> Очевидно, для достаточно абстрактной операции сравнения результат должен быть логическое 0, ибо оне неэквивалентны.
>> "Неэквивалентность" - это сравнение адресов этих объектов, с этим Си++ всё нормально. А операция сравнения на равенство не имеет смысла, так что должна бы возвращать NULL (в терминах SQL).
>А зачем нам sql
Это для примера - там трехзначная логика.
> эквивалентнось ты путаеш с "самим себе"
То есть для тебя "эквивалентность" - это алгоритм сравнения, определенный таким образом, что на объектах разных классов дает "ложь"? Это несложно реализовать в Си++.