Как стать автором
Обновить

Комментарии 148

Теперь понятно с кого «срисовали» гениального злодея создатели сериала «Шерлок».
Не похож же.

Магнуссен (Sherlock S03E03)
image
Может и не похож, но при виде фото, мозг начал сигнализировать, что где-то я его уже видел. Ближайшее воспоминание выдало Магнуссена.
Значит, в ваших Чертогах Разума банальный бардак.
Круто, у меня тоже есть Чертоги Разума!
У меня был такой же эффект. Только ближайшим оказался Adam Savage.
НЛО прилетело и опубликовало эту надпись здесь
И на Мориарти тем более не похож.
Я имел ввиду Магнуссена.
В 2005 году, он был проездом в Егорьевске, на полигон приезжал.
из серии ОБС:
он остановился в одном из кафе Егорьевска, к нему подошёл официант и взял автограф(в Егорьвске такие суровые официанты которые знают Н.Вирта в лицо). Скан автографа когда-то выкладывали на местном форме
вот кстати пруф
Спасибо за этот коммент. А то я боялся, что к этой статье будет только мой коммент не в тему.
Я бы сказал, это Вирт настолько суров, что его знают даже официанты в Егорьвске.
Да, спасибо за статью — я в ней почерпнул для себя очень важный тезис —
Присутствующие разделили сожаление по поводу распространения в качестве фактического стандарта крайне неудачного языка программирования «Си»

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

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

В последнее время все пытаются взять АРМ помощьней, нацепить на него какую то ось, и работать на высоком уровне попивая сок, совершенно не заботясь, а как это работает внутри и сколько ресурсов просто тратится впустую. А если это часть мозга чего то летающего, то будет очень неприятно если это летающее грохнутся на землю из за того что ось перегрузила ось второстепенными задачами и отвлекщись от главного — пилотирования.
Забавно, но мне С очень нравится, и побольше паскаля. Что действительно хорошо в паскале, так это возможность работы с делегатами «из коробки», когда как указатели на функцию в С довольно неуклюже выглядят. Паскаль лучше для обучения, но называть С неудачным — я бы, мягко говоря, не стал.
Паскаль очень замечателен, но к сожалению уже отжил своё=( Хотя этот коментарий я пишу, отровавшись от коддинга на паскале(на работе) (:
Я, конечно, зануда, но:

— Истинную величину И.С.Баха человечество оценило спустя несколько столетий после его смерти.
Я понимаю, что для красного словца, но это он загнул.

Даже просто посчитать — Бах умер в 1750 году, а несколько это как минимум два. Т.е. получается, что истинную величину(величие, наверное?) Баха человечество поняло после 1950-го года.

А Вирт да, я тоже с Паскаля начинал. Ну почти, на самом деле с Алгола и PL/1, но это было несерьезно.
А я только сейчас понял, что не понял смысл предложения. Сразу прочитал «величину И. С. Баха» примерно как «постоянную Планка». Задумался: и чему же равна эта величина Баха?!
Как-то в статье мало рассказано про его достижения. А между прочим, Никлаус Вирт:

1. Разработал и популяризовал идеи структурного программирования (вместе с Дейкстрой и Хоаром). Т.е. это его надо благодарить за то, что сейчас мы пишем подпрограммы, циклы и условные блоки, а не пытаемся разобраться с последовательностью goto в огромных цельных кусках кода. Сейчас такое положение дел кажется естественным, но в 70-х важность структурного подхода была далеко не так очевидна.
2. Разработал p-code («p» — от «portable») — промежуточное представление кода, переносимое между платформами (привет, Java!).
3. Впервые внедрил сборщик мусора в языке системного уровня (привет ещё раз!) — совместно с Юргом Гуткнехтом они разработали компилятор языка и операционную систему Oberon, в которых программист, оставаясь на низком системном уровне, защищён от ошибок при работе с указателями.
4. Популяризовал замечательный закон, объясняющий, почему ваша любимая среда разработки всё ещё тормозит даже на процессоре последнего поколения :)
5. Написал один из классических учебников по алгоритмам и структурам данных.

Язык программирования Oberon стоит выделить отдельно, поскольку он является прекрасной демонстрацией того, как очень сложные и мощные вещи можно выразить минимальным количеством средств. То же самое можно сказать и про одноимённую операционную систему: создать полнофункциональную ОС со всеми наиболее важными функциями за то время и теми средствами, которые это сделали Вирт и Гуткнехт — это надо ещё постараться.

С днём рождения, Никлаус! Долгих лет жизни!
Вирту долгих лет жизни и здоровья!

Романтик и популяризатор во многом далекий от реального программирования.
1. Я все время пользюсь логикой Хоара, как только стал писать программы. Вот его статья sunnyday.mit.edu/16.355/Hoare-CACM-69.pdf, но тут как-то Вирта нет.
Вклад Дейстры есть
Дейкстра Э. Дисциплина программирования = A discipline of programming. — 1-е изд. — М.: Мир, 1978. — 275 с.
Дал У., Дейкстра Э., Хоор К. Структурное программирование = Structured Programming. — 1-е изд. — М.: Мир, 1975. — 247 с.
3. Низкий уровень, сборка мусора и защита от ошибок при работе с указателями. Можно еще немного посолить. Пользуйтесь логикой Хоара из 1 пункта и у вас не будут проблем с указателями. Не забывайте про страничную организацию памяти и защищенный режим. Сборка мусора имеет тенденцию в некоторые моменты улетать по времени, что для операционной системы особенно реального времени не допустимо.
5. Тот классический учебник я лично пытался прочитать несколько раз, не осилил. Очень подробно и нудно в западном стиле много воды.

Язык программирования Oberon стоит выделить отдельно. Например такая «простая» вещь
MODULE Имя;
IMPORT СписокИмпорта;
Определения;
BEGIN
Операторы
END Имя.

Точка в конце это очень круто. Я тут много мог проехаться по синтаксису, но кому что нравится. Вообще, приближать человеческий язык (в данном случае английский) к формальному языку программирования глупо, но заставляет некоторых людей думать, что они что-то понимают в программировании. Я встречал людей, которые после изучения Паскаля, пытались использовать его конструкции в window-ых bat файлах.
1. Я не совсем понял, причём работы Хоара к Вирту? То, что Хоар не издавал совместных книг с Виртом ещё не значит, что Вирт не занимался структурным программированием :) Почитайте работы самого Никлауса. Он часто пишет о том, что поток контроля программы должен быть простым и понятным. В одной из последних ревизий Оберона он даже запретил писать RETURN где-либо кроме последней строчки процедуры, тем самым привязав конец выполнения подпрограммы к её синтаксическому концу и убрав «неявный goto». И это только один из многих примеров.

3. Опять же, причём тут логика Хоара? Хоар предложил теоретический свод правил (если я правильно понял его посыл) для более защищённого программирования, Вирт создал практический язык с той же целью. Оба молодцы.
Насчёт сборки мусора на системной уровне ничего не скажу — это очень долгая и не самая важная здесь тема. Напомню только, что даже на Java писали ОС, и совсем не в качестве теоретического эксперимента.

5. Это вы ещё Кнута не читали ;)

А вот про синтаксис я бы послушал. После знакомства с синтаксисом таких языков как Ruby, Python, Lisp, OCaml, Erlang, Prolog и С++ мне интересно, что же вас так смутило в синтаксисе Оберона.
1. Разработал Хоар. А Вирт был популяризатор. Так по Вашему все люди, кто популярно писал о специальной теории относительности имеют к ней отношение. К ней имеют отношения только два человека величайший математик, механик, физик Пуанкаре и Альберт Эйнштейн.

