LINUX.ORG.RU

[haskell] есть ли что-то типа reflection? (недемократизм языка?)

 


0

0

Обычная фраза: deriving (Read, Show, Eq, Ord)

Компилятор умеет выводить инстансы этих typeclass-ов. А что делать, если хочется их выводить чуть-чуть по-другому или добавить еще один, который автоматически бы выводился? (Для этого, возможно, подошло что-то похожее на reflection, патчить компилятор не предлагайте)

__________________________________________________

Недемократизм языка в моем понимании -- это

1. Частичная реализация некой фичи и одновременно отстутствие инструмента для расширения реализации этой фичи. Например в яве оператор + для сложения целых, вещественных, строк и все: комплексные, кватернионы, вектора, матрицы... складывай уже через add.

2. Невозможность смены конкретной реализации фичи (зачастую связано с п.1). Например, невозможность создать в рамках с++ свой virtual dispatch (для того, что сделать множественный virtual dispatch, т.е. п.1). В принципе, п.2 до некоторой степени неизбежен, так как иногда намного проще сделать фичу, чем API для написания фич).

__________________________________________________

Более глобальный вопрос -- а насколько хаскель демократичен? (для обеспечения демократизма разрешается использовать ключи компилятора, template haskell, ...)

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

>чтобы обертывать произвольное число аргументов, нужен уже с++0х.

видел блог http://bartoszmilewski.wordpress.com/ ? например, http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-... http://bartoszmilewski.wordpress.com/2009/09/08/template-metaprogramming-made...

поинт в том, что язык шаблонов в С++ является примитивным ФП языком, на самом деле.

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

How do you iterate over a type list? Well, there is no iteration in the metalanguge so the best you can do is to use recursion. To do that, you have to be able to separate the head of the list from its tail. Then you perform the action on the head and call yourself recursively with the tail. The head/tail separation is done using pattern matching.

Let me demonstrate a simple example from the paper Variadic Templates by Garry Powell et al. It calculates the length of a pack using recursion. First, the basic case–length-zero list:

template<>
struct count <> {
    static const int value = 0;
}
That is the full specialization of a template, so it will be tried first. Here’s the general case:
template<typename Head, typename... Tail>
struct count<Head, Tail...> {
    static const int value = 1 + count<Tail...>::value;
}

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

>ну а какая же отрасль знания занимается вопросом "качества языков программирования"?

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

с каждой разной точки зрения понимание качества разное. Поэтому тебе потребуются "отрасли знания": теория качества, поддержки и принятия решений, научный системный подход для понимания надёжности, статистической достоверности и экспериментов, с заданными _тобой_ требованиями к экспериментам.

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

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

>(насколько мне известо) нет объективных (и соостветственно доказуемых как в математике) метрик качества языков программирования

метрики чего ты хочешь получить? метрики процесса разработки? метрики программ на языке, используемом в процессе разработки? метрики вспомогательных инструментов, написанных на языке, используемом в процессе разработки? метрики понимания программистами используемых процессов, инструментов, языков?

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

Можно померять как-то вроде http://gmarceau.qc.ca/blog/2009/05/speed-size-and-dependability-of.html , при этом надо понимать, что именно измеряется.

Если считать, что "R=производительность_программы=K*производительность _программиста + N*производительность_языка", то это задаст круг радиуса R с началом грубо говоря в оси координат на похожих графиках.

Закон Мура автоматически улучшает N, а K сильно не изменяется.

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

>ну есть такое понятие как readability - как его формализовать?

условная плотность вероятности понимания очередным программистом написанного, при симуляции модели по методу Монте-Карло N случайно взятых программистов. Условия = те критерии качества, про которые вы тут распинаетесь.

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

>условная плотность вероятности понимания очередным программистом написанного, при симуляции модели по методу Монте-Карло N случайно взятых программистов. Условия = те критерии качества, про которые вы тут распинаетесь.

Это не есть формальным определением

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

>например: дублирование нарушает читабельность

