Oberon space

General Category => Общий раздел => Тема начата: valexey от Февраль 20, 2011, 10:48:17 pm

Название: Парадокс Блаба.
Отправлено: valexey от Февраль 20, 2011, 10:48:17 pm
Первоисточник тут: http://www.nestor.minsk.by/sr/2003/07/30710.html
Если лень читать всю цитату -- сама суть парадокса выделена жирным шрифтом, но я бы советовал таки прочитать целиком, иначе нюансы уловить не удастся.
Цитировать
Что же в Lisp'е такого прекрасного? Если он такой замечательный, почему его не используют все? Казалось бы, риторические вопросы, но на самом деле на них есть прямые ответы. Lisp настолько хорош не тем, что в нем есть некое волшебное качество, видимое только его приверженцам, а тем, что он — самый мощный язык программирования из существующих.
И причина того, что все вокруг пишут не на Lisp'е, заключается в том, что выбор языка программирования — вопрос не только технологии, но также и привычки, а ничто не меняется так медленно, как привычки. Конечно, оба эти тезиса требуют разъяснений.

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

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

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

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

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

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

Возьмем Cobol. Cobol — язык высокого уровня, так как компилируется в машинный язык. Но станет ли кто-нибудь утверждать, что по мощности Cobol эквивалентен, скажем, Python'у? Возможно, он ближе к машинному языку, чем Python.

А как насчет Perl четвертой версии? В Perl 5 в язык были добавлены лексические замыкания (lexical closures). Большинство Perl хакеров согласятся, что Perl 5 мощнее, чем Perl 4. Но раз вы это признали, вы признали, что один высокоуровневый язык может быть мощнее другого. Из этого неизбежно следует, что использовать нужно самый мощный язык.

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

Программисты очень привязываются к своим любимым языкам, а я не хочу оскорбить ничьи чувства, поэтому я объясню свою позицию, используя гипотетический язык с названием Блаб.

Блаб попадает в середину континуума абстрактности. Это не самый мощный язык, но он мощнее, чем Cobol или машинный язык.
И на самом деле, наш гипотетический программист на Блабе не будет использовать ни Cobol, ни машинный код. Для машинных кодов есть компиляторы. Что же касается Cobol'а, наш программист не знает, как на этом языке вообще что-то можно сделать. В Cobol'е даже нет некой возможности X, присутствующей в Блабе.

Когда наш гипотетический Блаб-программист смотрит вниз на континуум мощности языков, он знает, что смотрит вниз. Менее мощные, чем Блаб, языки явно менее мощны, так как в них нет некой особенности, к которой привык программист. Но когда он смотрит в другом направлении, вверх, он не осознает, что смотрит вверх. То, что он видит, — это просто "странные" языки. Возможно, он считает их одинаковыми с Блабом по мощности, но со всяческими сложными штучками. Блаба для нашего программиста вполне достаточно, так как он думает на Блабе.

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

Используя метод индукции, приходишь к выводу, что только те программисты, которые понимают самый мощный язык, в состоянии осознать полную картину разницы в мощности между различными языками (видимо, именно это имел ввиду Эрик Реймонд, когда говорил о том, что Lisp сделает вас лучше как программиста). Следуя парадоксу Блаба, нельзя доверять мнению других: другие программисты довольны тем языком, который используют, потому что этот язык определяет способ их программистского мышления.


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