3. Все эти правила не стоит травильного макроса assert, который был уже на Паскале под ЕС ЭВМ.
Я начинал писать программы на Lisp, которые считали в свое время достаточно большие задачи. Так вот на сборку мусора уходило в некоторых случаях до 20%. И это на Lisp-е которые специально со своими lisp-ячейками под это приспособлен и с Java лучше не сравнивать. Замечу раньше уровень программирования был значительно выше и сомневаться в качестве реализации не вижу смысла. «На Java писали ОС» — объектно-ориентированно можно писать и на Фортране-77.

5. В настоящие время занимаюсь реализацией ZDD диаграмм из 4 тома Кнута. Второй знаю почти наизусть. А так все читал и не раз. Единственный недостаток это его аля-ассемблер. Но туда можно не смотреть. Воды и популяризаторства как у Вирта нет. Самая лучшая книга по алгоритмам. НАСТОЯЩАЯ.

Prolog и Lisp очень просто. Проще не бывает. Python абсолютно лучший язык и для обучения и для профессионального программирования. Я часто либо делаю макет на Python, либо делаю привязку из C++ к Python-y. Хороший язык для обучения и для некоторого класса задач Haskell. Все что параллелится то все сложно. С++11 очень не плох сейчас начал писать на нем.

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

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

1. Это очень субъективно. Лично на меня практические исследования Вирта повлияли гораздо больше, чем теоретическое описание Хоара.
5. Опять же, в плане «воды» Вирт мне понравился гораздо больше. Кнут энциклопедист, который описывает всё от древних времён до последних тенденций. Это неплохо, но такой стиль довольно специфичен. Вирт же больше сосредотачивается на основных понятиях, описывая их «здесь и сейчас». В общем, дел вкуса.
Я математик (точнее механик, специализация околозвуковые течения газа), поэтом люблю формальное строгое изложение+мне всегда интересен сам процесс прихода к этим результатам в историческом контексте. Остальное я сам додумаю.

Прогресс есть именно в технической области. Какие за последние 25 лет есть сверхдостижения? Алгоритмы? Парадигмы программирования? Все старое. Единственно, из-за перегрева отрасли, полно в программировании людей, которым я бы и лопату бы не доверил.

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

Про Вирта я просто скромно помолчу. Хотя он бородат и это (косвенно, точнее эмпирически) говорит, что он должен создавать хорошие языки программирования.
Отбросим споры о величине учёных, дабы не разводить холивары. А вот что касается прогресса, то посмотрите на ту же самую сборку мусора. Одно разделение памяти на поколения чего стоит! А если брать последние сборщики мусора в Java (G1), то они вообще работают с минимальными остановками основных тредов. Ну или transient структуры данных в Clojure, которые позволяют избежать ненужного порождения объектов в циклах (хвостовой рекурсии). Это, конечно, не такие достижения, как изобретения транзистора, но на производительность систем они таки влияют. А 20% времени на сборку мусора/выделение памяти — это в современных рантаймах надо ещё постараться сделать.

Ну или если хотите околоматематические дисциплины, посмотрите на метод опорных векторов Вапника (1995), который сейчас считается одним из мощнейших классификаторов. Ну или алгоритм быстрого обучения глубоких сетей Хинтона (2006), который дал толчок для появления целого большого направления в машинном обучении. Вы можете справедливо заметить, что достижения становятся более локальными и меньше влияют на всю область. Но так было всегда. Если бы вы сказали про крутость TeX-а учёному 18 века, то он рассмеялся бы вам в лицо и сказал «Это же мелочь! Вот система координат Декарта....». И он был бы прав, между прочим.
Я решаю задачи в области символьных вычислений и не только. В символьных идет постоянное выделение и возврат объектов в кучу. Поэтому я уверен, что последние сборщики мусора в Java (G1) будут отстоем, по времени конечно. Для меня это пройденный этап моей жизни примерно 20 лет назад. Разделение памяти идеи еще когда я был в детском садике.

Моя реализация дает менне 1%, ускоряет примерно на 40% выполнение за счет страничной организации памяти и кэша процессора, но это не сборка мусора, а принципиально другой подход (ООП, а его Вы вроде не любите по публикациям, а я очень люблю этот подход, но книжки Грейди Буча ненавижу, вода, кругом вода), который дополнительно контролирует память и даже ее экономитЪ
freehabr.ru/blog/cpp/1757.html

Про хвостовую рекурсию меня не смешите, это доисторические компиляторы в Lisp-е сразу в цикл переводили. А как более сложные виды рекурсии. Теорема то есть о переводе, а где алгоритм. Стек не предлагать. Про машинное обучение… выразился по русски, но затем удалил.

Единственное достижение квантовые компьютеры. Но очень сильное. Во всех смыслах. Но это физики.
Многие компиляторы Common Lisp плохо справляются с хвостовой рекурсией. Это Schema по стандарту требует TCO.
В плане управления памятью появились регионы (вообще-то появились они в Cyclone, но сейчас они приблизились к массовому программированию).
Классы типов во многом удобнее ООП. К тому же не требуют иметь ссылку на VTBL — тоже экономия памяти.
Standart Lisp отлично. А Common Lisp очень спорен. У Lisp-а очень красивая идеология, но ООП в нем искусственно, поэтому на языке для которого должны быть отличные оптимизирующие компиляторы получается дрянь.
en.wikipedia.org/wiki/Portable_Standard_Lisp
Ну вот видите, даже ваши собственные скилы эволюционировали, а вы говорите, что за последние 25 лет нет никаких достижений ;) Т.е. для своей задачи вы прошли тот же путь, что и дизайнеры сборщиков мусора: попробовали, посмотрели результаты, повторили три раза, подобрали другой подход, повторили… и в итоге нашли то, что даёт удовлетворительный результат. Это прогресс, так или иначе, и никогда не знаешь, какая область вдруг выстрелит и поменяет индустрию: может быть это будут не квантовые компьютеры, а как раз машинное обучение, которое вам не нравится (кстати, почему?).