оно не нарушает читабельность. Оно нарушает более общий принцип DRY, и вводит несколько точек изменений, антипаттерн в дизайн, которые придётся изменять согласованно, оттого что язык не умеет выведение типов.

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

ну да, просто изложил сам ход мыслей. Нечто вроде формулы Байеса для фильтрации спама, только тут у нас плотность вероятности функции "понимания фичи языка".

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

> оно не нарушает читабельность. Оно нарушает более общий принцип DRY, и вводит несколько точек изменений, антипаттерн в дизайн, которые придётся изменять согласованно, оттого что язык не умеет выведение типов.

DRY само собой, об этом даже речи не идет

но и читабельность тоже ухудшается, сравним 2 строчки (java)

VeryLongClassHierarhyRoot r = new VeryLongClassHierarhyClass(1);

VeryLongClassHierarhyClass r = new VeryLongClassHierarhyClass(1);

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

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

>метрики чего ты хочешь получить? метрики процесса разработки? метрики программ на языке, используемом в процессе разработки? метрики вспомогательных инструментов, написанных на языке, используемом в процессе разработки? метрики понимания программистами используемых процессов, инструментов, языков?

все сразу (и можно без хлеба) (С) винни-пух

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

метрику я понимаю не как экспериментальную методику, а как накоторое число, относительно которого мы сможем хотя бы рассуждать "как оно изменяется вот при таком локальном (или глобальном?) изменении языка программирования"

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

> ну да, просто изложил сам ход мыслей. Нечто вроде формулы Байеса для фильтрации спама, только тут у нас плотность вероятности функции "понимания фичи языка".

эксперименты возможно и нужны, но шибко трудозатратны

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

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

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

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

имхо отсюда некуда копать

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

вот это уже лучше. но не полностью.

1. понятные другими программистами = читабельность

2. поддерживаемые = дело наживное либо хорошие средства метапрограммирования, чтобы сеньор девелоперы могли поддерживать, не патча компилятор

3. зрелые = вредная фигня (т.к. нам надо поддерживать новые технологии, а не плестись в хвосте прогресса) либо опять хорошие средства метапрограммирования, чтобы сеньор девелоперы могли шейпить язык (запрещая опасное и добавляя полезное), не патча компилятор

4. с минимум ненужных рисков.

тут должны быть описания рисков

сразу приведу несколько:

4.1 сильное изменение требований и/или жестокий рефакторинг программы

цель: минимизировать текстуальные изменения языка

средство: так называемая "гибкость" языка

пример: исключения более гибкие, чем возврат Алг. Типа Данных Variant<UsualResult,CanNotDoBecase,ShitHappens>

4.2 изменения технологий, в т.ч. самого языки

4.х <заполнить>

> С точки зрения программиста прикладного, это удобный язык предметной области. "С батарейками", если угодно.

== поддерживаемый

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

отсюда можно копать, моя любимая тема -- абстракции :-)

> С точки зрения компьютера :)) -- это язык, достаточно эффективно ложащийся на аппаратные ресурсы.

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

на самом деле, конечно это тоже важно.

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

s/минимизировать текстуальные изменения языка/минимизировать текстуальные изменения исходного кода программы на этом языке/

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

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

>> 2. я не хотел бы погрязнуть в процессе. Мне интересен язык, дающий прикладные преимущества.

> вот для этого я и спрашиваю про критерии, важность отдельных фич!! Грубо говоря, что важнее, 6 или легкое-прозрачное-автогенерируемое 2?

Я, в отличие от ден73, не боюсь погрязнуть в процессе. Соответственно и амбиций у меня побольше.

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

> поинт в том, что язык шаблонов в С++ является примитивным ФП языком, на самом деле.

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

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

> тут можно привести OMeta и расширяемых грамматик как пример удачного использования: http://www.moserware.com/2008/04/towards-moores-law-software-part-3-of-3.html Это не просто DSL, это произвольно расширяемый синтаксис, с ОО наследованием, перекрытием таких DSL.