Пять языков, которые советует хакерам Эрик Реймонд, находятся в разных точках континуума мощности, и то, где они находятся относительно друг друга, — тонкий вопрос. Я скажу, что Lisp находится на вершине континуума. И чтобы поддержать это утверждение, я скажу о том, чего мне не хватает, когда я смотрю на остальные пять языков. Как же можно что-то сделать с ними, думаю я, без свойства Z? И самое большое Z — это макросы. (Рассматривать макросы как отдельное свойство — это немного неправильно. На практике их польза увеличивается такими свойствами Lisp'а, как лексические замыкания и частичная параметризация (rest parameters).

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

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

Программы, которые пишут программы? И когда же такое может понадобиться?

Не очень часто, если вы думаете на Cobol'е. И постоянно, если вы думаете на Lisp'е. Было бы удобно, если бы я дал пример мощного макроса и сказал бы: "Вот! Смотрите!". Но если бы я и привел пример, для того, кто не знает Lisp, он выглядел бы не более чем белиберда. Рамки данной статьи не позволяют изложить все необходимое для понимания подобного примера. В книге Ansi Common Lisp я старался излагать материал как можно быстрее, но даже так я не добрался до макросов раньше страницы 160.
Однако мне кажется, что я могу дать убедительный аргумент. Исходный текст редактора Viaweb на 20-25 процентов состоял из макросов. Макросы сложнее писать, чем обычные функции Lisp'а, и считается дурным тоном использовать их там, где можно без них обойтись. Поэтому каждый макрос в той программе был необходим. Это значит, что примерно 20-25 процентов кода в программе делают то, что нельзя просто сделать на других языках.

Как бы скептически ни относился Блаб-программист к моим заявлениям о таинственной мощи Lisp'а, это должно его заинтересовать. Мы не писали этот код для своего собственного развлечения. Мы были маленькой компанией, и программировали так, как только могли, чтобы возвести технологический барьер между нами и нашими конкурентами.

Пытливый читатель может задаться вопросом, а нет ли здесь взаимосвязи? Некоторая большая часть кода делала нечто, что очень сложно сделать на других языках. Получившееся в результате программное обеспечение делало то, что программное обеспечение наших соперников делать не могло. Возможно, между этими фактами есть связь. Я советую вам подумать в этом направлении. Возможно, это все не просто старческие бредни.
Название: Re:Парадокс Блаба.
Отправлено: igor от Февраль 21, 2011, 03:54:01 am
Не осилил  :)
Первое впечатление от уже прочитанного - у автора в голове "каша", и взгляд очень однобокий. Требуется время на осмысление.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 05:11:11 am
Здесь уже обсуждали http://forum.oberoncore.ru/viewtopic.php?f=61&t=1914&hilit=%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81
Отрицательное отношение к макросам я с тех пор не изменил.
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 21, 2011, 05:23:34 am
Здесь уже обсуждали http://forum.oberoncore.ru/viewtopic.php?f=61&t=1914&hilit=%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81
Отрицательное отношение к макросам я с тех пор не изменил.
Скажите, в чём принципиальное отличие макросов от подпрограмм, кроме того, что макросы работают во время компиляции, а подпрограммы -- во время выполнения программы?
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 05:47:24 am
Принципиальное отличие в том, что они должны сработать у меня в голове, чтобы я представлял себе текст программы.
Вам понравятся макросы, которые порождают другие макросы, которые порождают текст программы? Мне - нет. И даже один уровень не нравится.
А вообще, т.к. у меня по определению нет опыта работы с макросами, тут были бы крайне желательны примеры.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 07:29:54 am
Макросы это мелкая частность, пример по сути. Сам парадокс то поинтересней будет.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 07:46:38 am
А если уж заговорили зачем-то о лиспе.. Лисп действительно великий язык. Он стирает грань между разработчиком компилятора и прикладным программистом. Там нет этой дурацкого разделения, порога между тем и другим. И это правильно.

Благодаря тому, что когда программист на лиспе пишет программу, он непосредственно видит синтаксическое дерево, у него не возникает в последствии проблем с его модификацией/созданием програмным способом, т.е. макросами. В отличае от языков где наличиствует т.н. "синтаксис" (тот же Оберон например). В этих языках программист может писать программу и не догадываться что такое синтаксическое дерево вообще, и как оно выглядит на его языке. Поэтому, когда ему говорят про макросы, он сразу кричит "нихачу, нимагу, нинужны!".

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

2Geniepro: Зефиров помнится критиковал лисп за то, что эти самые макросы-спецформы не являются нормальными функциями, т.е. их не передать в качестве аргумента в другую функцию. А выглядят они в точности также, т.е. синтаксически не отличимы от обычных функций.
Название: Re:Парадокс Блаба.
Отправлено: kemiisto от Февраль 21, 2011, 09:42:39 am
Лисп действительно великий язык. Он стирает грань между разработчиком компилятора и прикладным программистом. Там нет этой дурацкого разделения, порога между тем и другим. И это правильно.
И это совершенно НЕправильно. И вот почему.

Благодаря тому, что когда программист на лиспе пишет программу, он непосредственно видит синтаксическое дерево [...]
Нет, нет и ещё раз нет. Мопед не мой, как говорится. :P Info21 многократно декларировал это. Так что повторюсь, в каком то смысле. Программы пишут не только программисты. И даже не столько. На своём примере, я - химик. Поверьте на слово, когда, я пишу программу, я не вижу (и НЕ ХОЧУ видеть) никаких синтаксических деревьев и прочего, потому, что я не знаю, что это такое и знать НЕ ХОЧУ. У меня нет времени на всю эту ерунду. И смотрю я на все эти вещи не снизу-вверх, а эм... сбоку что-ли.