ООП я не нелюблю, я его не понимаю. Слишком уж размытое понятие, и слишком уж кривые классические реализации (Java, С#).

Хвостовую рекусию я упомянул в контексте транзиентных типов данных, т.е. временных мутабельных структур, которые позволяют значительно сэкономить память при больших циклах. А так да, естественно, TCO — не новость :)
«кривые классические реализации (Java, С#). „

Это не то слово. Кривые, а классикой язык для кофеварок (в прямом смысле этого слова) с кучей областей видимости, без goto, но с break и continue с метками, без множественного наследования, с красивой парадигмой о переносимости, которую все подряд нарушают, я назвать не могу. Про C#, Delphi и Paskal (не от Вирта) от Хейлсберга вообще полный бред, нарушение строгой типизации в Paskal, ООП в Delphi это курам на смех и продолжение этого уродства в C#.
слишком уж кривые классические реализации (Java, С#)

Это не классические, а мэйнстримовые. Классический — Смолтолк.
но это не сборка мусора, а принципиально другой подход (ООП

Сборка мусора и ООП вещи ортогональные друг другу. Можно использовать перове без второго, можно второе без первого, а можно и то, и другое.
«Сборка мусора и ООП вещи ортогональные друг другу»

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

Тогда лучше так. «Сборка мусора и ООП вещи ортонормированные К друг другу».
И подпись. Гипотенуза.
Скалярное произведение векторов сборки мусора и ООП равно нулю :)

Сборка мусора не является обязательным элементом ООП-языков (например C++), а ООП не является обязательным элементом языков со сборкой мусора (например PHP 3).
«Скалярное произведение векторов сборки мусора и ООП равно нулю :)»

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

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

Я сейчас выпил собственного напитка и согласен признаться в собственной тупости. Пути Господни неисповедимы!
В одной из последних ревизий Оберона он даже запретил писать RETURN где-либо кроме последней строчки процедуры, тем самым привязав конец выполнения подпрограммы к её синтаксическому концу и убрав «неявный goto».

Осталось сделать еще шаг и выкинуть слово RETURN, сказав что значением функции является значение ее последнего выражения. Благо так сделано во многих языках — Ruby, Perl, Rust,R, Julia, все функциональные.
А вот это уже нет. Т.е., лично мне такой подход тоже нравится, но он делает синтаксис менее очевидным, а вся история Oberon-а идёт в обратную сторону.
, сказав что значением функции является значение ее последнего выражения.

Не очевидно, что именно такой шаг. Как вариант функция может возвращать значение, присвоенное переменной с именем, совпадающим с именем функции.
В Паскале было — понятности это не прибавляло. Правильно Вирт от этого отказался.
Последнее выражение тоже понятности не прибавляет.
Лишние слова мешают восприятию. А если RETURN допустим только в конце, то он даже не несет ни какой подсказки при просмотре программы.
Мешают восприятию они только если избыточны, если же устраняют неоднозначность, то улучшают восприятие.
Последний RETURN как раз избыточен.
Если без операнда, то да.
Сборка мусора все-таки появиласть в Lisp, при этом полноценная, а не с подсчетом ссылок.
Но Lisp — это не совсем язык системного уровня. Т.е. попытки, конечно, были, но больше теоретические и эзотерические (Lisp-машины, стековые архитектуры… эх, романтика).
Lisp-машины были вполне успешными коммерческими разработками. Сейчас наиболее продвинутые Lisp-компиляторы по производительности могут поспорить с C.
Так вот именно, что запускались Lisp-программы на отдельных специальных машинах, а не на более распространённых стековых архитектурах.

Если вы про SBCL, то да, скорость у него что надо. Но вопрос то был в том, насколько Lisp подходит для системного программирования. Я слышал про людей, которые программировали на Лиспе микроконтроллеры, но это всё-таки больше исключение, чем правило.
>И в программировании классика тоже уступает арену коммерчески изуродованной индустриальной «попсе».

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

Не стоит торопить события. Не всё сразу. ;) При желании про его достижения можно узнать по ссылкам на рекомендуемые материалы.

Эта краткая заметка — повод вспомнить про Никлауса Вирта в его юбилей и высказать ему слова благодарности. Судя по комментариям наш народ весьма скуп на добрые слова.
Ну потому что статья пафосная, но во многом не по делу. Как будто бы имеет значение, кто ещё кончал его вуз в разные годы, или кого-то трогают тенденциозно-бредовые соображения автора про «диктатуру воинствующих дилетантов».

А если по делу — я глубоко уважаю профессора Вирта, учился в том числе и по его книжкам, и ценю его достижения.
Но он, на мой предвзятый взгляд, относится к тем «кирпичам» здания компьютерной науки, которые не окажутся на фасаде. Он многое сделал для развития идей, практики и содержания программирования.

Однако его основное детище — это попытка создать минимальный простой язык. Модула проще Паскаля, а Оберон проще Модулы. Однако жизнь показала, что идея эта нежизнеспособна, потому что сложные понятия требуют сложного языка. И даже те языки, которые начинались как «простые» (вроде тех же C# и Java), сейчас по сложности стремительно догоняют C++.

А ниша Паскаля стремительно уходит к языкам вроде Python или Ruby. Так что пройдёт ещё немного времени, и существенный вклад Вирта, к сожалению, окажется скрытым под новыми культурными слоями. Даже я, начинавший программирование с Бейсика, как-то мало соприкасался с его наследием.
Сия точка зрения безусловно имеет право на жизнь. Хотя весьма предвзята и обусловлена (очевидно) недостаточным опытом работы с наследием Вирта. ;)
Вынужден заметить, что предлагаемая статья никак не способствует познанию этого наследия. Вот и рассказали бы подробнее, а просто высказать мнение каждый умеет.
Я за продуктивный диалог. А не за фехтование на уровне эмоций и мнений. Есть желание узнать и разобраться — это одно. Если всё априори ясно и надо лишь высказать своё «фе» — нечто иное.

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

Можно, конечно, начать переписку в комментариях, но это в принципе неправильно.
Если интересует моя «аксиома», то это, конечно, не аксиома, а теорема. Чтобы её доказать, мне надо написать целую простыню текста.

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

Например, если я математик, то у меня должна быть возможность написать выражение «A*c», где A — квадратная матрица, а c — вектор-столбец, потому что к этому подвигают гигантские объёмы существующей математической литературы и поколения математиков, работавших над формализмом.

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

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

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

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

1. Абстрагирование — игнорирование «незначащих» деталей. Абстракция может помогать, а может и мешать в борьбе со сложностью в программировании. Нужны «правильные» абстракции. А вот степень правильности, адекватности применительно к конкретным задачам и инструментам определить непросто.

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

3. Сложные системы можно и нужно создавать простыми инструментами. Но степень простоты (минимизация избыточных средств) должна быть адекватной.
В том и дело, что (повторю свой тезис) автор языка не может знать заранее, что конкретно мне нужно. Так что с тезисом (2) я в корне не согласен: язык должен удовлетворять мои объективные потребности. А если не удовлетворяет, то для меня он не годится.

Тут, конечно, надо пройти по тонкому льду между «естественными / правильными» абстракциями и «вредными костылями». Скажем, Чак Мур вообще всё на свете объявляет вредными костылями.

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

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

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

2. Ментальный водораздел проходит по следующей границе: (1) «только самое необходимое» (языки-чемоданчики) и (2) «удовлетворение растущих потребностей» (языки-сундуки).
Дело не в моём вкусе, а в моей предметной области. Она не имеет никакого отношения ко вкусу.

Вот ориентация на определённый класс задач — это совсем другое дело. Поэтому у нас есть SQL, например. Или Perl. Но в контексте данной статьи, я думаю, речь в большей степени идёт о Паскале и Обероне, которые позиционируются как языки общего назначения.

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

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

3. Надо понимать границы применимости того или иного языка, его достоинства и недостатки в контексте задачи/архитектуры/опыта программиста. Зачем забивать гвозди микроскопом или орудовать топором при операциях на сердце?
Надо понимать границы применимости того или иного языка

Почему бы авторам их не давать самим, раз они лучше всего знают свои детища?
В отношении опыта и предпочтений. Насколько понимаю, вы поклонник Python. Тогда наверняка в курсе привязанностей Гвидо ван Россума.

Американский язык Modula-3, из которого во многом растут ноги Python, создавался в DEC Systems Research Center и принципиально отличается от европейской Modula-2. Язык-сундук против языка-чемоданчика. При этом синтаксическая основа, да и фундамент у них общий.
Нет, я поклонник C++.
По предыдущим замечаниям — понятно, но это всё довольно очевидные соображения, которые в наши дни всё сильнее размываются реальностью. А реальность такова, что предметных областей становится всё больше, а возможности человеческие ограничены. Всё равно очень хорошо выучить можно пять-семь языков и обходиться ими в любой задаче.

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