Jetbrains MPS затеяли то же, но у них вышел фейл в том смысле, что произвольная расширяемость только в рамках IDE, но *не* исходного текста.

Твою ссылку пробежал по диагонали -- так *ГДЕ* там парсер именно произвольно расширяемого синтаксиса??? всякие antlr не в счет

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

при симуляции модели по методу Монте-Карло N

вот есть статейка Джоэля про Evidence Based Scheduling http://www.joelonsoftware.com/items/2007/10/26.html — применение имитмоделирования по Монте-Карло для оценки вероятности успешного завершения проекта: контроля сроков, ресурсов, полноты фич (какие фичи надо выкинуть, чтобы вписаться в график).

Берём оценки исполнителей-программистов «сколько займёт реализация фичи». Делим план на факт, получаем «скорость исполнителя». Потом прогоняем на реальном проекте оценки времени, вычисляем возможные факт. времена (план/случайную «скорость» из выборки). Получаем имитмоделированием возможное время завершения проекта и % вероятности успешной реализации фич.

Можно немного придраться к модели: на мой взгляд, скорости-оценки не абсолютно равновероятные, скорее это условные вероятности из формулы вроде Байеса: вероятность точнее оценить трудоёмкость задачи больше, если до этого такие задачи уже решались. Скорее, это вопрос декомпозиции на подзадачи/исполнителей: зависимые/независимые, условно вероятные/равновероятные. Но предположим, что модель всё-таки достаточно точная.

Какое отношение это имеет к «критериям качества языка», метапрограммированию?

Пока что в модели Джоэля язык программирования мог быть любой. Но проведём эксперимент: пусть часть программистов-исполнителей делает проект на языке L, а другая часть берёт более богатый язык, «платформу Х». «Платформа Х» — это метаязык, метасистема — язык, описывающий сам себя, среда-система, написанная на себе самой. Если статистически можно доказать по результатам эксперимента, что система Х позволяет выдавать более точные оценки времени выполнения, видно, что применение такой платформы-метасистемы имеет смысл. Осталось только найти Х.

Поищем его конструктивно, индуктивно по такому же принципу. Система Х — метаязык сверхвысокого уровня, на уровне N которого описывается сам метаязык; уровень N описан с помощью более низкоуровнего языка уровня (N-1); ур. (N-1) описан с помощью уровня (N-2) и т.д. На уровне 1 сидит базовый Си, ассемблер, или байткод LLVM/.NET/Java.

Вопросы:

0. А есть ли смысл вообще в метаязыке Х по сравнению с каким-то одним обычным языком Х.

1. Какой именно метаязык лучше для уровня N?

2. Какие подуровни лучше для конкретного Х, как лучше провести декомпозицию.

3. ???? Как провести вычислительный эксперимент, пытаясь ответить на вопросы 0-1-2 статистически, эмпирически? Сколько и каких опытов надо провести, чтобы измерения 0-2 стали статистически значимыми? Что оценивает эксперимент -- умение наугад выбранных программистов решать задачу на конкретном языке, умение строить метасистему на конкретных базовых языках, конкретный компилятор или некие мифические «качества языка»? Допустим, мы можем доказать-найти корреляцию между сначала метасистемой Х и языкам L1,L2..Lk, затем между Lx и какими-то «качествами языка»-- или между «качествами» и удачно построенной метасистемой Х. Каковы границы применимости такой метасистемы на других проектах и задачах? Можно ли статистически/эвристически найти *самое* оптимальное, глобально, а не только локально решение или хотя бы определить направление его поиска?

4. PROFIT! Нашли волшебную платформу Х, языки, на которых её можно построить, «качества языка», используя которые можно всё это построить.

Ну то есть, предлагается провести эксперимент вроде shootout benchmark game по ссылке выше и кластеризировать/проанализировать результаты. И доказать эмпирически, статистически: «такой-то язык лучше в таких-то задачах благодаря такой-то семантике, таким-то базовым *качествам языка*»

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