valexey, вот ты же программист? В смысле, работаешь программистом. Тогда, тебе трудно будет "кожей почувствовать", что значит "нет времени на ерунду". Но уж поверь, таки нет.

Собственно, Лисп именно поэтому никогда популярен и не будет. Не нужно никому ваше синтаксическое древо => и Лисп не нужен. ;)
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 09:53:58 am
Таки да, я работаю программистом.

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

Если у нас есть специалист в некой предметной области который сам что-то программит, то ничто не мешает дать ему тот язык, который ему будет максимально удобен или к которому он просто привык. Все это делается элементарно на том же например лиспе. Посмотрите на Racket -- там реализован диалект Алгола-60. Думаю без проблем там можно и оберон реализовать. По сути ядро -- это например Лисп или иной мощный язык который позволяет быстро и просто создавать EDSL/DSL под задачу или даже под специалиста. Специалист предметной области счастлив, программисты тоже счастливы, ибо у них гибкий мощный инструмент позволивший быстро и максимально качественно осчастливить специалиста.

Т.е. я не вижу никаких противоречий.
Название: Re:Парадокс Блаба.
Отправлено: kemiisto от Февраль 21, 2011, 10:23:45 am
Если у нас есть специалист в некой предметной области который сам что-то программит, то ничто не мешает дать ему тот язык, который ему будет максимально удобен или к которому он просто привык. Все это делается элементарно на том же например лиспе.
Так уже всё дадено. А кое-что было дадено аж до Лиспа. :D

Т.е. я не вижу никаких противоречий.
Противоречие в том, что это советы хакерам. Там даже есть явная отсылка на некого Реймонда. А программы пишут не только (и не столько) хакеры. Поэтому аргументы про какую-то там мощность Лиспа не совсем уместны. Это сферическая мощность в вакуууме, ей воспользуются единицы.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 10:26:56 am
Проверить работу макроса в лиспе очень просто -- запускаем  макрос и результат его работы распечатываем. Проверяем.
Во-первых, я бы не сказал, что это просто. Кроме того, могут быть всякие нюансы.
Во-вторых, можете привести пример гениального использования макросов? Типа, а вот здесь языки без макросов сосут.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 10:45:01 am
Если у нас есть специалист в некой предметной области который сам что-то программит, то ничто не мешает дать ему тот язык, который ему будет максимально удобен или к которому он просто привык. Все это делается элементарно на том же например лиспе.
Так уже всё дадено. А кое-что было дадено аж до Лиспа. :D
Это фортран что-ли? :-)

Т.е. я не вижу никаких противоречий.
Противоречие в том, что это советы хакерам. Там даже есть явная отсылка на некого Реймонда. А программы пишут не только (и не столько) хакеры. Поэтому аргументы про какую-то там мощность Лиспа не совсем уместны. Это сферическая мощность в вакуууме, ей воспользуются единицы.
Моя не знать что такое "хакеры". Так что лучше подобрать какое-нибудь другое слово :-)
Название: Re:Парадокс Блаба.
Отправлено: kemiisto от Февраль 21, 2011, 10:51:47 am
Это фортран что-ли? :-)
;D Ога.

Моя не знать что такое "хакеры". Так что лучше подобрать какое-нибудь другое слово :-)
Это не ко мне, а к автору. У него там это словечко проскакивает. Ну, пускай будут "профессиональные программисты". "Профессиональность" означает здесь выбранную профессию, с помощью которой зарабатываешь на кусок хлеба.  :)
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 10:55:34 am
Проверить работу макроса в лиспе очень просто -- запускаем  макрос и результат его работы распечатываем. Проверяем.
Во-первых, я бы не сказал, что это просто. Кроме того, могут быть всякие нюансы.
Гм. А какие проблемы в распечатке получившегося AST'a?

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

Ну-у, чтобы не быть голословным... Например наш любимый пример -- управление ресурсом. Т.e. семантика такова -- если сказал А (получил ресурс), то ты просто обязан как можно быстрее сказать и Б (освободить ресурс). Говорить Б вручную не предлагать -- обязательно кто-нибудь где-нибудь забудет сказать Б.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 10:58:59 am
Ну и еще пример -- описание конечных автоматов. Т.e. мы хотим на этапе компиляции проверить корректность конечного автомата.