Творческие находки Бьёрна Страуструпа, вся эволюция C++ и весь процесс стандартизации языка как языка ПРОМЫШЛЕННОГО программирования очень показательны. Вирт и Страуструп — во многом антиподы.

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

Вы снова и снова уходите от темы.
Это всё общие слова про разность школ и прочие высокие философии. Не причисляю себя ни к какой «школе».

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

Кстати, довольно странно записывать Страуструпа и авторов Simula 67 в американцы.
Я свои тезисы сформулировал вполне конкретно. Если в них что-то непонятно, уточните.

Контекст и мотивация. К какой бы школе себя не причисляли, но вы (да и любой иной программист) смотрите на мир сквозь вполне определённую призму. И если эта призма определяется преференциями к C++, лично мне многое становится понятно.

Для меня языки-ядра (С, Modula-2, Oberon, Lisp, Prolog, Smalltalk, Forth и др.) по мировоззрению ближе, нежели языки-сундуки (C++, Ada, Modula-3, Java, C#, Python и др.).
Не стоит путать национальность автора (авторов) и приверженность его и его языка конкретной школе. Симула-67 отношу к европейской школе (белой и пушистой).
Simula 67 — прямой предок C++
Simula 67 — прямой предок C++.

И что из этого следует? Прямым предком С++ является и C. Кстати, не самый плохой представитель американской школы.
Давайте я для простоты картины сведу мысль к двум тезисам:

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

Я считаю, что минимализм и широкая сфера несовместимы, вот и всё.
Соответственно, можно опровергать (1), (2) или мой вывод. А разговоры о «школах» и т.п. нерелевантны.
> Я считаю, что минимализм и широкая сфера несовместимы,

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

Ну так укажите язык ОБЩЕГО назначения, который Вам нравится, а я попробую его раскритиковать. Это будет конструктивно.

Мне тоже нравятся языки из Вашего списка. Но только для написания каких-то мелких кусков или для самостоятельных упражнений. А вот в качестве инструмента для широкого класса задач у меня с ними плохо срастается.
Классический Oberon.
Ну, я, конечно, в этом языке малокомпетентен, так что могу сильно промазать.

Но вот взять хотя бы простую задачу: «разработать алгоритм сортировки произвольной линейной структуры данных, в которой хранятся объекты пользовательского типа, для которой определены операции доступа по индексу, а объекты сравнимы операцией „меньше“».

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

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

Думаю, вам стоит просто почитать описание языка Oberon. Там 16 страниц.
oberon2005.oberoncore.ru/paper/oberon.pdf
Я это читал, но согласитесь, между чтением мануала и умением писать хороший код на данном языке лежит пропасть. Поэтому я и прошу вас привести тот кусок, который был бы образцом «оберонного» стиля решения данной задачи. Подставляться я не боюсь, подумаешь, тоже мне проблема.

Если просто кидаться текстами, я не «пойму, что есть другие взгляды». Давайте конкретнее.

Согласитесь, моя задача не относится ни к какой узкой области. Речь идёт о банальной сортировке. Если один член команды разрабатывает алгоритм сортировки, а другой работает над структурами данных, то разделение труда таким образом выглядит очевидным. Кроме того, хороший алгоритм сортировки можно применить и в следующем проекте (короче говоря, это библиотечный код).
А что конкретно вы от меня ждёте? Написания текста этой задачи на Обероне?
Конечно. Это же код на десять строк от силы (пусть будет самый банальный mergesort).
Ok. Предположим, я его представляю. Что дальше? О каких критериях идёт речь?
Вы говорите, что «в мире есть иные взгляды на программирование». Вот я и хочу посмотреть, как такая задача решается на Обероне.

А критерии очень простые, многократно описаны в работах классиков и годятся для любого языка:
— По возможности сжатость (иначе можно писать на ассемблере).
— По возможности понятность.
— Возможность разделить работу между исполнителями.
— Возможность применить написанное в новых проектах.

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


Критерии большей частью субъективные. Понятность зависит от многих факторов, среди которых синтаксические одежды (культура, симпатии и антипатии) играют чуть ли не решающую роль. Например, Java или C# в одеждах синтаксиса Паскаля будет восприниматься иначе, нежели в одеждах синтаксиса Си.

Сжатость — опять-таки спорный вопрос. Примерно такой же, как ментальная разница между code и sources. Код и исходный текст. Язык программирования высокого уровня (а речь о них) в большей степени должен ориентироваться на программиста (не кодера!), нежели на транслятор. На легкость отчуждения своего творения (однозначного восприятия другими).

Код — это текст с креном восприятия именно компьютером.
Исходный текст — восприятие в первую очередь человеком.

Разделение работы между исполнителями — объективный критерий. Ему безусловно удовлетворяет виртовское понятие модуля — module (Модула-2 и Оберон).

Применение в новых проектах — очень размытый критерий.

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

Чтобы всё-таки от обсуждения была какая-то польза, имеет смысл немного погрузиться в контекст. Первым делом стоит (хотя бы по диагонали) посмотреть книгу Никлауса Вирта «Algorithms and Data Structures — Oberon Version. 2004». Там весьма подробно на конкретных примерах разобраны подобные вопросы.
www.ethoberon.ethz.ch/WirthPubl/AD.pdf
Вот смотрите, я просил десять строк кода, а в результате снова получаю несколько абзацев текста. Давайте код. Я не собираюсь свои критерии трактовать с религиозным рвением. Под сжатостью я понимаю, например, то, что сортировка пузырьком не будет занимать 200 строк. А 10 строк или 20 — не так принципиально. Но если 200 — увольте, у меня нет времени столько печатать сортировку.

Разделение работы меня интересует в контексте «одни пишут алгоритмы, а другие структуры». Вот как это реализуется (поэтому и просил обобщённую сортировку)? Применение в новых проектах — это идеально формализуемый критерий, которому удовлетворяет любая библиотека, такая как стандартные классы .NET или библиотека C++ STL.

Книга Вирта меня в данном случае не устраивает (я её читал), потому что там рассматриваются алгоритмы на примерах базовых типов данных. Например, если вы пойдёте в главу 2.2, то увидите, что сортировка описывается на примере сортировки целых чисел.

Как раз пример книги AD — это, в общем-то фейл уважаемого мэтра доказать свою теорию. Потому что со времён первого издания (1985) в ней по факту очень мало изменились листинги. Как-то вот на месте топчемся. Те же примеры практически в тех же декорациях.
Давайте без давайте. Чем больше будете давить на слабо, тем меньше шансов прийти к конструктиву.
Я не давлю на слабо, я всего лишь хочу конструктива, выраженного в коде. Что может быть конструктивнее?
Я ведь от вас хочу совсем немного — изучить хотя бы предмет критики. На уровне чтения пункта 6.3 16-страничного описания языка.
Но вот взять хотя бы простую задачу: «разработать алгоритм сортировки произвольной линейной структуры данных, в которой хранятся объекты пользовательского типа, для которой определены операции доступа по индексу, а объекты сравнимы операцией „меньше“».

Вот здесь вы немного хитрите (хотя наверное и не специально). Данная формулировка явно намекает на решение через обобщённое программирование на C++. Если бы мы с вами действительно сейчас писали программу на Обероне, то первый вопрос, который бы я задал был бы «а зачем это это надо?». Как я описал где-то ниже в комментариях, Оберон тяготеет к полному контролю над выполнением, поэтому совсем обобщённые подпрограммы (например, написанные на темплейтах) не приветствуются. Вероятнее всего, если бы мы столкнулись с такой задачей в реальности, то у нас был бы какой-то базовых класс, для которого и определена операция «меньше» (я не очень помню классический Оберон, поэтому, если вы позволите, я буду отписывать с точки зрения Оберона-2; тем не менее, в первой версии всё то же самое скорее всего также можно было бы сделать, но чуть более хитро). Структура данных, для которой определена операция доступа по индексу, это почти наверняка массив — в противном случае опять же нарушается философия Оберона, ибо связанные списки, графы, хеши и все, для кого можно каким-то образом определить операцию доступа по индексу, каждый будут требовать своего эффективного алгоритма. В итоге мы получаем запрос на алгоритм сортировки для массива записей, унаследованных от некоторой базовой, которая поддерживает операцию сравнения. Реализация, как вы понимаете, будет не сильно отличаться от реализации на, скажем, Java (без дженериков).

Философия Оберона очень сильно отличается от философии C++, не только на уровне решений, но и на уровне постановки задач. Если хотите, можем сравнить подходы на примере какой-нибудь вымышленной подсистемы. Не обещаю, что в подробностях расскажу про то, как это нужно реализовывать на Обероне (всё-таки последний раз я в нём практиковался лет 5 назад), но общее направление мысли, думаю, дать смогу.
Шаблоны — не единственный способ создания полиморфных функций. Классический способ — экспортировать тип и операцию сравнения из модуля и работать с ними. Не знаю, реализуемо ли это на Oberon, очень давно на него смотрел.
А определять бинарные операции через наследование — не самый удачный способ. В Java его сделали не от хорошей жизни.
Классический способ — экспортировать тип и операцию сравнения из модуля и работать с ними. Не знаю, реализуемо ли это на Oberon, очень давно на него смотрел.

Вот честно не могу точно ответить на этот вопрос, средства Оберона для таких нестандартных для него задач помню весьма слабо. Могу только сказать, что многие задачи действительно решаются через функции высшего порядка. Плюс, в Component Pascal (наследник Оберона-2) появился общий тип ANYREC и указатель на него — ANYPTR. Насколько я помню, когда я писал на CP, то обобощённые задачи решал именно через них.
Ну почему же, это решение необязательно намекает на C++. Это можно совершенно без напряжений сделать на Python и на массе других языков. По поводу «зачем это надо» я отвечу очень просто: старая идея «повторного использования кода» никем не отменена.

Вот смотрите. Есть огромное количество классических алгоритмов, описанных у Кормена или у Кнута. Это ведь полезные алгоритмы, так? Иначе они бы не вошли в учебники.

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

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

Даже если вы предложите алгоритм только для массива (ОК), всё равно остаются сложности со сравнением и копированием элементов неизвестной природы. А заставлять пользователя наследоваться от вашего базового класса — это уже перебор (ну, если там нет множественного наследования, конечно).
Ну почему же, это решение необязательно намекает на C++. Это можно совершенно без напряжений сделать на Python и на массе других языков

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

Насчёт общих алгоритмов. Ну смотрите, возьмём для примера Component Pascal. Не потому что он круче своих предшественников (хотя фич у него несколько больше), а потому что его я помню лучше всего :) Есть там такой тип — ANYREC, от которого наследуются все записи. И есть функции высшего порядка. Этого вполне достаточно для того, чтобы написать функцию сортировки, которая будет принимать массив ANYREC-ов и процедуру-компоратор, а выдавать отсортированный массив. Алгоритм Дейкстры реализуется аналогичным образом и сохраняется в модуле. Но даже если бы не было ANYREC, то вместо записи можно было бы использовать некий ID, а сами записи хранить в массиве нужного типа. Ну или ещё как-нибудь.