ниасилил многабуков -- это не значит, что "читабельность хреновая". "ниасилил эпистолу ибо невнятное tl;dr" -- уже более разумная причина. Читабельность хреновая не потому что буков многа, а оттого, что буквы невнятные. Можно и внятно написать многабуков так, чтобы было не лень распарсить, ежели текст не уныл.

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

что показывает это число? Какой у него физический смысл?

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

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

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

>шибко трудозатратны

да ну. Берём какой-то маааленький проектик из 2-3 подзадач, просим оценить время на реализацию, вычисляем факт затраты на реализацию. Запускаем легион анонимусов ^W^W army of programmers чтобы порешали, и с 1000-ной попытки собираем более-менее убедительную репрезентативную выборку. Ищем корреляции. Профит! :)

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

> Система Х -- метаязык сверхвысокого уровня, на уровне N которого описывается сам метаязык; уровень N описан с помощью более низкоуровнего языка уровня (N-1); ур. (N-1) описан с помощью уровня (N-2) и т.д. На уровне 1 сидит базовый Си, ассемблер, или байткод LLVM/.NET/Java.

не понял... уровень 2 описан с помощью ассемблера или даже си?

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

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

> Запускаем легион анонимусов ^W^W army of programmers чтобы порешали, и с 1000-ной попытки собираем более-менее убедительную репрезентативную выборку. Ищем корреляции. Профит! :)

знаешь ли, не все имеют карманную армию в 3000 программистов

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

>1. понятные другими программистами = читабельность

>2. поддерживаемые = дело наживное либо хорошие средства метапрограммирования, чтобы сеньор девелоперы могли поддерживать, не патча компилятор


хорошо читаемый write only код на метабрейнфаке прокатит?

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

>3. зрелые = вредная фигня.. чтобы сеньор девелоперы могли шейпить язык (запрещая опасное и добавляя полезное), не патча компилятор


сидит молодой акын, играет Iron Maiden. Ищет. Сидит старый акын, адынпалкадваструна, дзынь раз в минуту. Нашёл.

а зачем им вообще что-то "шейпить", если средства зрелые? Если пубертатные, тогда ладно ещё.

вот сижу я сейчас под виндой, поставил mingw, llvm, собрал ldc, сижу tango патчу-собираю. Собранный под mingw-ом llvm D compiler упорно считает, что винда у меня posix. В SVN tango уже вроде пофиксили, так я старый стабильный релиз нашел. А Hans Boehm gc в libgc.a мингвом тоже с приключениями собирается -- или без нитей, или руками Makefile.direct править. А потом хочу ещё с исключениями потрахаться, SEH такой занятный под виндой.

Спрашивается, нафига бы мне чего-то там патчить, компилять, пробовать, если бы LDC официально держал "из коробки" позикс под виндовым gcc? Но получился жуткий зоопарк, на который надо пробовать, патчить, шейпить вот чего-то там.

>4. с минимум ненужных рисков.

>тут должны быть описания рисков


так это ж понятно. Write only код на брейнфаке -- это риск. Архитектурные астронавты -- тоже риск. Незрелые тулзы -- тоже риск. Решать не ту задачу -- огромный риск.

В модели Evidence Based Scheduling Джоэля риск -- это bad estimator, исполнитель, оценки которого с большой дисперсией, с большими разбросами.

>пример: исключения более гибкие, чем возврат Алг. Типа Данных


ну лисповые условия и рестарты тут рулят и педалят. Или смоллтоковый doesNotUnderstand.
Изменения требований вообще решаться по-другому должны -- надо долго думать и потом быстро грамотно задизайнить, а не заниматься monkey patching'ом используя "гибкость языка". Другое дело, если программа -- организация эксперимента или прототип того-ещё-не-знаю-чего. Тут гибкость важнее дизайна.

>4.2 изменения технологий, в т.ч. самого языки


это как? Мольеровский мещанин ВНЕЗАПНО обнаружил, что всю жизнь разговаривал прозой?

>== поддерживаемый