Вообще эти самые макросы (или иной механизм выше уровнем чем банальное структурное программирование) полезны, всегда когда нужно нечто вроде EDSL соорудить.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 12:15:01 pm
Ну, не видите проблем, бог вам судия.
А все-таки, реальный пример-то можете дать?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 12:28:32 pm
Ну, не видите проблем, бог вам судия.
А все-таки, реальный пример-то можете дать?
А что подразумевается под реальным примером? Прям таки код?
А где именно использовать это можно и нужно и где без подобных высокоуровневых средств не обойтись, я указал. Хотя быть может я и не прав конечно и на Обероне эти задачи таки можно решить приемлемым способом...
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 12:39:23 pm
Именно код. Хорошо бы на Лиспе. С комментариями для бестолковых (себя имею в виду  :)).
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 21, 2011, 12:51:48 pm
Во-вторых, можете привести пример гениального использования макросов? Типа, а вот здесь языки без макросов сосут.
В C# есть оператор using, который, в частности, позволяет автоматически закрывать файл после того, как с ним будет проведена какая-то работа:// точно на память работу с файлами в .NET не помню,
// просто пример как это может выглядеть

using (File file = File.Open("filename.txt"))
{
    // что-то делаем с файлом file

} // тут он автоматически закрывается
Когда в С# не было этого оператора (вроде когда-то его не было, может ошибаюсь), приходилось (да и теперь в том же С или Обероне приходится) закрывать файл вручную. Естественно, можно было по запарке забыть это дело сделать.

Макросы позволяют самостоятельно модифицировать язык, добавить этот самый "using":; условный синтаксис:

(defmacro with-open-file (file filename body)
    (let (,file (open-file filename)
      ,@body
      (close-file ,file))))

; пример использования:

(with-open-file file "filename.txt"
    ( ; что-то делаем с файлом file
    )) ; тут он автоматически закрывается
Ну, в некоторых языках некоторые возможности макросов можно реализовать и без макросов. Например, в Хаскелле:with_open_file :: FilePath -> IOMode -> (Handle -> IO a) -> IO a
with_open_file filename mode action = do
    fhnd   <- openFile filename mode
    result <- action fhnd
    hClose fhnd
    return result

-- Пример использования

do  ...
    with_open_file "filename.txt" ReadMode $ \\file -> do
        ... -- что-то делаем с файлом file
    -- тут он автоматически закрывается
Но Хаскелл -- ленивый язык, в нём такие фокусы проходят.
В сях тоже можно соорудить макрос, но именно -- какой-никакой, а макрос.
А в оберонах?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 12:56:47 pm
Цитировать
If you have a scarce resource that you need to manage the lifecycle of explicitly instead of tying it into a GC finalization, then the approximate equivalent of the try/finally code on FinalizeInsteadOfProperDestructor is
  (let ((r (allocator-for-my-scarce-resource)))
    (unwind-protect
    (progn
       (foo)
     (bar)
     (etc))
    (deallocate-my-scarce-resource r)))