Как это делается на классическом Обероне, честно не помню. То ли там есть обобщённые указатели (вроде void* в Си), то ли через процедуры высшго порядка, то ли ещё как-то. При необходимости такие библиотеки также создаются. Но, по своему опыту программирования на этом прекрасном языке, в разы чаще приходится писать именно модули, которые решают какие-то конкреные задачи: пишут лог, читают пакеты из сети, решают линейные уравнения и т.д.
Минимализм и широкая сфера совместимы. Пример — язык С.
Да чего уж там, давайте сразу назовём ассемблер.
Понятно, что любой язык программирования полон по Тьюрингу, но наши представления о прекрасном всё-таки прошли некоторую эволюцию с 1973 года.
Во-первых, по моему скромному мнению, ассемблер не имеет широкой сферы применение в обычном смысле. Во-вторых, приведите, пожалуйста, примеры с точки зрения программирования — что такое минимализм и широкая сфера применения. То есть, какие языки Вы считаете широко применимыми, а какие минималистичными? Что получается, только брейнфак можно назвать минималистичным? =)
p.s.: Мои представления о прекрасном — это минималистичный С, и с 1973 ему так и не нашли замену во многих областях, хотя да — в прикладном программировании его сильно потеснили.
Ну давайте согласимся, что играть в слова незачем: любой полный по Тьюрингу язык годится для чего угодно. Так что и C может «широко применяться», естественно.

А значит, разница состоит исключительно в «удобстве» (в любом понимании этого термина) для программиста. Соответственно, вам кажется, что инструменты, разработанные за последние 40 лет, не особенно ценны. Ну что я могу на это сказать?.. Видимо, в вашей сфере деятельности действительно это не нужно.

Я исхожу из того, что любой инструмент, придуманный за последние 40 лет, призван решать какую-то задачу. А чем больше задач может решать язык, тем шире он применим в реальной жизни, вот и всё.
«Только самое необходимое» без возможности расширяять язык своими абстракциями — не самое удачное решение. Язык получается простой и Тьюринг-полный, но не упрощает программирование больших сложных систем.
Одно другого не исключает. В частности, классический Oberon — модульный расширяемый язык. Стройте свои абстракции (если язык подходит для вашего класса задач), но в рамках данного «законодательства».

Есть устойчивый стереотип: сложные задачи можно решать только сложными инструментами. Наверное, всё же корректнее говорить — адекватными, подходящими, а не сложными. Что есть простота и сложность применительно к инструменту? Скальпель — сложный инструмент? По своей сути, по своей структуре — нет. Но при его использовании включаются в действие сопутствующие знания и навыки того, кто им оперирует. Нужна высокая квалификация. Есть простота структуры, есть простота комбинирования структур (установления связей этой структуры с другими), есть простота применения инструмента (адекватного владения им для данного класса задач). Чем проще инструмент, тем при росте сложности решаемых задач более высокие требования он предъявляет к квалификации того, кто с ним работает.
Наиболее мощные средства построения абстракций — макросы, функции высшего порядка, параметрический полиморфизм — в Oberon «вне закона». Даже ООП ограничено и модули не параметризуемы.
«Законным» остается только создание классических процедурных библиотек.

Oberon, как скальпель, сам по себе прост и на базовом уровне прост в использовании. Но написать на нем ОС могут только программисты класса Вирта.
В контексте достижений Вирта Вы затронули весьма интересную тему. Oberon System. Стоит обязательно познакомиться с этим неординарным проектом.
www.ozon.ru/context/detail/id/8218517/
Наиболее мощные средства построения абстракций — макросы, функции высшего порядка, параметрический полиморфизм — в Oberon «вне закона». Даже ООП ограничено и модули не параметризуемы.