да, важно не "200 студентов написали много версий 0.01", а:
1. зрелый, поддерживаемый код
2. автоматизация везде, где возможно (FFI, генерация стабов и т.п.)

>отсюда можно копать, моя любимая тема -- абстракции :-)


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

Например, был тред про факториал на окамле, хаскелле, с++ и т.п. Так основной вывод с того треда: размещается объект в стеке, хипе или в пуле -- абстракция более важная, чем "написано на с++/яве/окамле".

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

>на самом деле, конечно это тоже важно.


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

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

да-да-да, а ещё есть Boost::Spirit на шаблонах, вот гадость-то...

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

>Твою ссылку пробежал по диагонали -- так *ГДЕ* там парсер именно произвольно расширяемого синтаксиса???

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

"Расширяемый синтаксис" -- это программа на языке OMeta, грамматики, правила синтаксикеские и семантические действия (на хост-языке).

Например, первая картинка: http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_fZlN-Jc9I/AAAAAAAAAak/_dJMMq3JO1E/s16... -- это программа на метаязыке.

Вторая картинка http://3.bp.blogspot.com/_Zfbv3mHcYrc/R_cAAN-Jc2I/AAAAAAAAAZs/eM3bX3tzrag/s16... -- это правила метаязыка, язык описания языка программы на первой картинке.

Видим: грамматические правила, после -> в скобках -- семантические действия на хост-языке. Это не местами смоллток, местами лисп, это COLA и COKE -- языки проекта FONC, с соотв. объектной моделью (COLA=Common Object-Lambda Architecture).

В общем, почитай блог с первой статьи http://www.moserware.com/2008/04/towards-moores-law-software-part-1-of-3.html про цели и задачи проекта STEPS -- Reinvention the computing. Более наукообразно и менее разлаписто это есть на http://www.vpri.org/html/writings.php в "Fundamental New Computer Technologies".

http://tinlizzie.org/ometa/ - сайт автора OMeta
http://www.piumarta.com/software/cola/ -- COLA http://lambda-the-ultimate.org/node/2483 ещё у автора есть PEG-парсер на Си http://piumarta.com/software/peg/

Диплом по PEG Брайана Форда http://pdos.csail.mit.edu/~baford/packrat/
интересен прежде всего критикой и реализацией. Критика направлена на
1. Packrat, который мемоайзит всё подряд -- достаточно только несколько токенов
2. PEG, как не самый быстрый по сравнению с LL(k) или LALR алгоритм; Кроме того, смысл PEG немного другой -- это описание именно алгоритма парсера, а не грамматики.
3. Реализацию. Тут постарался сам Форд -- сделал свой packrat парсер на Clean и Хаскелле, с монадами, с комбинаторами и просто с паттерн матчингом. В итоге можно эвристически считать, что накладные расходы на монады больше, чем на паттерн матчинг :))