(UNWIND-PROTECT means "evaluate the first argument. When you stop with the first argument, for whatever reason, also run the subsequent args" - if you like, "try" the first arg, and "finally" do the other args)
You can't depend on some client programmer always remembering to do this, so you make it easy for them. Write a macro, which would probably be called WITH-SCARCE-RESOURCE in this case, that wraps the unwind-protect so the user never has to remember
(defmacro with-scarce-resource ((name) &body body)
    `(let ((,name (allocator-for-my-scarce-resource)))
    (unwind-protect
     (progn
     ,@body)
   (deallocate-my-scarce-resource r))))
so now we just have to do
(with-scarce-resource (r)
  (foo)
 (bar)
 (etc))
Источник: http://www.c2.com/cgi/wiki?LispMacro (http://www.c2.com/cgi/wiki?LispMacro)
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 01:07:21 pm
Но Хаскелл -- ленивый язык, в нём такие фокусы проходят.
А кстати, как тут помогает ленивость? Я не вижу проблем сделать то же самое на энергичном языке с замыканиями.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 01:17:26 pm
Пока не разобрался с кодом - вопрос: а что мешает невнимательным НЕ использовать макрос и нарушать дисциплину работы с ресурсом?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 01:23:47 pm
Пока не разобрался с кодом - вопрос: а что мешает невнимательным НЕ использовать макрос и нарушать дисциплину работы с ресурсом?
В хаскеле помешает система типов. Оно просто не скомпилируется.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 01:25:57 pm
Ну так там, к счастью, и не макрос.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 01:34:47 pm
Ну так там, к счастью, и не макрос.
А это без разницы на самом деле.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 02:18:04 pm
Тогда не понял - об чем базар?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 02:28:16 pm
Тогда не понял - об чем базар?
Базар о парадоксе Блаба :-)

Конкретно по этому случаю -- макросы в лиспе и лямбда в хаскеле позволяет реализовать функциональность, а система типов позволяет запретить небезопасное использование ресурсов.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 02:36:45 pm
Пардон, в статье про Хаскел ни слова. Более того, Грейхем считает, что он хуже Лиспа.
Поэтому я предлагаю обсудить (и попытаться опровергнуть) тезис:
"Любой макрос демонстрирует дефект в языке или в голове программиста".

Я его привожу по памяти, если кто-нибудь найдет первоисточник, буду очень благодарен.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 03:11:01 pm
А Грейхем про него вообще что-то знает? :-)

Я не буду опровергать тезис, что "Любой макрос демонстрирует дефект в языке или в голове программиста", я его просто дополню тезисом, что "во всех языках есть дефекты". Можно сделать язык который будет достаточен для 80-90 процентов кода любого проекта. Однако оставшиеся 10-20 процентов кода... Они у каждого проекта свои. И чтобы удовлетворить на 100 процентов потребности всех проектов придется столько в язык понапихать... Посмотри на C#. Аду и другие языки идущие тем путем. В язык добавляют и добавляют редкоиспользуемые фичи, язык пухнет, пухнут голову у использующих его, пухнут головы у писателей компилятора и либ.

Много лучше когда в языке есть просто возможности (те же макросы например) которые позволяют реализовать необходимое в данном проекте, но отсутствующее в языке, просто в виде либы. Либа пишется быстро. На другие проекты не влияет, на сложность языка не влияет. Влияет только на тот код, где она явно импортирована. Очень удобно и правильно. В основном с помощью этого строится архитектурообразующие конструкции для данного проекта.
Название: Re:Парадокс Блаба.
Отправлено: vlad от Февраль 21, 2011, 03:11:43 pm
Пардон, в статье про Хаскел ни слова. Более того, Грейхем считает, что он хуже Лиспа.
Поэтому я предлагаю обсудить (и попытаться опровергнуть) тезис:
"Любой макрос демонстрирует дефект в языке или в голове программиста".

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

Да чего тут обсуждать :) Тут простой диагноз: человек измучился с сишными макросами :)
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 03:21:23 pm
Ну, таки да, сишные макросы они с одной стороны ужасны, с другой стороны до смешного мало могут. Там AST'ом и не пахнет.

На самом деле я склонен рассматривать как аналог лисповых макросов шаблоны в С++. Впрочем, относительно лиспа они также убоги. А в ghc есть расширение под названием TH (Template Haskell) иногда весьма полезно бывает. Ну и в D2 есть механизм позволяющий писать программы работающие на этапе компиляции. Прямо на подмножестве D2 писать. Опять же очень удобно для всяких EDSL, в частности для тех же конечных автоматов.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 21, 2011, 03:27:23 pm
А Грейхем про него вообще что-то знает? :-)
Почему-то у меня отложилось в памяти, что он считает недостатком требование, чтобы в списке все элементы были одного типа. Но сейчас не смог этого найти.
Может я все переврал и возвел напраслину?...  ???
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 21, 2011, 03:32:54 pm
Ну-у. Хм... Ничто не мешает иметь список состоящий из элементов типа Data.Dynamic, в которых будет уже содержаться все что угодно. Динамическая типизация реализуется посредством статической, но вот обратное не верно.
Название: Re:Парадокс Блаба.
Отправлено: igor от Февраль 22, 2011, 04:38:44 am
Программы пишут не только программисты. И даже не столько. На своём примере, я - химик.
Не программист, который пишет программы, - таки, программист. (С)  ;)
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 22, 2011, 05:48:11 am
Но Хаскелл -- ленивый язык, в нём такие фокусы проходят.
А кстати, как тут помогает ленивость? Я не вижу проблем сделать то же самое на энергичном языке с замыканиями.
Да, я наверное неточно выразился. Хотел поправиться, что дело в функциональности языка, но потом вспомнил, что в том же смоллтоке будет выглядеть примерно так же, как и в хаскелле.
Тем не менее, иногда удобнее не функцию передавать, а просто некое вычисление/действие, а ленивость языка позволяет отложить выполнение этого вычисления до тех пор, пока оно не понадобится. Но тут, скорее, чисто синтаксическое удобство.
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 22, 2011, 05:58:27 am
А Грейхем про него вообще что-то знает? :-)
Почему-то у меня отложилось в памяти, что он считает недостатком требование, чтобы в списке все элементы были одного типа. Но сейчас не смог этого найти.
Может я все переврал и возвел напраслину?...  ???
То, что в списке все элементы одного типа -- скорее достоинство, чем недостаток -- проверка типов во время компиляции чаще полезна, чем неудобна.

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

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

В таком случае может быть удобнее объявить класс типов с требуемыми операциями, которые будут проделываться с элементами в этом списке, и объявлять, что в этом списке могут быть значения любых типов данных, входящих в этот класс (экзистенциальные типы в терминах хаскелла).
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 22, 2011, 06:07:22 am
Вообще, Пол Грэм (автор этой статьи) рекомендовал использовать макросы только в том случае, если они сокращают код раз в двадцать. Он признавал, что обильное и неуместное использование макросов способно только запутать и усложнить понимание программы.
Да даже если код благодаря макросам может быть уменьшен всего лишь в 10 раз -- разве это не повод для их использования.
К сожалению, не могу придумать такого примера, где было бы уменьшение кода на порядок. Однако иногда жалею, что в том же C# нет даже простых сишных макросов -- иногда они позволили бы не делать тупой копи-паст.

Вообще, это общая проблема -- демонстрация полезности какой-то технологии на игрушечных примеров. Вот тот же ООП -- кому-то он реально помогает бороться со сложностью ПО, но на мелких примерах выглядит, наоборот, удручающе громоздко и неудобно...
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 22, 2011, 10:02:42 am
Однако иногда жалею, что в том же C# нет даже простых сишных макросов -- иногда они позволили бы не делать тупой копи-паст.
Ну так и приведите пример. Мне, например, не приходилось жалеть.
И, кстати, где эти примеры на Лиспе с уменьшением размера кода в 20 раз?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 22, 2011, 10:12:21 am
Дженерики в шарпе и шаблоны в плюсах по сути частные случаи макросов (в понятии лиспа конечно а не Си). Польза от дженериков и шаблонов думаю всем очевидна.
Название: Re:Парадокс Блаба.
Отправлено: Geniepro от Февраль 22, 2011, 10:43:55 am
Однако иногда жалею, что в том же C# нет даже простых сишных макросов -- иногда они позволили бы не делать тупой копи-паст.
Ну так и приведите пример. Мне, например, не приходилось жалеть.
И, кстати, где эти примеры на Лиспе с уменьшением размера кода в 20 раз?
Ну вот мой пример:if (obj1[i].abracadabra1 != obj2[i].other_abracadabra1)
{
    какие-то действия с obj1[i].abracadabra1:
   
    obj1[i].abracadabra1 = obj2[i].other_abracadabra1;

    какие-то другие действия с obj1[i].abracadabra1:
}

if (obj1[i].abracadabra2 != obj2[i].other_abracadabra2)
{
    какие-то действия с obj1[i].abracadabra2:
   
    obj1[i].abracadabra2 = obj2[i].other_abracadabra2;

    какие-то другие действия с obj1[i].abracadabra2:
}

if (obj1[i].abracadabra3 != obj2[i].other_abracadabra3)
{
    какие-то действия с obj1[i].abracadabra3:
   
    obj1[i].abracadabra3 = obj2[i].other_abracadabra3;

    какие-то другие действия с obj1[i].abracadabra3:
}

if (obj1[i].abracadabra4 != obj2[i].other_abracadabra4)
{
    какие-то действия с obj1[i].abracadabra4:
   
    obj1[i].abracadabra4 = obj2[i].other_abracadabra4;

    какие-то другие действия с obj1[i].abracadabra4:
}

if (obj1[i].abracadabra5 != obj2[i].other_abracadabra5)
{
    какие-то действия с obj1[i].abracadabra5:
   
    obj1[i].abracadabra5 = obj2[i].other_abracadabra5;

    какие-то другие действия с obj1[i].abracadabra5:
}
Типы у этих abracadabra1..abracadabra5 -- разные, не совместимые (в смысле нет там наследований всяких).

Были бы макросы (хоть сишные), можно было бы сделать так:
#define do_what_we_need(obj1,obj2)          \\
    if (obj1 != obj2)                       \\
    {                                       \\
        какие-то действия с obj1:           \\
                                            \\
        obj1 = obj2;                        \\
                                            \\
        какие-то другие действия с obj1;    \\
    }

do_what_we_need(obj1[i].abracadabra1, obj2[i].other_abracadabra1);
do_what_we_need(obj1[i].abracadabra2, obj2[i].other_abracadabra2);
do_what_we_need(obj1[i].abracadabra3, obj2[i].other_abracadabra3);
do_what_we_need(obj1[i].abracadabra4, obj2[i].other_abracadabra4);
do_what_we_need(obj1[i].abracadabra5, obj2[i].other_abracadabra5);

А по поводу 20-кратного уменьшения кода, да ещё и на Лиспе -- это Вы лучше у Пола Грэма спросите, у него наверняка есть таких примеров...
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 22, 2011, 11:54:01 am
Дженерики в шарпе и шаблоны в плюсах по сути частные случаи макросов (в понятии лиспа конечно а не Си). Польза от дженериков и шаблонов думаю всем очевидна.
Дженерики в шарпе - это хорошо. Макросы - это гов плохо. Зачем мешать такие вещи?
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 22, 2011, 12:05:49 pm
У меня такое ощущение складывается, что под макросом постоянно подразумевается то недоразумение что имеется в Си (которое, в частности, не ограничено по области действия, не может анализировать типы и т.д. и т.п., и вообще являет собою примитивнейший случай банальной текстовой замены). Так вот в лиспе макросы это совсем другое :-)

Кстати, а что это мы на макросах зациклились? Они тут вторичны абсолютно. Первичен парадокс Блаба. Впрочем, такое горячее обсуждение макросов является как бы живой иллюстрацией оного парадокса.
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 22, 2011, 12:33:11 pm
1. - В чем заключается парадокс Блаба?
2. - В парадоксе Блаба.
далее см. пункт 1.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 22, 2011, 12:43:43 pm
Ну как же? Вполне четкое определение дадено:
Цитировать
Блаб попадает в середину континуума абстрактности. Это не самый мощный язык, но он мощнее, чем Cobol или машинный язык.
И на самом деле, наш гипотетический программист на Блабе не будет использовать ни Cobol, ни машинный код. Для машинных кодов есть компиляторы. Что же касается Cobol'а, наш программист не знает, как на этом языке вообще что-то можно сделать. В Cobol'е даже нет некой возможности X, присутствующей в Блабе.

Когда наш гипотетический Блаб-программист смотрит вниз на континуум мощности языков, он знает, что смотрит вниз. Менее мощные, чем Блаб, языки явно менее мощны, так как в них нет некой особенности, к которой привык программист. Но когда он смотрит в другом направлении, вверх, он не осознает, что смотрит вверх. То, что он видит, — это просто "странные" языки. Возможно, он считает их одинаковыми с Блабом по мощности, но со всяческими сложными штучками. Блаба для нашего программиста вполне достаточно, так как он думает на Блабе.

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

Используя метод индукции, приходишь к выводу, что только те программисты, которые понимают самый мощный язык, в состоянии осознать полную картину разницы в мощности между различными языками
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 22, 2011, 01:08:06 pm
Это описание "когнитивной слепоты". А парадокс вообще отсутствует.
Мне в статье интересны 2 тезиса:
1. Лисп - самый мощный язык всех времен и народов.
2. Значительная часть его мощности обеспечивается за счет макросов.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 22, 2011, 01:45:00 pm
Это описание "когнитивной слепоты". А парадокс вообще отсутствует.
Термин "когнитивная слепота" слишком общий и слишком мутный. В частности этих самых подвидов слепоты я нашел сразу несколько штук (это общеупотребимые термины).

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

Мне в статье интересны 2 тезиса:
1. Лисп - самый мощный язык всех времен и народов.
2. Значительная часть его мощности обеспечивается за счет макросов.
А мне не очень, потому как это ж очевидно :-) Лисп по сути является метаязыком. Но он не единственный такой. Из него хороший метаязык получается благодаря двум вещам:
1) Отсутствие синтаксиса.
2) Наличие макросов.
Первый пункт обучает человеческий мозг мыслить сразу в терминах AST и семантики.
Второй пункт позволяет модифицировать семантику и манипулировать AST'ом.
Т.o. отсутствует разрыв между первым и вторым, как в иных языках. И это хорошо.

Однако если вдруг кто-то считает что это плохо, то хотелось бы увидеть пример где наглядно было бы видно, что это плохо.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 22, 2011, 02:59:53 pm
Если хочется посравнивать лисп с другими языками, вот например табличка Lisp VS Python: http://love5an.livejournal.com/356033.html
Название: Re:Парадокс Блаба.
Отправлено: Peter Almazov от Февраль 23, 2011, 07:38:38 am
У меня такое ощущение складывается, что под макросом постоянно подразумевается то недоразумение что имеется в Си (которое, в частности, не ограничено по области действия, не может анализировать типы и т.д. и т.п., и вообще являет собою примитивнейший случай банальной текстовой замены). Так вот в лиспе макросы это совсем другое :-)
Тут было бы полезно попытаться дать определения макроса.
Шарпные дженерики не должны под него попадать - там есть существенная поддержка в run-time.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 23, 2011, 11:38:40 am
У меня такое ощущение складывается, что под макросом постоянно подразумевается то недоразумение что имеется в Си (которое, в частности, не ограничено по области действия, не может анализировать типы и т.д. и т.п., и вообще являет собою примитивнейший случай банальной текстовой замены). Так вот в лиспе макросы это совсем другое :-)
Тут было бы полезно попытаться дать определения макроса.
Шарпные дженерики не должны под него попадать - там есть существенная поддержка в run-time.
А у лиспа макросы могут работать и в рантайме, т.е. не только на этапе компиляции. Код это данные.
Я ж говорю, шарповые дженерики это частный случай лисповых макросов :-)
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 23, 2011, 11:45:49 am
Кстати, в .нете рантайм поддержка дженериков -- это ж чистая оптимизация (чтобы код не раздувался). На семантику это не влияет.
Название: Re:Парадокс Блаба.
Отправлено: Илья Ермаков от Февраль 23, 2011, 03:39:40 pm
Как так только оптимизация?

Почему забываете про случай, когда загружается динамически сборка, в которой используется новый инстанс дженерика. Должен быть механизм, который эту сборку догенерирует, из того определения дженерика, которое уже сидит у меня в памяти.
Название: Re:Парадокс Блаба.
Отправлено: valexey от Февраль 23, 2011, 03:49:28 pm
Забываю, потому, что с .нетом возился крайне мало. Таки та, видимо динамическое инстанцирование с кодогенерацией там используется (в отличае от той же явы например). Впрочем, тем больше .нетные дженерики становятся похожи на лисповые макросы :-)
Название: Re: Парадокс Блаба.
Отправлено: Peter Almazov от Ноябрь 14, 2011, 11:48:58 am
Случайно наткнулся на хорошую статью Macros: why they're evil (http://scienceblogs.com/goodmath/2007/12/macros_why_theyre_evil.php).
Там в комментариях многие защищают макросы.
Ознакомился с аргументами. Рвотный рефлекс не уменьшился.
Название: Re: Парадокс Блаба.
Отправлено: Geniepro от Ноябрь 15, 2011, 06:50:25 am
Макросы всего лишь инструмент, так же как и процедуры, функции, объекты, акторы всякие.
С чего бы этим инструментам вызывать такие эмоции?  :o
Название: Re: Парадокс Блаба.
Отправлено: DIzer от Ноябрь 15, 2011, 07:22:14 am
Ну да - вон коровцы по сути дела на них (точнее, используя вариант препроцессинга) поддержку русского языка в КП  для ББ сварганили, если я не ошибаюсь,  :) и ничего себе - работает(иначе - перепись + доработка ЯП и компилятора).
Название: Re: Парадокс Блаба.
Отправлено: Peter Almazov от Ноябрь 15, 2011, 07:36:48 am
Макросы всего лишь инструмент, так же как и процедуры, функции, объекты, акторы всякие.
С чего бы этим инструментам вызывать такие эмоции?  :o
Неопытный работник знает, что нужно делать. Опытный знает, что не надо делать.
Сразу оговорюсь, что себя не могу отнести ко вторым. Изучение функциональных языков весьма наглядно мне это демонстрирует.
Название: Re: Парадокс Блаба.
Отправлено: DIzer от Ноябрь 15, 2011, 07:42:23 am
....
Сразу оговорюсь, что себя не могу отнести ко вторым. Изучение функциональных языков весьма наглядно мне это демонстрирует.
и хорошо - иначе никто ничего бы и не делал, ибо все фигня  по сравнению с мировой революцией....  :D
Название: Re: Парадокс Блаба.
Отправлено: DIzer от Ноябрь 15, 2011, 08:07:03 am
Geniepro, слегка  перефразируя Лелика из "Бриллиантовой руки"  How to read Haskell like Python -  это не актуально,  " How to WRITE Haskell like Python and what is the GAIN you can get from"  - вот это тема... :D :D :D :D