Мне кажется, вы ориентируетесь в своих рассуждениях на немного другие задачи, нежели те, для которых создавался Oberon. Вирт всегда работал на низком уровне, поэтому, как ни смешно, самый близкий к Оберону по целям язык из ныне популярных — Си. Но в отличие от Томпсона и Ритчи, Вирт также всегда делал упор на надёжность создаваемых систем: в предполагаемых условиях использования (бортовое ПО, микроконтроллеры важных производственных систем и т.д.) небрежность в коде может стоить очень и очень дорого. Поэтому все ненадёжные средства раз за разом жёстко вырезались (ну или просто не добавлялись). В частности, Вирт негативно высказывался по поводу обобщённого программирования в C++, поскольку автор темплейта не может предугадать все возможные варианты его использования, а пользователь в свою очередь может не знать о подводных камнях. Например, обобщённая функция сортировки может рассчитать на оператор ">" для сравнения элементов, а пользователь может использовать в качестве параметра тип, для которого ">" означает что-то совершенно другое, например, запись в сокет. При этом при неудачном стечении обстоятельств полученный после подстановки в темплейт код действительно скомпилируется, однако работать, очевидно, будет совсем не так, как ожидается. Да и в целом метапрограммирование всё-таки считается продвинутой и не самой безопасной техникой, даже в самом метапрограммном языке — Лиспе.

В то же время, функции высшего порядка в Обероне имеют место и, насколько я помню, считаются вполне кошерным средством. Полиморфизм представлен в Обероне-2 (хотя также довольно строгий). ООП ограничено разве что инкапсуляцией на уровне модуля, а не класса, но это уже вопрос вкуса (например, на мой личный взгляд такой подход к инкапсуляции гораздо, гораздо удобней). Наследование и полиморфизм, как я уже говорил, в нём есть. Что такое параметризованные модули, честно говоря, я не понял (мне в голову приходят разве что функторы в OCaml, преимущество которых перед объектами/замыканиями я так и не понял).
В отличие от объектов/замыканий они могут экспортировать и принимать в качестве параметра абстрактрые типы данных. Это отличие хорошо описано в TAPL.
Так мы всё-таки про функторы? Тогда согласитесь, что и большинство других языков (в т.ч. суперзвёзд таких как Common Lisp или C++) лишены этого преимущества.
Языки вообще сильно разные ;-).
А есть ли в Обероне операция по типу foreach для обхода коллекции?

Из моего опыта вероятность того, что оператор ">" будет означать запись в сокет минимальна, в то время как ошибка в границах коллекции в циклах вроде for i = 1 to N — это просто классика жанра.
В Oberon-2 вернули цикл for, это самое близкое. foreach Вирт не допустил бы как что-то ужасно излишнее. И я даже вполне верю, что при специфике его работы foreach не особо полезная функция (хотя лично мне без неё было бы грустно).
Вот в этом и проблема, потому что сначала нам рассказывают про инструменты, «простые как скальпель», которые благодаря своей простоте «предохраняют от ошибок», но потом на практике оказывается, что всё это на самом деле болтовня. Потому что да, чем меньше инструментов, тем меньше способов ошибиться. Но чем проще инструмент, тем хуже он подходит для решения любой отдельно взятой задачи, и в итоге провоцирует совершать идиотские ошибки, просто по невнимательности, да и плодит сущности там, где это не надо. Например, в Паскале если мне надо просто выполнить действие для каждого элемента коллекции, у меня возникает абсолютно избыточная сущность «индексатор i», хотя в моей задаче его нигде не было.

Ну то есть по сути предлагается альтернатива: либо вафельница + тостер, либо сковородка. Да, в первом случае сущности две, но неправильно их применить трудно. А во втором случае сущность одна, но ошибиться можно миллионом способов.
Давайте по порядку. Одна из основных идей Вирта в том, что небольшое хорошо продуманное ядро системы работает гораздо лучше большой кучи пересекающихся фич. Проще всего это объяснить на примере сравнения с C++. Моя любимая проблема в плюсах — это как согласовать ссылки и указатели. В одном месте мне более удобными показались ссылки, в другом — указатели, а когда я попытался их совместить, получился венегрет. Ну ладно, после недели терзаний решил перейти только на указатели, а ещё через неделю встретился с программистом, который, после таких же мыслей, перешёл исключительно на ссылки. И снова беда. Вирт в своих языках проповедует идею того, что должен существовать ровно один способ сделать что-то. Этот единый способ может быть немного менее удобным, чем несколько отдельных, но зато потом не будет никаких проблем при сомещении подсистем. Т.е. минимализм ядра системы в первую очередь нужен для гибкости на уровне дизайна системы.

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

Наконец, не стоит забывать, что Вирт — программист системного уровня. Возможно, что для него удобство цикла foreach далеко не так очевидно: это мы с вами привыкли проходить весь массив целиком, я для него более привычным может быть оперирование элементами с 15 по 25, или вообще ведение нескольких индексов внутри одного цикла, или ещё что-то. Не владея спецификой лично я не могу сказать, почему выбор был сделан в эту сторону.

В дополнение к выше сказанному, надо заметить, что классический Oberon — это авторский язык. Он был опробован его автором и группой приближённых на реальных задачах и сформировался в соответсвии со вполне прагматичными целями. В то же время, у сообщества круг задач шире, чем у одного человека, поэтому последователи создали расширения, такие как Oberon-2 и Active Pascal. Однако общая идеология осталась той же: средства языка подбирались очень аккуратно и так, чтобы каждое из расширений довало максимальный эффект при минимуме изменений.

Заметьте, что тот же подход использует Гвидо ван Россум в Python — новые принципиальные фичи проходят долгий путь отбора прежде чем попасть в язык, а дублирующиеся функции вырезаются (например, reduce, который Гвидо предлагает делать через циклы).
Да, в этом смысле проблема C++ показательна, потому что Страуструп в «Дизайн и эволюция С++» пишет, что ссылки были введены ради перегрузки операторов. Тут было два пути — либо отказаться перегружать операции, либо отказаться от ссылок. Проблема в том, что «по Вирту» надо было вообще отказаться от нужной фичи из-за того, что она частично пересекается с существующей. Ну или переписать весь язык с нуля, да. В этом смысле С++ похож на человеческие языки: в нём сосуществуют самые разные «пласты» лексики. Некоторые явно архаичны, но с этим ничего не сделаешь.

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

А по поводу «набора фич» — в общем-то С++ тоже консервативен. Апдейт стандарта раз 13 лет — разве это часто? А на выходе такая разница с Обероном. А вот С#, конечно, бешеная собака. Я не успеваю версии отслеживать.
Ну или переписать весь язык с нуля, да.

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

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

Против темплейтов главный аргумент в том, что они позволяют генерировать код без осознания всего, что может быть внутри. Т.е. индексы у вас всегда перед глазами (да и, если честно, привычка писать `i < len(array)` вырабатывается быстро, а другой код автоматически вызывает раздражение рецепторов), а вот что находится внутри темплейтов не всегда известно. Т.е. тут больше вопрос ошибки в понимании, а не ошибки по невнимательности.

Так или иначе, это решение Вирта, и в контексте Оберона мы можем соглашаться или не соглашаться, но реализация останется такой.

Апдейт стандарта раз 13 лет — разве это часто?

