Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Философия языка

Язык, который не меняет вашего представления о программировании, недостоин изучения.
Alan J. Perlis

В качестве вступления

Все языки программирования можно разделить с известной долей погрешности на две категории.
  • Первая: языки, допускающие эффективную реализацию. Их эффективность направлена либо на наибольшую скорость исполнения, либо на экономию вычислительных и других ресурсов (объём памяти, потребление электроэнергии),
  • Вторая: языки, которые ставят целью наибольшую скорость работы программиста, а не программы. Поэтому на некоторые не совсем эффективные решения закрываются глаза. Ну и что, что в PHP массивы реализованы посредством ассоциативных массивов: $array[2] не подразумевает прямого обращения по индексу 2, здесь происходит обращение к элементу ассоциативного массива по ключу 2. Ведь работает, не правда ли?
        Возможно, имеет смысл говорить и о третьей категории языков, которые ставят своей целью максимальный охват вычислительных платформ. Здесь идут вход виртуальные машины, байт-коды. Поступившись некоторой долей производительности («родной» код быстрее байт-кода), виртуальная машина работает в известной степени одинаково на разных платформах. Поэтому написанный код поэтому не требует переделок или их число невелико. В этом можно увидеть экономию труда разработчика, повышение его производительности. Следовательно, это направление языков можно отнести ко второй категории.
Философия языка
        Каждая философия имеет право на жизнь, многие развитые языки могут найти свою аудиторию и свою нишу. Каждый подход имеет как преимущества, так и обратную сторону. Создать же язык, который был бы настолько универсален, что сочетал бы в себе все возможные философии, все известные парадигмы, все эффективные практики программирования, увы, никому не удавалось. Поэтому разрабатывая язык, надо определиться с его будущим назначением. Ниже обозначены цели, которых бы хотелось достичь при разработке языка. Несогласные с ними могут начать свой проект или присоединиться к существующим, благо, их хватает. А теперь —

Философия языка

  • Лаконичность, простота и ясность языка. Простота является самостоятельной ценностью. Простота тесно связана с лаконичностью. Кто растекается мыслью по древу, тот теряет нить логики. "Короче, Склифоссофский!". Чем меньше исключений из правил, тем проще правила выполнять.

  • Двоичный исполняемый код, у которого больше преимуществ и меньше недостатков, чем у интерпретируемого кода. Это здорово — иметь исполняемый код, который сразу готовый к исполнению, которому не нужны интерпретаторы, фреймворки и виртуальные машины. Недостаток последних не только в том, что они медленнее. Но и в том, что их не нужно устанавливать только тогда, когда вы — Microsoft. Лучше один раз откомпилировать, чем сто раз интерпретировать. Где можно найти исполняемый код javascript и скопировать их на другой компьютер?

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

    Замечательно, что благодаря закону Мура мы удваиваем свои возможности каждые полтора года. Но нет причин приветствовать удвоение с той же регулярностью объема кода, необходимого для вывода "hello, world". Исполняемый код для вывода "hello, word", выданный Qt, примерно 210 раз больше, чем необходимо для вывода этой надписи. Такое разбухание кода заняло примерно 15 лет, так что закон Мура работает и для ПО.

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

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

    255 + 1 не равно 0, 65 535 + 1 не равно 0 и 4 294 967 295 + 1 не равно 0, но 0.1 * 6 равно 0.6. В отличие от C/C++ и многих других языков. Программы не должны молчать об ошибках, потому что их тогда не исправят.

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

В качестве послесловия

        Это можно считать последним, но тоже важным пунктом философии. Разрабатывая язык, нужно постоянно задавать себе вопрос: «А что в нём есть такого, чтобы заинтересовать будущих пользователей?» Для успешности новому языку программирования нужна критическая масса удачных нововведений. Появляясь на свет, новый язык не имеет многое из того, что имеют старые языки: библиотек, IDE, литературы и прочего. Будущие пользователи языка могут простить эти болезни становления, если в нём предлагаются хорошие идеи. Если их недостаточно, если язык является лишь новой комбинацией старых известных ингредиентов, то надо много раз подумать, а нужен ли он вообще.

Опубликовано: 2016.01.28, последняя правка: 2019.01.26    20:51

ОценитеОценки посетителей
   ████████████████████████ 9 (56.2%)
   ██████ 2 (12.5%)
   ███ 1 (6.25%)
   ███████████ 4 (25%)

Отзывы

     2016/04/03 16:22, Вежливый Лис          # 

Философия русского языка неотделима от философии русской культуры.

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

     2016/04/03 16:44, Автор сайта          # 

Тут о философии языка программирования, а не философии русского языка и культуры. Как связаны между собой программирование, фашизм, русский «искин» и американский?

     2016/04/04 13:59, Вежливый Лис          # 

Вы пишете просто о разработке НОВОГО языка, а не русского. Разработать новый язык сейчас большой проблемы нет. Пример — VladD2 с сайта rsdn разработал язык Nemerle. С вашей точки зрения это русский язык.

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

     2016/04/04 16:40, Автор сайта          # 

1) Русский язык создавать не надо, он уже есть силами А.С. Пушкина, Л.Н. Толстого и других великих россиян.
2) Nemerle создали поляки Михал Москаль, Камиль Скальски и Павел Ольшта.
3) За непосильные задачи не берусь.

     2016/04/04 18:20, Вежливый Лис          # 

1. разумеется я не имел в виду, что надо создавать русский язык. Я предполагал, что это Вам будет понятно (потому что факт существования русского языка известен и мне и вам, он общеизвестный). Поэтому я сократил группу существительного "русский язык программирования, отличающийся от других языков именно теми особенностями, которые он берет из русского естественного языка" до одного слова "русский". К сожалению, Вы слишком высокого о себе мнения и считаете меня дурачком, поэтому не справились с задачей восстановления смысла фразы. В дальнейшем буду Вам тщательнее разжевывать.
2. Поляки конечно создали, но если смотреть по объему вклада и текущим мейнтейнерам — сейчас есть сильная русская команда.
3. Только ставя идеальные цели можно добиться хоть чего-нибудь отличающегося от среднего. Иначе можно сидеть и спокойно калякать себе на 1С.

     2016/04/05 13:16, Автор сайта          # 

1)

Вы слишком высокого о себе мнения

Со стороны, вероятно, виднее. Но я стараюсь выражаться чётко и недвусмысленно. И желаю того же от других. Каков вопрос, таков ответ. 2) Вы приписали авторство языка человеку, может быть и уважаемому, но забыли упомянуть подлинных «родителей». Это несправедливо. 3)

Только ставя идеальные цели можно добиться хоть чего-нибудь отличающегося от среднего

а) Не только идеальные, но и реалистичные. Что толку ставить перед собой невыполнимые задачи?
б) Создание языка, отличающегося от «среднего», не является простой задачей. Попробуйте умножить на Си 0.1 на 6 и сравните с 0.6, увеличьте unsigned char 255 на 1 посмотрите результат. После этого понятно, почему во всех лицензионных соглашениях пишут, что они «ни за что не отвечают»: ну какие могут быть гарантии, когда (смотри результаты примеров на пару строк выше) допустимы такие ошибки? Языки есть куда улучшать, потому что существующие языки действительно средние, и даже весьма.

     2016/04/05 14:57, Вежливый Лис          # 

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

Да есть определенные неясности, Пенроуз против, но это решаемые задачи (выяснить неясности и опровергнуть Пенроуза практически).

     2016/04/05 16:56, Автор сайта          # 

Не берусь за то, в чём не специалист. Если Вам это по силам, то только могу пожелать удачи. Домен iskin.su свободен, а iskin.tk ещё и бесплатен.

     2016/04/05 17:24, Вежливый Лис          # 

Не берусь за то, в чём не специалист.

А кто мне говорил, что это фигня, что Лисп не выучен, и всё можно изучить? Конечно, это разного уровня сложности задачи, но принцип-то один — дорогу осилит идущий.

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

     2016/04/05 17:59, Автор сайта          # 

А кто мне говорил, что это фигня, что Лисп не выучен, и всё можно изучить?

Не могли бы дать ссылку, где были такие слова?

Честно говоря, Lisp не интересен, причины — в приведённой выше статье. По той причине, есть желание сделать язык, подходящий для системного программирования, где можно было бы использовать русский язык — как это делалось или делается в Эль-76, Алгол-68, Кумир, 1С. Или ещё лучше. Приспособить же естественный язык для программирования — затея сомнительная. Но если Вам удастся — порадуюсь за Вас. «Я не удивлюсь, если программирование станет ещё более формализованным и отодвинется от обычной человеческой речи ещё дальше» — ответил Б. Страуструп на вопрос о будущих языках программирования. Опровергайте автора C++.

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

Нет, хочу привнести в язык то, чего нет в других. Кое-какие наработки уже есть.

     2016/04/05 18:22, Вежливый Лис          # 

http://ruscomp.24bb.ru/viewtopic.php?id=79#p2070

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

     2016/04/05 19:09, Автор сайта          # 

Так Вы же жаловались:

Я бы присоединился, да Лисп в школе не изучал...

И я этому удивился:

Да мало ли чего мы не изучали в школе! Я в школе вообще ничего по программированию не проходил. И что теперь, вообще не программировать? Те языки, что сейчас использую, я даже в вузе не изучал. Всё самостоятельно изучалось. Программист, который не занимается самообразованием, быстро становится ненужным.

Одно дело — изучать языки — тот самый инструмент, без которого не мыслим программист. Другое дело — изучать какие-то новые прикладные области для программирования. Меня не тянет, например, программировать бухучёт или Интернет-магазины. Так же не тянет заниматься ИИ. Ведь совсем иная специальность.

     2016/04/18 05:06, rst256          # 

1. разумеется я не имел в виду, что надо создавать русский язык. Я предполагал, что это Вам будет понятно (потому что факт существования русского языка известен и мне и вам, он общеизвестный). Поэтому я сократил группу существительного "русский язык программирования, отличающийся от других языков именно теми особенностями, которые он берет из русского естественного языка" до одного слова "русский".

Сообщение прошло, ошибок не выявили, сообщение оказалось понято не так.
Нет, извините, сначала допилите естественный язык, а потом снова посмотрим.
Не переживайте, это касается любого естественного языка. Мы не говорим, что он плохой, он просто не для этого. Николай Лобачевский дал замечательно яркую оценку искусственным языкам: «Чему одолжены своими блестящими успехами науки, слава нынешних времен, торжество ума человеческого? Без сомнения, ИСКУССТВЕННОМУ языку своему!»

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

     2016/04/18 05:59, rst256          # 

Если выйдет, мы становимся богаче на ещё 1 раздел математики.

     2016/04/18 06:11, rst256          # 

Вежливый Лис, правда хотите участвовать в разработке ИИ, или составлением грамматики русского языка? Я окажу вам любую посильную помощь, возьметесь за вопрос выделения именной группы. Там легко, других групп не будет, просто притянуть идентификаторы, разделенные пробелами, к смыслу. Например, чтобы «длина входной строки» превратилось в «длина(входной строки)»

     2016/04/18 09:11, utkin          # 

Лаконичность, простота и ясность языка. Простота является самостоятельной ценностью. Простота тесно связана с лаконичностью. Кто растекается мыслью по древу, тот теряет нить логики. "Короче, Склифоссофский!". Чем меньше исключений из правил, тем проще правила выполнять.

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

Двоичный исполняемый код, у которого больше преимуществ и меньше недостатков, чем у интерпретируемого кода. Это здорово — иметь исполняемый код, который сразу готовый к исполнению, которому не нужны интерпретаторы, фреймворки и виртуальные машины. Недостаток последних не только в том, что они медленнее. Но и в том, что их не нужно устанавливать только тогда, когда вы — Microsoft. Лучше один раз откомпилировать, чем сто раз интерпретировать. Где можно найти исполняемый код javascript и скопировать их на другой компьютер?

О, мечты. Опять идеализм. Нет, правда. 64-битные приложения не работают на 32 бит. И все. Даже для винды для разных версий нужны разные версии программ. Поэтому фреймворки и введены собственно, чтобы перешагивать аппаратные проблемы.
Есть куча программ, которые без javascript на другом компе не запустятся. А уже про межплатформенные ограничения вообще молчу: винда и линукс как-то не взаимодействуют. Конечно, есть wine и вроде как вин10 хочет исполнять линуксные elf файлы, но это пока не решение, а костыль по сути. Поэтому и силен Ява — он межплатформенный. Конечно, пляски с бубуном тоже нужны, но их надо на порядок меньше. Возьмите фреймворк NetBeans. Там чуть ли ни своя операционная система, чтобы все работало и переносилось из одного окружения в другое.

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

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

Замечательно, что благодаря закону Мура мы удваиваем свои возможности каждые полтора года. Но нет причин приветствовать удвоение с той же регулярностью объема кода, необходимого для вывода "hello, world". Исполняемый код для вывода "hello, word", выданный Qt, примерно 210 раз больше, чем необходимо для вывода этой надписи. Такое разбухание кода заняло примерно 15 лет, так что закон Мура работает и для ПО.

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

     2016/04/08 13:17, Автор сайта          # 

Уткин: сочувствую, что Ваше сообщение обрезалось. Но я и так доводил длину сообщения до 4K. Теперь сделал 10. Но Вам посоветовал бы текст набирать в Ворде.

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

     2016/04/18 13:21, rst256          # 

Вот обрезался пост и даже не предупредил. Автор сайта, пожалуйста подредактируйте, а то у меня полпростыни ответа съело и выглядит теперь некрасиво — цитата есть, а ответа нет.

От души сочувствую, вообще отношение браузера к набранному тексту просто свинское, любой редактор при закрытии спросит о не сохраненном тексте, но не браузер. Может он не редактор текста, но думаю, нам на это плевать, когда случайно закрываем страницу с отправленным постом ...
А Автору сайта думаю пора уже приделать ссылку на форум, наверное вы не знали у сайта есть форум :-)
http://compiler.forumcity.com/posting.php?mode=newtopic&f=2

     2016/04/19 21:06, rst256          # 

Но я и так доводил длину сообщения до 4K. Теперь сделал 10.

А ограничение ну конфиге выб сервера или уже в php? Если в php возвращайте текст назад с ошибкой, главное же текст не потерять.

     2016/04/28 23:27, Автор сайта          # 

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

     2016/05/04 19:29, utkin          # 

А какие задачи должен решать язык? А то как-то все расплывчато...

     2016/05/05 11:02, Автор сайта          # 

На то она и философия, чтобы избежать превращения в статичное техническое задание. Написана в подражание Python. Насколько мне известно, это единственный язык, имеющий сформулированную философию (у Python она состоит исключительно из расплывчатого). Философия разрабатываемого языка является концентрированным выражением мыслей и идей как автора, так и некоторых соратников, сочувствующих и просто наблюдателей. Задаёт направление движения и желаемые цели. Имеет прикладное значение: отсечь те предложения, которые разворачивают разработку на второй путь (см. классификацию языков программирования в начале статьи).

     2016/05/05 13:07, utkin          # 

Я воспринимаю философию как базовые рамки, на основе которых и нужно уже строить техзадание. Философия пусть и не явно, но рассматривается в функциональном стиле — это просто необходимо для понимания концепций. Ну вот сейчас, если сформированы основные мысли, наверно можно определять некоторый круг задач. Я представляю это как универсальный язык программирования, но имеющий более выскокуровневые механизмы по сравнению с Дельфи и С++. Ну типа нет необходимости следить за удалением объектов как в Яве, но более продвинутый синтаксис, типа как Питон. То есть как более мощное и современное продолжение С++ (по области применения, а не по семантике/синтаксису).

     2016/05/05 13:48, Автор сайта          # 

Вы правильно понимаете, это действительно эскиз словами. Который можно и должно шлифовать. Но границы, тем не менее, очерчены.

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

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

     2016/05/19 07:10, rst256          # 

Ну и что, что в PHP массивы реализованы посредством ассоциативных массивов: $array[2] не подразумевает прямого обращения по индексу 2, здесь происходит обращение к элементу ассоциативного массива по ключу 2.

Это кривая реализация, а не способ повысить производительность работы программиста. Например таблицы в языке Lua одновременно могут хранить данные в виде обычных и ассоциативных массивов, элементы с индексами 1, 2, 3, и т. д. хранятся в динамическом массиве, остальные в ассоциативном массиве.

     2016/05/20 13:08, Автор сайта          # 

PHP: всё таки дело в языке, а не в криворукости реализаторов. Классический массив имеет индексы, непрерывные на некотором диапазоне: 0 — n (Си) и m — n (Паскаль). Наибольшее и наименьшее значения индексов статичны (известны во время компиляции) или подвижны (не фиксированы, но известны к моменту создания массива, а далее не меняются: смотри « массивы переменной длины в C/C++»). В PHP границы массива не фиксируются. Можно работать с массивом $array[0..9], но потом бац! и обратиться к элементу $array[100000]. А потом бац! к элементу $array[-100000]. И как такое прикажите реализовать, если язык позволяет такие вольности? Ассоциативный массив просто напрашивается.

Но ассоциативный массив в PHP — это не в чистом виде хэш-таблица. Он ещё обладает свойствами списка. Когда нужно обратиться к элементу по индексу — он хэш-таблица. А когда надо совершить обход контейнера от начала и до конца, то он — список.

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

     2016/06/01 11:15, rusty_cat          # 

Русский язык создавать не надо, он уже есть силами А.С. Пушкина, Л.Н. Толстого и других великих россиян.

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

Контрольное число: ...шестнадцать тсыяч пяьтсот девяносто пять

Я понимаю, кэпча и все такое, но формально такого числа нет, а есть некорректно поставленный вопрос.

     2016/06/01 16:45, Автор сайта          # 

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

2) Это такая капча: некоторые буквы (но не первая и последняя) случайным образом меняются местами. Погуглите фразу «Главное, чтобы первые и последняя были на месте»:

Интересный факт из восприятия человеческим мозгом печатных слов.

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

Это сдалено для защтиы от робертов. Роберт токай текст не помйёт, а чеволек — вплоне.

     2016/06/02 21:50, rusty_cat          # 