Ещё можно посмотреть на bootstrapping Church/State языка или metapeg (ссылки были по треду выше, http://subvert-the-dominant-paradigm.net/blog/?p=37 )

Church/State примерно похож на COLA/COKE или Goo/C или L/C по целям -- два языка с общим ядром, один описан на другом.

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

ага. Например, берём COLA/COKE или Church/State. Функциональный язык описан с помощью императивного ядра. Императивное ядро -- базовые примитивы языка недолисп, который транслируется в Си, и в который транслируется "лисп".
Похожие идеи есть и в MBase, на лиспе ядро 1 уровня, 1 уровень компилируется в .NET VM (0 уровень, через рефлексию реализуется ядро языка), второй уровень компилируется в первый, третий во второй и т.п.
Или, язык HN с C++ в качестве HN0, язык вроде Хаскелля HN (на самом деле, комбинаторная логика).

То есть, вопрос про оптимальные языки можно ставить как
1. оптимальность метаязыка "сверхвысокого уровня"
2. оптимальность разбиения на подуровни, что лучше, 2 таких уровня или 3 таких.
3. оптимальность выбора языка для конкретного подуровня.

Например, возьмём Сhurch/State. То, что Church (функциональный) описан на State(императивном) -- обеспечивает интероперабельность функ/императивной части. То, что State транслируется и линкуется с Си, обеспечивает прозрачность интеграции с Си.

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

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

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

Например, возьмём С++. Константность, константные ссылки, транзитивность константности. Есть вероятность, что т.к. транзитивность константности не отслеживается, не обеспечивается, «реализация константности в С++ непонятна».

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

Почему не сделать методы по умолчанию виртуальными, а в особых случаях final sealed — невиртуальными? Почему _аннотация_ virtual, которую разумный компилятор с разумной системой типов должен сам вычислить и применить, чисто оптимизация для компилятора по-сути, у нас принимает такой важный *нечитаемый* смысл, что её везде надо писать руками, следить, не ошибиться бы? Вывод «виртуальные методы в С++ не понятны»

Почему в C/C++ нет средств отследить aliasing указателей автоматически? Требуется, в лучшем случае, расставлять компиляторно-зависимые костыли руками. Почему такие аннотации компилятор не может расставить сам. Вывод «семантика указателей в части aliasing problem в C/C++ непонятна».

Я не говорю, что фича непонятна абсолютно. Не, с некоторой вероятностью понимания этих костылей её можно считать условно-вероятностно понятной, по нечёткой логике. Но если фича не однозначно понятна со 100% вероятностью, это хорошо закопанные грабли.

Возьми, например, текст с терминами — он условно-понятен. Или на лунном с иероглифами — он сразу понятен, наглядно — если ты знаешь иероглиф или основные штрихи, идиомы.

Вот фантастически наглядно описана разница между императивным и функциональным стилем мышления — Хаскель это такой «ГЕПТАПОД А» http://dustyattic.ru/literature/ted_chan/story_of_your_life

Так что — ПОНИМАЙ http://dustyattic.ru/literature/ted_chan/grip

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

>случай, когда Money меняет синтаксис с 500$ на $500. Тогда Money надо исключить из функции parse_stream_that_start_on_digit (это мы очевидно сделаем), но запросто можем забыть исключить его из потомков LiteralThatStartsOnDigit, и компилятор об этом не напомнит -- у нас будет Money* parse_money(...) {...}.

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

>Ну, посмотрев с другой стороны, 500$ или $500 -- это деталь реализации, и она не должна влиять на иерархию классов

да, но при реализации на BNF или ANTLR или TLDP нам надо описать правила явно. Хорошо ещё, что пасер не LALR -- может ВНЕЗАПНО сломаться из-за нежданных shift-reduce конфликтов. Вывод: реализация абстракции "правило для $currency" не имеет отношения к наследованию, это более общая аггрегация.

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

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

а я ведь один раз четко сказал свое мнение, ладно еще раз:

использование в языке только зрелых средств considered harmful.

В качестве примера рассмотрим яву, в которой до 2005(!!!!) года не было дженериков, а использовалось зрелое выведение всего из Object-a (в том числе при создании коллекций, бу-га-га!)

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

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

> хорошо читаемый write only код на метабрейнфаке прокатит?

"читаемый write only"? это что такое?

> хорошо читаемый ... код на метабрейнфаке прокатит?

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

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

= понятность языка

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

> мне кажется, "читабельность" -- это подвид более общей фичи "понятность" языка.

я бы (вопреки одному своему посту в этом треде) почти до конца бы их разделил:

читабельность синтаксиса,

понятность семантики.

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

это значить подстраиваться под быдлокодеров? хотя не все так просто.

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

но должна быть возможность, дописав атрибут, сказать: "а вот здесь компилятор обязан развиртуализовать функцию", и если он это не может, должна быть ошибка компиляции.

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

> Какой физический смысл у невиртуального деструктора?

очевидный для знающего идеологию с++

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

> Почему не сделать методы по умолчанию виртуальными, а в особых случаях final sealed -- невиртуальными? Почему _аннотация_ virtual, которую разумный компилятор с разумной системой типов должен сам вычислить и применить, чисто оптимизация для компилятора по-сути, у нас принимает такой важный *нечитаемый* смысл, что её везде надо писать руками, следить, не ошибиться бы? Вывод "виртуальные методы в С++ не понятны"

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

и идеология и требует пересмотра, однако в ее рамках виртуальные методы в С++ понятны.

______________________________________

я потом видимо еще отвечу

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

>В качестве примера рассмотрим яву, в которой до 2005(!!!!) года не было дженериков,

Когда ява создавалась (конец 90-х) были очень сильные реакционные настроения против шаблонов С++ которые вызывали внезапные internal compiler error-ы без разъяснения контекста ошибки, просаживали время компиляции в несколько раз и вообще интродуцировали кучу внезапных граблей которые могли вылезти и на финальной стадии проекта. В первой ревизии С# шаблонов тоже не было. По результатам голосования на сайте Борланда генерики выпилили и из Дельфи.

>а использовалось зрелое выведение всего из Object-a (в том числе при создании коллекций, бу-га-га!)

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

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

> Когда ява создавалась (конец 90-х) были очень сильные реакционные настроения против шаблонов С++ которые вызывали внезапные internal compiler error-ы без разъяснения контекста ошибки, просаживали время компиляции в несколько раз и вообще интродуцировали кучу внезапных граблей которые могли вылезти и на финальной стадии проекта. В первой ревизии С# шаблонов тоже не было. По результатам голосования на сайте Борланда генерики выпилили и из Дельфи.

(побежал в википедию проверять насчет С# и Дельфи)

если так, то все это подтверждает тезис: в языке должны быть "незрелые" фичи, иначе лет через 5-10 мы будем ужасаться идиотизму его создателей

>> а использовалось зрелое выведение всего из Object-a (в том числе при создании коллекций, бу-га-га!)

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

не понял... ты защищаешь подход старой явы? ну так это

1. небезопасно -- то, что сейчас ловится статически, вызывало http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ArrayStoreException.html

2. тормозно -- нужны рантаймовые проверки

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

>не понял... ты защищаешь подход старой явы?

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

>небезопасно -- то, что сейчас ловится статически, вызывало

Это чисто теоретическая проблема т.к коллекции всегда private и поэтому то что в них кладется ограничено интерфейсом класса в котором они содержатся.

>тормозно -- нужны рантаймовые проверки

А их никак не избежать без того чтобы отказаться от того что код всех библиотек в момент работы над проектом полностью собран. В том же COM гоняли туда-сюда коллекции IUnknown-ов и делали им QueryInterface перед использованием.

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

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

бред

плюсы никогда не отличались стремлением решать теоретические проблемы (и потому не популярны в академической среде :-)

> Это чисто теоретическая проблема т.к коллекции всегда private и поэтому то что в них кладется ограничено интерфейсом класса в котором они содержатся.

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

> А их никак не избежать без того чтобы отказаться от того что код всех библиотек в момент работы над проектом полностью собран. В том же COM гоняли туда-сюда коллекции IUnknown-ов и делали им QueryInterface перед использованием.

СОМ головного мозга?

в современной яве избежали

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

>плюсы никогда не отличались стремлением решать теоретические проблемы (и потому не популярны в академической среде

Наверно я слишком громко назвал проблемы которые любит решать С++ "теоретическими". Это скорее FUD-проблемы.

>> Это чисто теоретическая проблема т.к коллекции всегда private и поэтому то что в них кладется ограничено интерфейсом класса в котором они содержатся.

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

Можно сделать аргументом массив и при получении конвертировать. А при отдаче вовне конвертировать обратно из коллекции в массив. Впрочем, в плюсах при получении аргумента вида const std::vector< std::tr1::shared_ptr<Widget> >& чтобы сохранить содержимое себе его тоже надо копировать, и тоже неявно копировать при отдаче коллекции вовне, полагаясь на оптимизацию возвращаемого значения.

>в современной яве избежали

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

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