Зато сколько всего в каждом апдейте! ;)
Да уж. По поводу шаблонов — не зря Страуструп сокрушался, что в стандарт так и не вошли концепты. Если дождёмся, полегчает. Хотя язык станет ещё монстроуознее.

А «написанный с нуля С++» уже есть — язык D. Вон какой популярный, все на нём только и пишут :)
И еще отказ от обобщенных функций (шаблонов) приводит к невозможности создавать эффективные библиотеки. То есть каждый проект делается фактически с нуля и борьба со сложностью сводится к тому, что на слишком сложные проекты не хватает времени и средств.

Для программирования контроллеров перспективен подход, когда программа генерируется из декларативного описания.
It depends. С одной стороны, шаблонные коллекции в C++ STL — это, конечно, штука мощная. Но с другой стороны, в голом C у вас по сути есть только массивы, которые сразу обладают типом. И ничего, пишут ведь на нём огромное количество кода.

Очень сложно оценивать преимущества или недостатки языка в отрывае от задачи. В Python после Lisp-овского макропрограммирования мне очень сложно работать с AST, а в Lisp-е после NumPy-евских массивов очень сложно работать с линейной алгеброй. И обоих языках задалбывает писать кучу дополнительных проверок, чтобы обойти динамическую типизацию там, где лучше подошла бы статическая.
Да, пишут. Но разве я сильно ошибусь, если предположу, что ниша C постепено отходит к задачам, где основная работа как раз и производится с такими массивами?.. Рискну сделать и более сильное утверждение: в 2014 году язык С уже не может считаться языком общего назначения.
Язык общего назначения — это красивое слово, которым обозначают язык, на котором можно более или менее удобно писать программы в двух-трёх областях. Например, на PL/SQL или на MATLAB довольно сложно написать веб-сервер, на C это гораздо проще. Но за пределами этих двух-трёх областей языки всё равно сильно разбиты по нишам. Вы ведь не станете писать сайт на C++ или драйвер на PHP, не так ли?
Да, конечно, тут можно многое обсудить. Для меня «язык общего назначения» — это, скажем так, второй язык программирования. Если в качестве первого языка я бы предложил изучить что-то простое и полуигрушечное (вроде SmallBasic), то в качестве второго языка это был бы тот самый наш «общеназначенец». И это был бы явно и не SQL, и не MATLAB, и не PHP.
Я слышал, что Oberon используется в каком-то университете в качестве первого языка программирования как раз. В другом университете в качестве второго, но первый ещё интересней — Haskell :)
NumPy — всего лишь библиотека. Есть ли подобные для Common Lisp не знаю, но есть lisp-подобный язык LUSH, который с линейной алгеброй справляется хорошо.
Сам я с линейное алгеброй работал в R.
Для Clojure есть Incanter, который как раз реинкорнация R на Лиспе. Но по удобству с NumPy не сравнить: проблема лежит в самой идеологии — Clojure предполагает функциональный стиль и порождение нового объекта при любой мутации, для вычислительной математики это сразу убийство (представьте себе цикл по всем пикселям изображения, где на каждой итерации значение пикселя меняется и картинка дублируется ;)). Получается, что либо мы дико проигрываем в производительсноти, либо теряем всё удобство языка.
Ну вот почему вы всё время ударяетесь в общие рассуждения? Ведь мы же все здесь программировать умеем. Покажите на примере, как простой инструмент решает сложную задачу, и мы сразу же поймём. По крайней мере, я.

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

В качестве подсказки. При переходе от Паскаля (классического) к Модуле-2 Вирт добавил всего одну новую ключевую концепцию — модуль. И чисто алгоритмический язык стал применим для работы на уровне абстрактных типов данных и в коллективной разработке. Стал и языком системного программирования.

При переходе от Модулы-2 к Оберону Вирт опять-таки добавил всего одну ключевую концепцию — type extension (расширение типа на базе RECORD-структур). Фактически это интересующий вас механизм для generic-программирования и для ООП (ООП-ассемблер). Изучите внимательно, что такое type extension, и многие вопросы для вас отпадут сами собой.
Дайте мне десять строк кода сортировки, и это мне поможет гораздо больше, прошу.

И да, в Бейсике есть абстрактные типы данных. И из книги Вирта AD я не увидел особой разницы. Многие листинги оттуда прекрасно переносятся на Бейсик.
Прочитайте про type extension. Это меньше страницы в описании Оберона.
Я прочитал, но всё равно вопросов больше, чем ответов. Хочется видеть, как это реально выглядит.
Задавайте вопросы. Что вам конкретно непонятно в type extension?
Вот если бы я увидел код, вопросы бы отпали сами собой.
В частности (опять же, мы теряем время, потому что я вынужден формулировать все вопросы, которые и так бы прояснились при виде кода):

1) Можно ли получить тип на основе нескольких базовых? Это необходимо в моей задаче.
2) Как имея только базовый тип, написать код присваивания объектов производных типов?
3) Как конкретно можно разрешить автору производного типа передать алгоритму сортировки (который ничего не знает о производном типе) функцию сравнения?..
1. В Обероне нет множественного наследования.

T = RECORD END;
T1 = RECORD (T) field: AbstractType END;

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

2. Разделение между generic-алгоритмом и абстрактной структурой данных (ADT) может достигаться путём декомпозиции на модули: модуль (ADT), экспортирующий функции работы со скрытыми структурами, и алгоритмический модуль, импортирующий ADT-модуль.
Оставим пока наследование, потому что второе — это проблема.