1) Языки слабо подвержены веяниям моды, но технологии меняются. Когда-то были только числа, потом строки, порты и файлы, теперь — регулярные выражения, хеш-массивы, SQL, XML/Xpath/Xlink/Xpointer, CSS, интерфейсы (множественное наследование), параллельные вычисления и GUI. Что появится завтра, не могу даже предположить. Языки развиваются, вынужденные включать те или иные нововведения, некоторые нововведения входят естественным образом, некоторые — подобно "костылям".
Так вот про мультипарадигменность. "Язык — не новогодняя ёлка, чтобы иметь на себе все возможные украшения..." От чего мы готовы отказаться?
  • От портов и физических адресов? Хорошо. Значит, все физические устройства, в том числе завтрашнего поколения, не включенные в core языка, нашему программисту станут недоступны. Или, подобно php, будем выпускать "заплатки", которые через пару версий от парадигмы языка оставят рваное одеяло.
  • От SQL? Верно. Кому нужны сегодня реляционные базы данных!
  • От XML и древовидных структур? Отлично. Никакого обмена с другими приложениями. Или, наоборот, заставим программиста каждый раз выдумывать их заново и плодить собственные библиотеки.
  • От CSS? Пожалуй. Будем создавать внешний вид приложений операторами основного рабочего кода.
  • От GUI? Точно. Да здравствует командная строка! До свидания графические системы, цифровая обработка изображений, трехмерная геометрия и иже.
И кстати, неверно, что фреймворки и виртуальные машины "не нужно устанавливать только тогда, когда вы — Microsoft". Я слышал где-то бывают Android, MAC OS и Linux, и даже PSP. Их тоже пора отменять. Сами виноваты, раз не поддерживают наш универсальный бинарный код.
Я все это к тому, что классно звучит — "Лаконичность, простота и ясность" (++), "Компактность и скорость исполняемого кода" (+), "Право на родной язык" (+), "Надёжность и безопасность" (++), "Мультипарадигменность" (++), но как-то попахивает это сферическим языком в вакууме.
В статье не хватает главного — какие классы задач будет решать язык, а какие не будет: математическое моделирование? разработку компиляторов? обработку естественного языка? экспертные системы? диалоговые графические системы? компьютерную геометрию? распознавание образов? будет ли работать с БД? какими? реляционными, объектными, распределенными хранилищами? файловая система? иерархическая или реляционная? как с разработкой сетевых приложений? сервер-клиент? параллельные и распределенные вычисления? и т.д.

2) Как программист вы должны понимать, что означают любые (неочевидные) умолчания в вопросах формализации.
У вас есть четкое и недвусмысленное указание: "Введите цифрами контрольное число".
И есть строка "шестьдесят тсыяч шестьедсят штсеь", которая в соответствии с правилами русского языка содержит единственное число — "шестьдесят", остальное — абракадабра.
Да, человек поймет и прочитает, но мы вроде говорим о программировании? Контрольная строка, приведенная выше, может быть получена из строкового представления контрольного числа путем перестановки цифр, а может, к примеру, кодированием по какой-то таблице. Кроме того, раз буквы в словах переставлены, слова в строке тоже могут быть переставлены в соответствии с перестановками букв и т.д.
И да, если всерьез понадобится, за пару часов я напишу код, который будет переводить эту абракадабру в нормальные человеческие 60066.

     2016/06/02 22:44, Автор сайта          # 

1) Шла речь о языке. О том, что он не должен иметь в себе всё мыслимое и немыслимое. Есть хорошая статья на похожую тему: «Почему Ваза утонул, а С++ всё ещё на плаву»:

Основным принципом постройки корабля было «А почему бы нам не добавить сюда ещё и вот такую фичу?»

Перечисленные Вами технологии (SQL, XML и т.д.) — это всё должно делаться в библиотеках. Причём здесь язык?

Область применения языка видится в системном программировании, т.е. примерно из той же ниши, что и C/C++, D, Rust.

2) Но Вы же не жалуетесь, что графические капчи крайне не разборчивы, они не содержат «чёткого и недвусмысленного указания»? Эту капчу разгадать проще, чем графическую. То, что здесь не видно спама, говорит о том, что капча со своей работой справляется.

     2016/06/03 00:58, rusty_cat          # 

1) "это всё должно делаться в библиотеках"
например, у php "это все" как раз и "делается в библиотеках" (включая SQL, XML и regexp). не правда ли, криво? Но другой вопрос интереснее: что все? Где-то на просторах этого сайта, в статье про Дракон вспоминается, что программы — это главным образом не алгоритмы, а структуры данных. И вот структуры данных, как показывает практика, чаще всего неожиданно появляются. На сегодняшний день мы имеем, кроме простых типов:
- массивы (статические и динамические);
- хеш-массивы, а также такие древние варианты, как struct/union;
- class, prototype, interface в разных вариантах ООП;
- списки типа [T ! H] (lisp, prolog);
- реляционные БД (prolog);
- XML-деревья с возможностью обхода при помощи XPath;
- компактные JSON-структуры, объединяющие простые и ассоциативные массивы;
- регулярные выражения (создаваемые на лету);
- SQL-запросы (создаваемые на лету) и др.
Этот набор реально существующих можно дополнить, к примеру, компактными графами (why not, раз уж мечтать), грамматиками, конечными автоматами, множествами, отношениями, чем чёрт не шутит. И встает вопрос: будем сочинять синтаксис для каждого такого типа?

Как JSON и RegExp в JavaScript, <tagName>...</tagName> для XML и {css-prop: value; ...} для хешей или будем представлять стандартными типами — строками (SQL и RegExp'ы), массивами — результаты выборок из БД и пр., и в результате — тратить время на перекодирование (лексический/синтаксический анализ, ага) и обход стандартными циклами?
А когда потребуются новые типы, что тогда? Все заново или "хрен вам" и кодировать из строк и криво составлять из массивов?

2) "А почему его зовут Неуловимым Джо, Билли?"

     2016/06/03 10:59, Автор сайта          # 

1) Надо начинать с основного, с ядра языка. Реализовать основные виды контейнеров. А потом можно думать над тем, что добавить в ядро, а что переложить на библиотеки. Потому что некоторые вещи в ядре будут явно избыточными. Зачем, к примеру, в языке, на котором будут писаться ОС реального времени, нужны встроенные средства для работы с SQL запросами? Я уже писал, что описанная философия имеет прикладное значение: отсечь те предложения, которые разворачивают разработку на второй путь (см. классификацию языков программирования в начале статьи).

2) Вы правильно заметили, неуловимость — главная гарантия защиты. У Вас были трудности с вводом цифр? Мне кажется, что нет. И если ничего не ломалось, то и чинить не стоит.

     2016/06/03 21:22, rusty_cat          # 

Есть у меня подозрение, что универсальный язык для написания ОС с собственной ОС интересен народу даже меньше, чем язык с фишками для решения прикладных задач. Опять-таки для раскрутки придется создать армию гаджетов, поддерживающих эту ОС.
Впрочем, спасибо за диалог. Я примерно понял, какой язык мне бы хотелось увидеть — такой, в котором можно описать структуру данных и тут же её использовать без всяких костылей, естественным образом: xml ли, xpath ли, лисповские списки. Надо обрабатывать структуры химических молекул или блок-схемы — наследуем от xml, добавляем логику обработки узлов и вуаля. Хочется интерфейс — пишем кусок XUL или XAML, форма есть, ждет обработчиков. А какие там будут унарные операторы и будут ли, невелика разница. Как-то так.

     2016/06/03 23:54, Автор сайта          # 

Значит, вам нужен язык программирования, который ставит целью наивысшую производительность программиста (см. выше — вторая категория языков). Мы же видим перед собой целью язык, обеспечивающий высочайшую скорость программ, а остальное — по возможности. Возможность написать какую-то ОС — это тест для языка, к какой категории он относится. Можно переписать Windows на Lisp или Unix на PHP? Нет, не получится. Значит, они не из первой категории.

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

     2016/10/26 06:46, misha_shar53          # 

То, что сформулирована философия языка, крайне важно. Дальнейшие шаги можно сверять с ней. Попробую эту философию прокомментировать.
1. Лаконичность, простота и ясность языка.
Все ясно, никаких возражений быть не может.
2. Двоичный исполняемый код.
Для философии требование вторичное. Интерпретатор сделать быстрее и на нем проще отработать концепцию языка.
3. Компактность и скорость исполняемого кода.
Пункт тесно связанный с предыдущим, но никаких возражений против него нет.
4. Право на родной язык. Противоречивый пункт. Может сильно снизить ареал распространения. Хотя зависит от того, в каких конструкциях это будет применено.
5. Надёжность и безопасность. 
Нет возражений.
6. Мультипарадигменность.
Само по себе неплохое требование. Но надо подходить к нему очень взвешено, не перегрузив язык разными конструкциями. Этот пункт явно находится в противоречии с первым пунктом.

Послесловие — самая ценная мысль.

Из комментариев становится ясной ниша для языка.

Область применения языка видится в системном программировании, т.е. примерно из той же ниши, что и C/C++, D, Rust. >

Язык системного программирования. Это уже конкретика. Остается выбрать прототип.
Начнем с Си. Соответствует пунктам 1,2,3. Остальным не соответствует.
Язык С++ Соответствует пунктам 2,3,6.
Языки D и Rust не комментирую, не знаю что это такое.
Язык Объектный Паскаль соответствует пунктам 1,2,3,5,6.
Язык Object-C соответствует пунктам 2,3,6.
Анализ конечно бы надо продолжить сравнением с другими языками программирования, но я в этом не силен.
Теперь о главном. Какая есть основная идея улучшения языка? Я такой идеи на сайте не нашел. Обсуждение в разделе «Описание языка» смехотворно. Идей там нет.
Как реализовать 4 пункт «Право на язык» обсуждать нечего. Просто техническая проблема. Пункт 5 очень важен. Каждый из языков его как то решает. Из рассмотренных мной решением является строгая типизация. Объектный Паскаль дополнительно проверяет границы массива. Приведите другие способы повышения надежности языка.
Пункт 6, мультипарадигменность. Здесь непаханное поле идей и основной является конечно же ООП. Но надо выбрать и проанализировать все идеи.
По большому счету то основной проблемой языков этого класса является проблема управления кучей. Ни один из языков её не решает. Есть, конечно, идея сборки мусора , которая реализована во многих языках программирования, но применять её для языка этого класса я бы не решился. Сомнительная идея.
Для нового языка нужна глобальная идея, а пока её нет, остается только заняться анализом существующих языков.

     2016/10/27 18:18, Автор сайта          # 

Интерпретатор сделать быстрее и на нем проще отработать концепцию языка.

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

Право на родной язык. Противоречивый пункт. Может сильно снизить ареал распространения.

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

Остается выбрать прототип

Если взять 20% от C, 30% от D и по 25% от Rust и C++, то такой коктейль трудно назвать оригинальным. В чём новизна?

Какая есть основная идея улучшения языка? Я такой идеи на сайте не нашел

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

Описание языка смехотворно. Идей там нет.

Описание языка — это итог некой работы. Если не описан итог, значит работа ещё не закончена.

основной проблемой языков этого класса является проблема управления кучей

Говорите об этом, при этом не замечаете идей: «Какая есть основная идея улучшения языка? Я такой идеи на сайте не нашел». Ищите.

     2016/10/27 19:09, misha_shar53          # 

Если взять 20% от C, 30% от D и по 25% от Rust и C++, то такой коктейль трудно назвать оригинальным. В чём новизна?

Дело не в процентах, а в удачных идеях. Проще всего искать идеи в уже существующих языках. Ну и конечно если есть собственные, то это просто удача.

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

Прекрасно. Узнать новую идею в языке программирования очень интересно. Буду ждать. Но а не заметить я конечно мог. Извините, если обидел.

     2016/10/28 18:12, Автор сайта          # 

Проще всего искать идеи в уже существующих языках

Язык Rust нравится тем, что в нём есть концепция владения объектом. Но не нравится её реализация. Т.е. сама постановка вопроса, осознание существующей проблемы — это уже достижение. Но хотелось бы придумать что-то более простое и интуитивно понятное.

это просто удача

Типа в лотерею выиграл? Нет, многие идеи вынашивались годами, хотя в итоге посторонний взгляд зачастую не увидит за простотой решения долгих размышлений.

Но а не заметить я конечно мог.

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

Извините, если обидел.

Да какие обиды? Бросьте.

     2016/10/29 12:50, rst256          # 

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

А почему мы забываем про наши собственные ЯП? Советую взглянуть на язык Эль-76
https://yadi.sk/d/6HM5BM4bxmphK
Например обработка ситуаций (стр. 158) очень интересный вариант реализации механизма исключений.

     2016/10/30 07:53, misha_shar53          # 

Типа в лотерею выиграл? Нет, многие идеи вынашивались годами, хотя в итоге посторонний взгляд зачастую не увидит за простотой решения долгих размышлений.

То что я предлагаю в качестве языка, я вынашивал не менее 10 лет. Я видел что MUMPS морально устарел, в нем нет современных концепций, которые необходимы для современного языка. Но никак не мог понять, как их реализовать, не разрушив концепций MUMPS. Это понимал не только я, но и основной поставщик MUMPS систем InterSystems это тоже осознал и даже сделал реализацию. Лучше бы они не осознавали это и не делали реализации. Их реализация не соответствует основным концепциям MUMPS. Язык получился состоящим из 2-х несовместимых кусков. Я чувствовал , что есть простое и красивое решение. И когда меня осенило, как это сделать, я взялся за дело. Что из этого получится, посмотрим.

     2016/10/30 08:04, misha_shar53          # 

А почему мы забываем про наши собственные ЯП? Советую взглянуть на язык Эль-76 >

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

     2016/10/30 23:04, Автор сайта          # 

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

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

На самом деле атрибут в «Эльбрусах» — это бит, который указывает, что хранится в ячейке: код или данные. Это предотвращает исполнение кода, где хранятся данные, и нельзя использовать код как данные.

     2016/10/31 11:22, rst256          # 

Так ведь в МВК Эльбрус возможна адресация и соответственно формирование указателя с точностью до бита (стр. 74).
Посмотрите нам же на стр. 119 у них базовый тип только один лог, я сам конечно с трудом в это верю, однако вот со стр. 120 пример описания целочисленных типов со знаком:

% целое фомата ф31
тип цел = структ (конст зн#лог, мант : наб(31))
% целое фомата ф64
тип дцел = структ (конст зн#лог, мант : наб(63))

     2016/11/02 15:35, misha_shar53          # 

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

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

     2017/10/02 15:49, alextretyak          # 

4 294 967 295 + 1 не равно 0, но 0.1 * 6 равно 0.6. В отличие от C/C++ и многих других языков. Программы не должны молчать об ошибках, потому что их тогда не исправят.

Согласен. Но реалии таковы, что в самых популярных языках (Java, С++, C# [без добавления флага /checked]) арифметическое переполнение не бросает исключения, и делать такое в новом компилируемом языке мало кто решится. Единственное, что могло бы исправить эту ситуацию, как я считаю, так это только аппаратная поддержка на уровне процессора исключения при арифметических переполнениях, причём без потери производительности. А иначе в языках программирования общего пользования это так и не появится (появиться может только в виде дополнительного флага компиляции для добавления программных проверок на переполнение [как флаг /checked в C#]).
Но в случае, когда выражение может быть вычислено на этапе компиляции, выдавать ошибку при переполнении компилятор обязан в любом случае, я так считаю (MSVC++ выдаёт warning).

     2017/10/04 22:17, Автор сайта          # 

В IBM/360/370 и ЕС ЭВМ переполнения вызывали аппаратное прерывание. В x86 это можно отследить через прерывания. В языке Rust есть механизмы контроля переполнения.

     2017/10/08 12:00, alextretyak          # 

В языке Rust есть механизмы контроля переполнения.

Так, посмотрим, что там в Rust...

http://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/ <- google:‘rust integer overflow’:
The status of detecting and avoiding overflow in Rust +'‘*‘’’''changed several times+''‘‘’’' in the lead up to the 1.0.0 release last year. That fluid situation means there's still quite a bit of confusion about exactly how overflow is handled and mitigated, and what the consequences are.
...
The current status in Rust was decided in RFC 560:
. in debug mode, arithmetic (+, -, etc.) on signed and unsigned primitive integers is checked for overflow, panicking if it occurs, and,
. in release mode, overflow is not checked and is specified to wrap as two's complement.

Хм, интересная тема. Посмотрим, что люди пишут.

https://news.ycombinator.com/item?id=11595398:
I very much believe overflow checking should be on for release builds, and not just debug.

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

I think the only sensible thing to do is to have distinct operators for integer arithmetic ...
Swift has this and this is a sensible way to go but not the only one.

Так, а что там в Swift?

https://briancoyner.github.io/2015/11/19/swift-integer-overflow.html:
Swift's integer types provide an addWithOverflow(lhs,rhs) method.

Нет, это похоже что-то не то... А, вот оно:

https://developer.apple.com/library/content/documentation/ Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html# //apple_ref/doc/uid/TP40014097-CH27-ID37 <- google:swift operators for integer overflow’:
. Overflow addition (&+)
. Overflow subtraction (&-)
. Overflow multiplication (&*)

О, вот это жесть! Сразу вспомнил про какую-то аналогичную хрень в Nim c unsigned операциями. Не вспомню точно что там, но Гугл мне поможет... Вот оно:

https://nim-lang.org/docs/manual.html:
a +% b unsigned integer addition
a -% b unsigned integer subtraction
a *% b unsigned integer multiplication
a /% b unsigned integer division
a %% b unsigned integer modulo operation
a <% b treat a and b as unsigned and compare
a <=% b treat a and b as unsigned and compare

Автор языка думает, что люди машины что-ли? И думают об арифметических операциях категориями signed/unsigned? Моё мнение такое, что unsigned надо вообще убрать из языка, не вводить в язык программирования, а сделать int_in_range. Например, `int_in_range[1..] i` будет говорить о том, что для переменной i допустимы значения от 1 и более. А int_in_range[0..255] будет занимать 1 байт.

Признаюсь, я и сам любил использовать в С++ такой "хак": одну проверку `(unsigned)i < (unsigned)len` вместо `i >= 0 && i < len`, но это должно решаться просто другой записью: `i in 0..<len`, для которой компилятор должен генерировать также только одно условие. Для `i in a..b` также очевидно достаточно только одной проверки.

Взглянуть бы на статистику/частоту использования. Это хоть кто-то вообще использует? Держу пари, на долю `&+` придётся менее 0.1% от количества обычного `+`.

Единственная польза (ибо, если сразу сделать только длинную запись, то не будут пользоваться не потому что фигня, а потому что длинно писать) от таких извращений — это возможность собрать статистику и убедиться/удостовериться в том, что это фигня. А фигня... если и оставлять её поддержку, то она должна хотя бы выглядеть... понятно и длинно {ибо редко используется, и будут быстро забывать что это за &+, вот как в статье выше: `UInt8.addWithOverflow(a, b)`. Правда название функции я бы другое выбрал.

In practice, for anything which isn't a micro-benchmark, it's a negligible performance hit. ...
It starts with 2x like kibwen says. ...
That can easily lead to excessive branch target buffer invalidation and mess up branch prediction.

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

On the other hand, as long as we have no hardware support this is not going to fly.

No "modern" targets. MIPS and Alpha could trap on overflow (on MIPS `add` would trap, `addu` would not, not sure about Alpha) but neither x86_64 nor ARM have hardware support for trapping on overflow. x86 had INTO, which would INT 4 if the overflow flag was set, it still required additional instructions and the OS needed to convert that to an application trap, but there you are. It was removed in x86_64, likely because it wasn't used much.

What we really need is a hardware extension for ARM/Intel that traps on under/overflow:
http://blog.regehr.org/archives/1154:
Processors should support integer math instructions that optionally trap on overflow. Because popular architectures lack this feature, otherwise excellent modern systems programming languages, such as Rust, Go, and D, have default integer types that wrap.

The overflow flag requires a operation and branch to check. A trap is "free" until it actually happens.

Это, собственно, то, что я и хотел сказать, вот.

P.S. Этот комментарий «причёсывать» не обязательно, в скором времени я опубликую спецификацию/описание разметки, на которой он написан. Когда будет соответствующая реализация (скорее всего на Python), попрошу автора данного сайта перевести этот и последующие мои комментарии в html посредством этой реализации.

     2017/10/09 21:17, Автор сайта          # 

В чём выгода аппаратного прерывания при переполнениях? Не нужен дополнительный код для проверки флага переполнения. Проверки и код раздувают, и процессорное время тратят.
P.S. А вы бы могли предложить какую-то альтернативу «try...catch» для реагирования на переполнения?

     2017/10/12 15:09, alextretyak          # 

В чём выгода аппаратного прерывания при переполнениях?

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

P.S. А вы бы могли предложить какую-то альтернативу «try...catch» для реагирования на переполнения?

Я вижу такое решение. Переполнения при арифметических операциях должны порождать исключения "второго рода" ("фатальные"/"дорогие" исключения), перехватывать которые посредством catch необязательно. Если исключение не было перехвачено посредством catch, тогда целесообразно сохранить полный дамп памяти процесса (в Windows — через вызов MiniDumpWriteDump, ..., MiniDumpWithFullMemory, ...). Нам, программистам в Katauri, при работе над ММОРПГ Royal Quest эти дампы очень помогали в исправлении ошибок в коде сервера. И выдать пользователю сообщение об ошибке с предложением прервать выполнение программы либо продолжить выполнение (на свой страх и риск).

Свою позицию по исключениям (про два рода исключений) я изложил здесь.

     2017/10/24 23:53, rst256          # 

P.S. А вы бы могли предложить какую-то альтернативу «try...catch» для реагирования на переполнения?

Падение в кору и только падение в кору — единственная верная реакция на возникновение ошибки при выполнении, «try...catch» и прочие исключения приводят к запутыванию кода, замалчиванию этих ошибок и оказывают пагубное влияние на морально-нравственный облик программиста.

Ну а если серьезно то, можно ещё при переполнении результат в NaN превращать. Тут тогда не прерывание будет нужно, а поддержка NaN для целочисленных типов. Это ещё веселее, чем исключения будет, ведь недаром говорят: "Кто отладку бага с NaN прошел, тот проверку на NaN будет даже для констант делать".

     2017/10/25 13:07, Автор сайта          # 

Предлагаю два вида исключений.

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

Падение в кору и только падение в кору

Слава богу, что не падение в бездну или гиену огненную…

поддержка NaN для целочисленных типов

А где ж её взять, эту поддержку? Аппаратную поддержку? Я вижу другую аппаратную поддержку, которая не требует дополнительной памяти и не выходит за рамки существующих архитектур процессоров (по крайней мере — распространённых). Это флаги. Функция/операция при серьёзных ошибках устанавливает один флаг, при «интересном положении» — другой флаг. После возвращения из функции эти флаги проверяются (условный переход на обработку ситуации).

     2018/07/03 03:27, rst256          # 

Слава богу, что не падение в бездну или гиену огненную

В гиену огненную тех, кто необычные ситуации исключениями обрабатывает!

Например есть такая программа "yobit_free_bot". Она при старте производит загрузка данных с веб сервера, и исключением обрабатываются ошибки в процессе загрузки. Обработчик этого исключения выводит сообщение вида "Нет связи с сайтом... проверьте Интернет". Вот только Интернет был, и данные с той страницы другие программы загружали успешно...
Чёрт возьми, я 3 часа убил на отключение, а после и полное удаление всех фаерволов/антивирусов, пересоздание winsock, переустановку ОС, и множество других танцевальных па с бубном вокруг больного... А дело было в том, что программа была написана под более новую версию .NET чем та, что стояла у клиента, по этой причине и возникало это исключение.

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

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

     2020/09/20 21:24, Неслучайный читатель          # 

Сэкономленная электроэнергия спасает леса, животных, коралловые рифы и всю нашу планету.

На Хабре статья эту тему: «Астрономам порекомендовали меньше использовать суперкомпьютеры и Python из-за вреда экологии» . И поделом. Программы на Питоне львиную долю времени разогревают планету, и лишь толику делают полезную работу. Это если сравнивать с другими языками программирования. Критика не удивительна. Короче, Грета Тунберг ненавидит Питон, а интерпретаторы разогревают планету.

     2021/08/07 15:31, Автор сайта          # 

Читаю на cnews.ru: «ядро Linux слишком «дырявое», его нужно переписать с нуля». В статье пишут про разработчика ядра этой ОС, который предлагает отказаться от языка C по причине его небезопасности и переписать ядро на Rust. Разработчик ядра, которого зовут Кис Кук, считает причиной дырявости ядра Linux язык C, на котором оно написано. Он считает, что Linux следовало бы писать на «более безопасных» языках. В качестве примера Кук привел язык Rust.

На Stack Overflow провели опрос и выяснили, что самый любимый язык программирования — это Rust (почти 87% респондентов), Самым же ненавистным языком признали С (66%). Последнее связано, по-видимому, с большой его распространённостью. Будь столь же распространён Бейсик, к примеру, лидером антипатий был бы он.

Симпатии же к Rust связаны, в первую очередь, с его вниманием к надёжности программ. Хотя и в Rust в этом плане тоже не всё идеально.

     2021/08/08 16:51, Gudleifr          # 

А как можно ядро ОС, работающее в real-time в 0-м нулевом кольце защиты, сделать безопасным?

     2021/08/08 18:57, Автор сайта          # 

Существуют микроядра, чья корректность теоретически доказана. Вывод: безопасность достигается научно доказанной корректностью кода.

     2021/08/08 19:18, Gudleifr          # 

безопасность достигается научно доказанной корректностью кода

У меня для Вас плохая новость. Научно доказана неразрешимость задачи доказательства корректности кода.

     2021/08/08 23:46, Автор сайта          # 

Разработчики микроядра seL4 не обнимали необъятного. Они всего лишь доказали корректность и соответствие кода поставленному ТЗ. Доказали не только себе, но и другим учёным мужам. Защитили диссертации, учёные советы тоже согласились с доказательствами. Шарлатаны, поди.

     2021/08/09 00:01, Gudleifr          # 

Они всего лишь доказали корректность и соответствие кода поставленному ТЗ.

А при чем тут наука? Это была чисто технологическая проверка.

     2021/08/09 00:12, Автор сайта          # 

Да нет, «технологическая проверка» — это размытое понятие. Отладку тоже можно считать технологической проверкой. А тут именно научное доказательство. Как например:
0 & 0 = 0;
0 & 1 = 0:
1 & 0 = 0;
1 & 1 = 1.
Вот так же логически доказана правильность исходного кода.

     2021/08/09 00:47, Gudleifr          # 

> Вот так же логически доказана правильность исходного кода.
Вы заблуждаетесь.

     2021/08/09 11:16, Александр Коновалов aka Маздайщик          # 

Возникло недопонимание в теме корректности программ, попытаюсь внести ясность.

Доказательство корректности программ — это, как правило, доказательство того, что программа не делает того, чего не должна. Например, не зависает, не делит на ноль или правильно обращается к памяти.

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

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

Можно поступать двумя путями:
  • Можно брать реальные программы и искать в них подозрительный код. Это и warning’и компилятора, и специализированные инструменты вроде PVS-Studio.
  • Можно наоборот исключить конструкции, которые могут привести к некоторым видам ошибок. Например, ручное управление памятью в языках со сборкой мусора, статическая проверка ошибок, отсекающая заведомо некорректные операции и т.д.

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

А как можно ядро ОС, работающее в real-time в 0-м нулевом кольце защиты, сделать безопасным?

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

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

В «небезопасной» части (помеченной ключевым словом unsafe) можно делать то же, что и на Си. В ней компилятор проверяет не все инварианты, ответственность за корректность лежит на программисте.

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

     2021/08/09 12:21, Gudleifr          # 

попытаюсь внести ясность

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

Помните Хоар сказал: "Есть два способа построения программ: сделать их настолько простыми, что там очевидно не будет ошибок, или же настолько сложными, что там не будет очевидных ошибок"?

Вы, очевидно, пытаетесь идти вторым путем.

     2021/08/09 13:14, Автор сайта          # 

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

     2021/08/09 13:19, Gudleifr          # 

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

К сожалению, это доказуемо не работает.

     2021/08/09 14:31, Автор сайта          # 

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

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

     2021/08/09 14:37, Gudleifr          # 

Но ещё изобретаются новые языки со старыми проблемами — вот таких людей мне понять труднее.

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

     2021/08/09 15:09, Александр Коновалов aka Маздайщик          # 

Вы, очевидно, пытаетесь идти вторым путем.

А мне не очевидно! Докажите это «с какой-то долей уверенности».

     2021/08/09 15:24, Gudleifr          # 

Докажите это «с какой-то долей уверенности».

Вот Ваша фраза:

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

Т.е. Вы считаете хорошей практикой добавление "автоматической проверки" в код либо самого компилятора, либо программы (т.е. код станет больше либо потому, что в него введены лишние проверки, либо потому, что приходится избегать небезопасных конструкций) на наличие "очевидных ошибок". (Неочевидные, очевидно заранее предусмотреть невозможно). Ч.Т.Д.

Полагаю, что и в ядре ОС бОльшая часть кода будет в безопасной зоне.

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

     2021/08/14 18:16, Александр Коновалов aka Маздайщик          # 

Т.е. Вы считаете хорошей практикой добавление „автоматической проверки“ в код либо самого компилятора, либо программы (т.е. код станет больше либо потому, что в него введены лишние проверки, либо потому, что приходится избегать небезопасных конструкций) на наличие „очевидных ошибок“. (Неочевидные, очевидно заранее предусмотреть невозможно). Ч.Т.Д.»

Если от «лишних проверок» станет больше код библиотеки, то на пользовательский код это никак не повлияет. Один раз в библиотечный класс будет добавлена проверка (например, проверка обращения к индексу в классе динамического массива), пользователь получит бо́льшую безопасность ценой незначительного увеличения кода и незначительной потери быстродействия. И что?

(На сайте есть статья Дмитрия Караваева о потерях производительности, вызванных контролем целочисленного переполнения. Они незначительны.)

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

Мой любимый пример — поиск в двумерном массиве без использования goto. Задача: найти пару индексов элемента в двумерном массиве с заданным значением. Большинство программистов не умеют эту задачу решать структурно (т.е. без goto или return). Но лаконичное структурное решение есть.
found = false;
for (i = 0; i < M; ++i) {
for (j = 0; j < N; ++j) {
if (a[i][j] == search_for) {
found = true;
break;
}
}
}

if (found)
print ("Элемент найден, %i, %i\n", i, j);
else
print ("Элемент не найден\n");
Структурное решение:
i = 0;
j = 0;
while (i < M && a[i][j] != search_for) {
++j;
if (j == N) {
j = 0;
++i;
}
}

if (i < M)
print ("Элемент найден, %i, %i\n", i, j);
else
print ("Элемент не найден\n");

на наличие „очевидных ошибок“. (Неочевидные, очевидно заранее предусмотреть невозможно). Ч.Т.Д.»

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

Если Вы сами не делали очевидные ошибки, то Вы или себя обманываете, или пишете на таком языке, где очевидные ошибки не очевидны.

Поэтому лучше, когда от очевидных ошибок оберегает машина. Или проверками времени выполнения (assert не зря придумали), или прямым запретом конструкций, относительно часто приводящих к ошибкам. Как показывает практика, запрет подобных конструкций не сильно мешает программировать.

Пример. В языках типа C# или Java невозможно (без плясок с бубном) испортить память, т.к. отсутствует адресная арифметика и неинициализированные указатели (неинициализированные переменные неявно инициализируются в null). В ассемблере, Форте и Си — запросто.

Так что Ваше «доказательство» на поверку оказывается фразой «очевидно, что».

     2021/08/14 18:33, Gudleifr          # 

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

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

А почему избежание небезопасных конструкций будет увеличивать объём кода?

"Ёлочки" (избыточные деревья проверок), "Матрешки" (избыточная вложенность), "синдром чайника"...

Встречал утверждение, что на 1000 строк кода приходится примерно одна некритическая ошибка

Около 30. И это после всех проверок умными языками. И не все они некритические.

В ассемблере, Форте и Си — запросто.

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

     2021/08/14 19:47, Gudleifr          # 

Пардон, не заметил.

Так что Ваше «доказательство» на поверку оказывается фразой «очевидно, что».

Даже, если бы это было так, то Ваш последний тост доказывает искомое исчерпывающе.

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

     2021/08/15 10:08, Александр Коновалов aka Маздайщик          # 

В ассемблере, Форте и Си — запросто.

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

Т.е. Вы согласны с тем, что программы на перечисленных языках неизбежно содержат ошибки доступа к памяти. А программы на Java заведомо не содержат. Целого класса ошибок в них нет.

«Ёлочки» (избыточные деревья проверок), «Матрешки» (избыточная вложенность), «синдром чайника»…

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

Даже, если бы это было так, то Ваш последний тост доказывает искомое исчерпывающе.

Я тупой. И как же доказывает?

     2021/08/15 10:45, Александр Коновалов aka Маздайщик          # 

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

Альтернатива? Велосипедить библиотеки самим? Тогда ошибок будет ещё больше.

     2021/08/15 11:04, Gudleifr          # 

Т.е. Вы согласны с тем...

Разумеется, я с Вами согласен. В том, что ошибки были, есть и будут... Мы (со стариком Хоаром) просто пытаемся Вам намекнуть, что, усложняя средства борьбы с ошибками, Вы просто увеличиваете число ошибок и уменьшаете свою возможность что-то запрограммировать. Как нарисовал старик Броуди, строите клетку вокруг себя, а не вокруг тигра.

И как же доказывает?

Хоар:

... настолько сложными, что там не будет очевидных ошибок

Вы:

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

     2021/08/15 22:07, Александр Коновалов aka Маздайщик          # 

Вернёмся к цитате Хоара:

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

Во-первых, это, очевидно, шутка. Двух способов нет, есть общий принцип: чем проще программа, тем меньше в ней ошибок.

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

Какие из этого следствия для языкостроения:
  • Язык должен избавлять программиста от деталей реализации, не относящихся по существу к задаче. Например, от управления памятью. В Си нужно для каждого malloc()’а явно вызывать free(), это, очевидно, зашумляет код. В C++ и Rust освобождение памяти можно спрятать в деструктор, который вызовется автоматически. В Java сборка мусора.
  • Язык должен иметь удобные средства для декомпозиции. Сама постановка задачи может требовать написания объёмной программы. Если огромная программа пишется монолитом, то она будет «настолько сложной, что в ней не будет очевидных ошибок». Поэтому нужны средства разбиения большой задачи на небольшие независимые компоненты: модульность, инкапсуляция и прочее.

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

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

     2021/08/15 22:08, Александр Коновалов aka Маздайщик          # 

Возможно, это будет интересно Автору сайта.

Кроме того, система типов Haskell’а позволяет выводить нетривиальные свойства функций только из их сигнатур. Например, если тип функции описан как
f :: [a] -> [a]
то эта функция принимает список, возвращает новый список того же типа, элементами которого могут быть только элементы исходного списка (и ничего более). На выходе будет перестановка элементов аргумента, возможно, с повторениями и вычёркиваниями. Есть такая замечательная статья: Phillip Wadler «Theorems for free!» («Теоремы задарма!») про свойства функций на основе одних лишь типов.

     2021/08/15 22:29, Александр Коновалов aka Маздайщик          # 

Есть интересный материал про то, как делать ошибки очевидными.

     2021/08/15 23:40, Gudleifr          # 

Во-первых, это, очевидно, шутка.

К сожалению, она вполне точно описывает то, что происходит последние 40 лет.

Во-вторых, в ней речь идёт о построении программ, а не проектировании языков программирования.

За исключением некоторого ограниченного числа случаев, это одно и то же.

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

Но это не значит, что на её 1000 строк стало меньше 30 ошибок.

Да, можно придумать +100500 способов искать специально придуманные для такого случая ошибки, но в реальной жизни получаем что-то вроде (поискал по форумам хоть что-то подходящее): постановка задачки (на прямую цепочку рассуждений) — 10 строк, решение на DOS GWBASIC — 60 строк, присланное мне решение на Haskell — 170 строк (причем, перебор правил жестко прописан в коде). Что ещё надо добавить в Hascell, чтобы хотя бы догнать BASIC 40-летней давности?

Или, приведенный Вами выше пример. Там нет никакой адресной арифметики. И что, там нет ошибок?

     2021/08/16 11:40, Александр Коновалов aka Маздайщик          # 

А что за задачка-то?

     2021/08/16 11:56, Gudleifr          # 

Задачка: https://gudleifr.forum2x2.ru/t63-topic#681

Haskell-решение: https://gamedev.ru/flame/forum/?id=226833&page=39&m=4528495#m571
(Там, дальше, есть более "компактное" решение, но "компактность" свелась к замене данных кодом, т.е. решение перестало быть универсальным).

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

     2021/08/17 09:25, Клихальт          # 

Извините, что вмешиваюсь в вашу увлекательную беседу про ошибки, но вот в этот пример кода
found = false;
for (i = 0; i < M; ++i) {
for (j = 0; j < N; ++j) {
if (a[i][j] == search_for) {
found = true;
break;
}
}
}

if (found)
print ("Элемент найден, %i, %i\n", i, j);
else
print ("Элемент не найден\n");
вкралась крохотная ошибка, благодаря которой на экран при найденном совпадении (вне зависимости от количества и места расположения в массиве этих совпадений) всегда будет выводиться "Элемент найден, <M>> <N>". И да, выводиться будет, если Вы замените print на ptintf, но это если вы пишите на Си. Если мне конечно не изменяет память, т. к. на Си я не писал уже лет тридцать.

P.S. Язык может быть насколько сколь угодно простым, сложным, беззащитным, защищенным (требуемое подставьте сами), но в голову он к вам не залезет что и о чём вы думали, когда писали не узнает, потому ошибки как были, так и останутся.

     2021/08/17 11:38, Автор сайта          # 

2 Клихальт
Ответ на комментарий из другой ветки, тут тема более подходящая.

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

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

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

Если имеется в виду усложнение языка, когда он становится сложен, противоречив, неоднозначен и провоцирует совершение ошибок, то это не наш путь. В первом пункте «философии языка» (изложено выше) записано: «Лаконичность, простота и ясность языка».

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

Нет смысла противопоставлять развитие программистов и развитие языков. Развитие языков полезно тем, что у программиста становится шире выбор. Многие программисты высказываются в том духе, что «Хаскелл прочищает мозги», то есть заставляет взглянуть на задачу под другим углом. А не будь Хаскелла (в результате развития языков!), кто б тогда развивал мозги в эту сторону?

но вот в этот пример кода … вкралась крохотная ошибка

Да, было бы неплохо написать «break 2;», как в PHP, но в Си такого нет. С «printf» Вы тоже правы.

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

Э.Дейкстра:

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

«Какие ваши доказательства?» Это подтверждается статистикой? Или энцефалограммой мозга? А нет никаких доказательств, есть только известные полемические приёмы: гротеск, эпатаж, эмоциональные манипуляции.

2 Александр Коновалов aka Маздайщик

f :: [a] -> [a]
то эта функция принимает список

Удивляет, что в Хаскелл список — единственный нескалярный (агрегатный) тип данных. Подозреваю, что это традиция, идущая от Лиспа. Но вот факты для размышления:
  • Список — это структура с последовательным доступом к данным. Чтобы обратиться к какому-либо элементу списка, нужно либо шаг за шагом (императивно) пройти от начала списка, либо хранить адрес (состояние) предыдущего элемента.
  • Функциональные языки программирования отдают предпочтение программированию без состояний. Одна из целей функционального программирования — распараллеливание процессов (особенно актуально в эпоху многоядерных процессоров), но последовательный доступ исключает параллелелизм.

     2021/08/17 11:53, Gudleifr          # 

цитата явно не оттуда

Из Тьюринговской лекции.

Это подтверждается статистикой?

Да. Общаясь с молодежью я постоянно слышу: математика в программировании нужна только там, где надо посчитать что-то сложное.

     2021/08/17 13:06, Клихальт          # 

2 Автор сайта,


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

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

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

Правда, как мне кажется, это тема несколько другого разговора, не совсем относящаяся к самому языку как таковому.

     2021/08/18 14:00, Автор сайта          # 

2 Gudleifr

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

Ну да, интеграл нам пригодится, чтобы согнуть кусок проволоки по его форме и достать гаечный ключ, упавший в картер танкового движка. С равным успехом они могут убеждать в том, что обходятся без прозы. Достаточно написать цикл, и вот она, арифметика, первый раздел математики:
for (i=0; i<N; i++) { . . . }	// i++ — это уже арифметика,
// да не простая, а с переполнениями
Аргументы и результаты подпрограмм — это область действия и область значений в математических функциях. Если гарантировать чистоту функции в программе (например, ключевым словом «pure» в языке D), то она становится функцией в математическом смысле. В отсутствие недетерминизма и побочных эффектов такую функцию можно вырвать из контекста и прогнать все варианты входных значений и сверить полученные результаты с эталоном. Вот так можно гарантированно доказать её правильность. Вот оно, преимущество математического подхода. От математики ещё никому не было плохо. Кроме экзаменов, конечно.

2 Клихальт

Если компилятор считать неким продолжением языка

Ключевое слово — «если».

     2021/08/19 23:38, Александр Коновалов aka Маздайщик          # 

Удивляет, что в Хаскелл список — единственный нескалярный (агрегатный) тип данных.

Не единственный, т.к. есть ещё и кортежи, но суть не в этом. В стандартной библиотеке есть типы данных для массивов, правда, с мутабельными массивами можно работать только в монадах.

Если говорить о распараллеливании, то вызов
map f xs
где f — функция, а xs — список, прекрасно распараллеливается. Все вычисления чистые и могут выполняться независимо.

Кроме того, все операции работы со списком: взятие головы, взятие хвоста, проверка на пустоту, построение нового списка из головы и хвоста, чистые. Поэтому функции, работающие со списками, прекрасно параллелятся.

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

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

     2021/08/20 00:35, Gudleifr          # 

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

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

Кстати, давно собирался спросить, как на функциональном языке решать задачки "методом волны" на двумерном (и более) массиве?

     2021/08/20 16:46, Александр Коновалов aka Маздайщик          # 

Немного портит дело тот факт, что процессор не умеет ни во что, окромя массивов. 〈…〉 Да еще, при этом тащиться от того, что эти списки надо постоянно копировать...

Если список не изменяется, то и копировать его не надо, достаточно просто передавать ссылку. Если в начало списка добавляется элемент, тоже никакого копирования — создаётся новое звено, которое ссылается на старый хвост, O(1). Если список нужно полностью перебрать, то это уже O(n), так, что если в процессе перебора создаётся новый список, то не страшно. Это я про всякие map’ы и фильтрации, если что.

Более того, Хаскель — ленивый язык. Список может порождаться лениво по мере его потребления, а значит, потребление памяти в ряде задач будет константным. Например, здесь память будет O(1), хотя, на первый взгляд, в процессе создаются два списка:
foldl' 0 (+) (map (\x -> x*x) [1..1000000])

Кстати, давно собирался спросить, как на функциональном языке решать задачки "методом волны" на двумерном (и более) массиве?

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

     2021/08/20 17:07, Gudleifr          # 

Если список не изменяется, то и копировать его не надо...

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

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

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

     2021/08/24 10:21, Александр Коновалов aka Маздайщик          # 

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

Не проще.

Операции с массивами дармовые до тех пор, пока не требуется много памяти. Можно выделить массив «с запасом» и пользоваться им. Когда объём памяти заранее не известен, то удобнее использовать ссылочные структуры вроде списков или деревьев, создавая звенья в куче по мере надобности. (Про фрагментацию кучи и сборку мусора можешь не писать, мне про это известно).

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

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

Есть задачи, на которых несравненен шелл — работа с файлами и управление запуском программ. Есть задачи, которые удобно писать на Хаскеле, например, символьные вычисления. Пример: компиляция выражения в обратный польский код:
data Expr = Var String          -- переменная
| Num Float -- число
| Bin Expr Char Expr -- двуместная операция
| Un Char Expr -- одноместная операция

compile (Var s) = s
compile (Num f) = show f
compile (Bin x op y) = (compile x) ++ " " ++ (compile y) ++ " " ++ [op]
compile (Un op x) = (compile x) ++ [op]
Здесь описан тип данных для синтаксического дерева и функция, компилирующая это дерево в строку.

Тип данных описывается как алгебраический — почти как БНФ. Разбор случаев выполняется сопоставлением с образцом. И ни одной сторонней библиотеки.

На почти любом другом языке описание синтаксического дерева выражения + функции компиляции в постфиксный код будет длиннее. Другой пример. Хотим оптимизировать это же выражение — вычислить в нём узлы с константными аргументами:
optimize Var s = Var s
optimize Num f = Num f
optimize Bin x op y = calcBin (optimize x) op (optimize y)
optimize Un op x = calcUn op (optimize x)

calcBin (Num x) '+' (Num y) = Num (x + y)
calcBin (Num x) '-' (Num y) = Num (x - y)
calcBin (Num x) '*' (Num y) = Num (x * y)
calcBin (Num x) '/' (Num y) = Num (x / y)
calcBin x op y = Bin x op y

calcUn '-' (Num x) = Num (- x)
calcUn op x = Un op x

     2021/08/24 11:31, Gudleifr          # 

Операции с массивами дармовые до тех пор, пока не требуется много памяти.

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

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

Ага. См., например, канонический пример "FORTH и инфиксная запись"... На сколько порядков FORTH проще и быстрее Haskell?

Проблема тут в другом. Когда программистом было нужно реально написать лексический/грамматический анализатор для работы в промышленных масштабах, они на обычном C написали Lex и Yacc... И этого хватило на десятилетия. Язык — это средство упрощения работы с компьютером, а не нечто, что нужно изучать дольше, чем запрограммировать решение задачи на языке ассемблера.

     2021/08/24 23:17, Автор сайта          # 

Не единственный

Да, не единственный. Но единственный, который упомянут в самых рекомендуемых учебниках. Все примеры в них — только со списками.

Если говорить о распараллеливании, то вызов
map f xs
где f — функция, а xs — список, прекрасно распараллеливается. Все вычисления чистые и могут выполняться независимо.

Спору нет, вычисления могут выполняться на разных процессорах. Вот только контроллер памяти — общий. Обращение к памяти — в порядке очереди. Тогда каков порядок работы многоядерной системы?
1) Ядро №1 читает первый элемент списка и производит вычисления.
2.1) Ядро № 2 читает первый элемент списка, затем второй, и только потом производит вычисления, либо
2.2) ядро № 2 ждёт, когда ядро № 1 прочитает первый элемент списка, затем читает второй элемент и только потом производит вычисления.
3.1) Ядро № 3 читает первый элемент списка, затем второй, затем третий и только потом производит вычисления, либо
3.2) ядро № 3 ждёт, когда ядро № 2 прочитает второй элемент массива, затем читает третий элемент и только потом производит вычисления.
И так далее. Получается, что элемент с номером N попадёт в ядро с номером N только после последовательного чтения или перебора N элементов. У ядра N нет способов обратиться к элементу списка N одновременно с доступом первого ядра к первому элементу. Даже если ядра физически свободны для вычислений, то это не значит, что в них попали необходимые для вычислений данные. В чём ошибочны такие рассуждения и выводы?

с мутабельными массивами можно работать только в монадах.

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

В этом плане у языка Clean, мне видится, некоторое преимущество. Достаточно обеспечить уникальность доступа, чтобы были возможны деструктивные обновления. Потому что копирование, особенно больших объёмов, — это большие накладные расходы. Было бы интересно давать уникальный доступ не целиком к структуре, а к её отдельным элементам.

Да еще, при этом тащиться от того, что эти списки надо постоянно копировать...

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

Список может порождаться лениво по мере его потребления

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

Естественно, что найдутся обратные примеры, когда списки лучше подходят, чем массивы. Но учебник K&R не навязывает выбор способа организации данных. А после чтения учебников по Хаскелл я даже не знаю, каков синтаксис объявления и использования массивов.

У авторов учебников по Хаскелл любят приводить примеры с ленивым порождением. Заостряют внимание, что такая оптимизация недоступна в обычных языках. Но эта оптимизация делается поверх многочисленных пессимизаций. К примеру, каррирование — это замена функции с количеством аргументов N на N функций с единственным аргументом. А каждый новый вызов — это накладные расходы, пессимизация. Или использование функций как объекта первого класса. Адрес функции, вычисляемый и возвращаемый в другой функции, в общем случае заранее неизвестен. Что уменьшает возможность предсказания переходов процессором, что уменьшает скорость программы.

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

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

Конечно, проще, но с точки зрения императивного программиста. Такой код привычнее и проще пишется. Но согласен с Александром Коноваловым, что списки гибче в плане использования памяти, но не всегда.

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

А вот тут возможны варианты. Когда неизвестен объём памяти? Если объём известен во время компиляции, то тут всё ясно. Если известен в рантайме во время его создания, а далее не меняется, то такой массив можно всегда создать в стеке. Главное, чтобы соблюдалась дисциплина LIFO. Этот случай описан здесь на сайте в статьях про хранение данных в двух стеках. Ну а если размер массива меняется уже после создания, то тут тяжёлый случай. Тут, скорее всего, списки будут уместнее.

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

К сожалению, синтаксис не шибко читаемый. Где тут корень, где левый и правый лист дерева? И где тут увидеть ссылки/указатели на элементы дерева?

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

Не всегда краткость полезна. Вот пример плохо читаемой краткости (текст на языке J, который можно назвать «помехами в телеграфной линии»):
s =: ({. , }. /: 12"_ o. }. - {.) @ /:~
l =: 11"_ o. [: (* +)/ }. - {.
rr =: (1"_ , (0"_ > 3: l\ ]) , 1"_) # ]
hull =: [: rr^:_ s
Цитата оттуда же:

Даниель Мак-Кракен (Daniel McCracken) однажды отметил, что чтение и анализ программы из четырёх строк, написанных на языке APL, заняли у него четыре часа.

Gudleifr: они на обычном C написали Lex и Yacc... И этого хватило на десятилетия.

Вы знаете, об этом не очень давно писали: то ли в паре Lex/Yacc, то ли в бесплатном аналоге Flex/Bison нашли ошибку, которую десятилетиями в упор не видели. А будь они написаны на Хаскелл, то ошибка, скорее всего, была бы найдена во время компиляции. При всём уважении к Си...

     2021/08/24 23:43, Gudleifr          # 

Вы знаете, об этом не очень давно писали: то ли в паре Lex/Yacc, то ли в бесплатном аналоге Flex/Bison нашли ошибку, которую десятилетиями в упор не видели. А будь они написаны на Хаскелл, то ошибка, скорее всего, была бы найдена во время компиляции. При всём уважении к Си...

Вы так пишете, как будто это минус C, а не Haskell...

     2021/08/25 00:30, Gudleifr          # 

Конечно, проще, но с точки зрения императивного программиста.

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

Поэтому нижеследующее неверно совершенно:

списки гибче в плане использования памяти

     2021/09/01 23:24, Бурановский дедушка          # 

2 Автор сайта
О распараллеливании, «map f xs» и последовательном доступе к элементам списка из-за «бутылочного горлышка», созданного общей памятью.

«Параллельно» — это отнюдь не «одновременно». При исполнении кода
map f1 xs1
map f2 xs2
map f3 xs3
(продолжаю Ваши рассуждения) первый процессор, обработав первый элемент списка xs1, может не ждать, когда сделают свою работу остальные процессоры. Он может обрабатывать первый элемент списка xs2, затем xs3 и т. д. Этому помогают такие факты, что f1, f2, f3 — чистые, а в кэшах процессоров есть собственная копия участков памяти (что помогает обойти «бутылочное горлышко»), при этом списки xs1, xs2, xs3 используются только для чтения (что опять упрощает задачу распараллеливания).

То есть степень пессимизма можно уменьшить, хотя он всё равно обоснован.

неверно совершенно:

списки гибче в плане использования памяти

Списки дают возможность легко и просто вставить в любое место элемент и удалить в любом месте элемент. Он не нуждается в заранее известном размере; это размер меняется на ходу. Не убеждает? А попробуйте вставить в массив новый элемент перед первым или удалить первый элемент массива — и тогда появляется необходимость сдвига элементов: элементу n+1 присвоить значение элемента n и т. д.

     2021/09/01 23:42, Gudleifr          # 

первый процессор, обработав первый элемент списка xs1, может не ждать, когда сделают свою работу остальные

И сколько этих остальных? По сравнению с размером списка, вызывающим проблему?

Не убеждает?

Реализовать на массиве список — пожалуйста! А на списках — массив?

Добавить свой отзыв

Написать автору можно на электронную почту mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

Описание языка

●  Философия языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

Компьютерный юмор

Новости и прочее




Последние отзывы

2021/09/11 16:46 ••• Gudleifr
Изобретение очередного велосипеда?

2021/09/01 23:42 ••• Gudleifr
Философия языка

2021/08/31 22:04 ••• Gudleifr
Должна ли программа быть удобочитаемой?

2021/08/30 00:42 ••• Gudleifr
Все языки эквивалентны. Но некоторые из них эквивалентнее других

2021/08/19 20:52 ••• Gudleifr
В защиту PL/1

2021/08/19 20:34 ••• Gudleifr
Каким должен быть язык программирования?

2021/08/11 11:24 ••• Gudleifr
Почему обречён язык Форт

2021/08/07 13:43 ••• Anatoly
Компилятор

2021/08/07 13:30 ••• Anatoly
Многоязыковое программирование

2021/06/16 13:10 ••• Александр Коновалов aka Маздайщик
Не поминайте всуе PL/1

2021/05/19 23:15 ••• Денис Будяк
Энтузиасты-разработчики компиляторов и их проекты

2021/04/25 08:41 ••• kt
Некошерный «goto»

2021/04/19 17:01 ••• Клихальт
О наименовании проекта и языка программирования

2021/04/04 18:29 ••• kt
Переключатель

2021/04/02 19:32 ••• Александр Коновалов aka Маздайщик
Циклы