Как алгоритмический модуль может импортировать ADT-модуль, если ADT-модуля ещё нет? То есть я вот хочу написать библиотеку алгоритмов, которой могут воспользоваться неизвестные мне люди. Классическое разделение труда.
Однако жизнь показала, что идея эта нежизнеспособна, потому что сложные понятия требуют сложного языка. И даже те языки, которые начинались как «простые» (вроде тех же C# и Java), сейчас по сложности стремительно догоняют C++.

Ну почему же. Полноценный Lisp можно построить на 5-7 базовых специальных формах, при этом мощность получившегося языка будет зашкаливать (что и обеспечивает поразительную живучесть и перерождаемость языка). Другой пример — Python, который весьма консервативно подходит к добавлению новых функций, но при этом прекрасно подходит для создания нетривиальных алгоритмов и проектирования сложнейших систем. Java и C# — это скорее неудачные исключения, в которых изначально был заложен неправильный базис, дающий слишком мало гибкости. В Обероне же Вирт, наоборот, постарался подобрать именно тот базис, который при минимальном количестве средств даёт максимальную гибкость.
Lisp-подход к управлению сложностью — создание DSL. Хотя базовый Lisp или Scheme очень компактны, Common Lisp уже сравним по сложности с C++. Правда, освоив сложность языка потом можно писать очень выразительные, эффективные и легко поддерживаемые программы. То есть Lisp предлагает управлять сложностью, а не бежать от нее.

Python по моим наблюдениям, в борьбе со сложностью ни чего особенного не дает. Он, как и Oberon, предоставляет простой в освоении и использовании синтаксис, и большое количеств библиотек (в отличие от Oberon). Это дает низкий уровень вхождения, но совершенно бесполезно при разработке больших систем. Успешные применения Python обусловленны в основном его широким распространением.
То есть Lisp предлагает управлять сложностью, а не бежать от нее.

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

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

Ну вы даёте! Первые версии движка гугла были на писаны на Python, и слезли с него в основном из-за необходимости максимальной производительности (но до сих пор очень и очень активно используют его для других вещей). Сколько крупных сайтов на Django, сколько кластеров управляется Python-скпритами. И ещё много кого! Даже NASA использует его в системе планирования. Какие же ещё большие системы вы имеете ввиду, где Python совершенно бесполезен?

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

Успешность проекта во многом определяется квалификацией програмистов, а не языком. Понятно, что чем распространенный язык, тем больше абсолютное количество и программистов высокой квалификации, его используещие. То есть и больше успешных проектов. Теорема Байеса из статистики.
Вряд ли соглашусь. Языки вроде LISP или FORTH живучи и мощны, но я думаю, что они обладают слишком ограниченными средствами для описания моей проблемы на моём языке, скажем так. Это языки, которые «ломают программиста через колено». Если на всё смотреть сквозь призму FORTH или LISP, то да, на них можно сделать что угодно.

Если бы всё было так просто, на LISP писали бы всё подряд, и у языка вроде Java не было бы никакого шанса выжить.

Python я бы не назвал слишком простым языком. В него легко войти, но встроенных средств в него заложено очень немало. К тому же предположу, что рано или поздно и там начнутся добавления, потому что будет «почему Вася может написать на своём языке Х, а я не могу?»

Да и у Питона свои недостатки (которые являются продолжениями его достоинств) — интерпретация, динамические типы. Не всегда я им рад.
Распространенность языков программирования определяется многими факторами, часто с положительными обратными связями.
Эффективная реализация Lisp достаточно сложна и в те времена он не мог конкурировать с языками типа C. Язык С, благодоря нетребовательности к оптимизатору (техническая характеристика) и открытости (организационная характеристика) получает широкое распространение и становится de facto стандартом синтаксиса и средним программистам уже сложно воспринимать что-то другое. Вместе с синтаксисом программиты перестают воспринимать и отсутствующие в C понятия — lambda-исчисление, pattern matching. Тот же Python следует хоть не синтаксису, но практике оформления кода, принятому в C/C++, вводя очень ограниченное количество новых идей.
Это так, но из этого не следует, что в параллельной вселенной, где всё наоборот, LISP бы оказался впереди.

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

Когда ещё не было никакого C, LISP мог конкурировать с Бейсиком, однако вот как-то воспринимался Бейсик попроще.
Бейсик проще в реализации (простые структуры данных) и в освоении преподавателями.
Ну вот это проблема курицы и яйца: Бейсик появился позже Лиспа, так в чём же проблема освоения преподавателями, которые на тот момент были tabula rasa?
В том, что преподавали люди, программировавшие на Fortran и C.
Ну и математическая подготовка для понимания списков и lambda-исчисления требуется выше.
Не складывается. Фортран всего на год старше Лиспа, а C на пятнадцать лет моложе.
А вот про подготовку поверить могу. Но это уже к вопросу о «ломании через колено».
Так мы про Бейсик — время, когда преподавать программирование стали массово.
На часть высказываний уже ответили, поэтому я сосредоточусь на следующих:
Python я бы не назвал слишком простым языком. В него легко войти, но встроенных средств в него заложено очень немало. К тому же предположу, что рано или поздно и там начнутся добавления, потому что будет «почему Вася может написать на своём языке Х, а я не могу?»

Ну смотрите, попробуем перечислить базовые понятия Python, составляющие ядро языка:

1. object
2. callable
3. class
4. module
5. package
6. generators/iterators

Плюс есть несколько расширенных фич:

7. decorators
8. context («with» statement)

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

Да и у Питона свои недостатки (которые являются продолжениями его достоинств) — интерпретация, динамические типы. Не всегда я им рад.

Интерпретация — это всё-таки способ выполнения программы, а не особенность языка. PyPy, например, прекомпилирует код перед выполнением.
А если вам по вкусу статическая типизация, то всё вообще прекрасно — есть Cython, в котором есть опциональное декларирование типов, и модули на котором элементарно подключаются в основному проекту на обычном Python ;)
Я думаю, если такими широкими мазками перечислять базовые понятия C++, окажется примерно столько же :)

Интерпретация и типизация, я бы сказал, очень важное свойство языка. Именно благодаря этим штукам в Python так изящно работает duck typing и гораздо меньше головной боли с частично пересекающимися в целях механизмами шаблонов и наследования в C++. Ведь если подумать, сколько всего в C++ наворочено лишь ради того, чтобы код можно было откомпилировать…
В C++ очень много пересекающихся понятий, служащих, по большому счёту, для одних и тех же вещей. Классический пример — указатели (pointers) и ссылки (references). Понятно, что они не идентичны, но в 99% случаев они выполняют одну и ту же функцию. То же самое касается const и макроподстановок. И ещё десятка фич. А ещё два десятка нужны для того, чтобы как-то склеить в одной программе предыдущие десять — как вы правильно заметили, «сколько всего в C++ наворочено лишь ради того, чтобы код можно было откомпилировать» :)

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

В процессе развития языка всегда возникает дилемма: порвать с прошлым и переписать заново, либо сохранять всё в языке. Конечно, в первом случае мы получаем красоту, но никто с таким языком не захочет иметь дела. Даже весьма скромные обновления Python в третьей версии вызвали раскол, до сих пор не преодолённый.

А С++ да, сохраняет все те окаменелости, которые давно пора бы выбросить, но нельзя. Я вот не знаю, если бы на месте Страуструпа решил, что перегрузка операторов нужна, чтобы я делал? Наверно, тоже ввёл бы ссылки. Макроподстановки взяты ещё из C, стало быть, в С++ надо было не делать const вообще или переписать механизм макросов.

В общем, всё плохо :)
Ну вот как раз Python — это хороший пример языка, на котором и пишут, и практически не ругают (а если ругают, то больше за реализацию, а не за спецификацию). При этом ядро языка ведь действительно небольшое, а концепции простые. Всё есть объект, т.е. структура, имеющая атрибуты и значение. Некоторые объекты являются вызываемыми и имеют прикреплённый исполняемый код. Всё. Все остальные концепции можно объяснить через эти два понятия и даже написать их реализацию без «синтаксического сахара». И ведь вполне популярный язык ;)

Что же касается перехода на тройку, то тут дело не в новых стандартах. Т.е., конечно, есть люди, которым не нравятся именно изменения в языке, но таких меньшинство. Большинство же следует принципу «работает — не трогай». Python 2 уже достаточно хорош, чтобы не спешить что-то менять. Плюс старые версии языка на серверах (мы щас менаем системный с 2.4 (!) на 2.6, а вы говорите про 3), плюс ещё не портированные библиотеки (мне вот критически важен OpenCV, я обёртка для него работает только со второй версией Питона)… В итоге все (ну почти все) вроде бы согласны, что переходить надо, но вот прямо сейчас мало кто готов это сделать.
Безусловно, заслуга Вирта в том, что он один из первых осознал необходимость борьбы со сложностью и относительно успешно эту борьбу начал.
Но это борьба состояла в играх с синтаксисом и ограничением на ввод новых концепций, при этом сохраняя старые. Вирт в своих разработках прочно держится за императивное программирование, тщательно игнорирую обобщенное, функциональное и, даже, ООП.
Думаю, что вы недостаточно хорошо знаете то, что делал Вирт.

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

Когда я на это смотрел, я не нашел принципиальных отличий от наследование в стиле ООП.
К тому же на ООП не надо зацикливаться. Параметрический полиморфизм проще и полезнее, чем полиморфизм на основе подтипов.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории