Если взять вместо мотаний взад-вперёд по строке последовательное движение с рекурсией, которая всё равно неизбежна в случае выражений типа ((a+b)*(c-d))*e (ваш алгоритм будет вынужден считать скобки, чтобы определить пару первой скобке...) — получится самый типовой нисходящий ручной парсер типа того, что в книге Страуструпа по C++. А если добавить разбор по приоритетам операций — получится парсер Пратта. И, заметьте, никаких мотаний.
Поэтому я бы сказал, что вопрос надо заменить на другой — «если так просто писать ручные парсеры, зачем нас мучают всеми этими LL и LALR?» И вот на него уже сложно ответить методологически корректно, потому что тут как раз тот случай, когда преждевременная математизация убивает понимание.
> Кто-то очень не умный в Обратной Польской Записи добавил слово «обратная», это и приговорило этот способ записи всегда быть «неправильным».
«Добавил» потому, что «прямая польская» запись это префиксная, как в LISP. И идут эти термины «прямая» и «обратная» от работ Яна Лукасевича в 1920-е годы. Слово «польская» добавили уже после него, но в его честь. И это были очень умные люди, которые основали нынешнюю Computer Science.
И ничего «неправильного» в этом нет, кроме того, что такую запись, в отличие от префиксной, сложнее парсить и модифицировать — надо рассчитывать просмотром назад, где части выражения.
> Естественную Польскую Запись
Своими нововведениями вы нарушаете устоявшуюся терминологию. Не думаю, что это будет принято обществом.
> Модификатор async никак не влияет на тип возвращаемого методом значения, то есть к типизации не имеет вообще никакого отношения.
Это если считать, что T и Task<T> это принципиально несовместимые сущности из разных вселенных. Но есть и другая трактовка — где это разные, но родственные типы, и где можно сложить T и Task<T> и получить новый Task<T>.
Собственно, построение через async или futures делает почти это (нет синтаксической прозрачности).
> Вы сами правильно заметили, что она редко когда нужна.
Категорически прошу внимательно читать и не подтасовывать. Я не сказал, что она редко _нужна_, я сказал, что она редко _используется_. А используется она редко, в частности, из-за того, что мало где адекватно реализована, и из-за критиканства неосиляторов. Я её использовал и в Python, и в C++ (без общего базового класса), и как-то программы не рухнули и работают без проблем.
Остальной ваш пафос пропускаю мимо за непрактичной банальностью.
При том, что его иначе использовать в этих условиях было невозможно (чрезмерно дорого). И размер нулевой страницы, и громоздкость временной заливки данных в неё и вылива обратно — провоцировали абьюзить её, используя под то, что в нормальных системах не сидит постоянно в регистрах.
> Но архитектура Spark с более чем сотней регистров не стала преобладающей.
Вы с IA-64 не путаете? SPARC имел с точки зрения пользовательского кода 32 регистра (включая пустой). Системному позволялось видеть полный ротор регистров, но к вопросу плотности обычного кода это уже не относится.
Использовать нулевую страницу 6502 в качестве «почти регистров» не годилось. Проблема в том, что, говоря современным термином, регистры бывают общего назначения и служебные (в x86 последние это то, что MSR), так вот нулевая страница несла оба набора, и все участвующие использовали какие-то её ячейки непредсказуемым образом (надо было вычислять по исходникам).
Для полностью самостоятельного приложения, которое берёт на себя всю работу с аппаратной частью и вокруг, это было неважно. А вот если хотел сделать что-то такое, что и было хитрое на ассемблере, и сочеталось даже просто с местным бейсиком (хотя бы не сломать его по выходу из своего кода!) — уже возможность использовать нулевую страницу резко сокращалась. А какая-нибудь Рапира использовала её реально всю — оставляя только несколько ячеек нетронутыми — причём какие именно, документация подвирала.
Да, с этим можно было банально не столкнуться. Но с тех пор утверждение «нулевая страница это те же регистры» вызывает у меня только саркастическую ухмылку — и применяется как объяснение, почему процессору нужны настоящие регистры, а не суррогаты.
> 8080A и КР580ВМ80А также использовали три напряжения — см. документацию.
Хм, я не нашёл с ходу упоминания специфики именно 8080A, все почему-то универсально говорят про оба. OK, сочтём это за сбой памяти.
> непредсказуемых эффектов PDP-11
Про это уже ответили — неродные процессоры могли как-то лажать, но DEC, насколько я знаю, чётко держал планку.
И эти эффекты не касаются самых важных вопросов — например, порядок выбора дополнительных слов в командах типа mov #1, 20(%2).
> Только это «сильно раньше» было без процессоров-чипов, о которых статья.
Не сходится: вы VAXʼу отдельную главу посвятили.
Не принципиально, но считаю необходимым заметить.
> Посмотрите на команду LDA ($55,X) — тaкое на z80 не представить.
И смысла в ней где-то на уровне ноль целых фиг десятых. Я ещё в те времена как-то заинтересовался осмысленностью этой адресации, пересмотрел (чёрт, грепа не было, листал и глазами смотрел) код стандартных программ типа Бейсика, Школьницы — случаи были просто единичные и тупо сомнительные, в отличие от $ABCD,X или ($AB),Y — последняя вообще использовалась на каждом шагу (ну ещё бы).
Был какой-то паттерн написания, при котором именно такая адресация была полезна? Если да, я его не знаю и не использовал.
В остальном, под что легче писать — вкусовщина, но меня постоянное гоняние байтиков через аккумулятор просто доставало, особенно видя рядом вкусные аналоги типа клонов PDP-11.
Если бы конкуренты не тратили попусту по 4 такта на ерунду, тот 6502 просто не взлетел бы.
8080 требовал три напряжения, а 8080A — только одно — +5V. Наши клоны были соответственно K580ИК80 (позднее ВМ80) и КР580ВМ80А; причём, 80 был в тонком корпусе с мягкими выводами (только пайка), а 80А — в обычной многоножке (соответственно, легко ставился на розетку). Реально у нас использовался только 8080А/ВМ80А — во всех компьютерах местной разработки. В вики есть фото Квазаровского ИК80 — у меня когда-то лежало несколько таких без дела.
Тут интеловский 8080A был конкурентом их же 8085, и Z80 — наверно, поэтому 8085 оказался никому не нужен.
> Есть основание полагать, что GNU ассемблер для x86 делали под влиянием именно ассемблера PDP-11.
Да, но не напрямую. Сначала был порт System V на i386, сделанный AT&T. Именно в нём было принято такое решение — и множество других, напрямую склонированных с Unix ассемблера PDP-11 и VAX-11 — таких, например, как команды ассемблера, начинающиеся с точки (.byte, .word, .align...) Эти наработки были куплены и перенесены в SCO Unix. И уже под влиянием SCO был сделан GNU as.
Некоторые особенности их решений сохраняются до сих пор. Например, в AT&T отличие fsubr от fsub в том, что суффикс r означает укладку результата не в st(0), а в другой регистр — хотя в оригинальном Intel синтаксисе это означало укладку в регистр вычитаемого, а не уменьшаемого. Или, они заменили идиотски путаные обозначения Intel для команд расширений знака (кто помнит навскидку отличие cwde от cwd?) на свои такие же путаные (cltd против cltq).
> Очень странные и непредсказуемые эффекты можно получить, используя счётчик команд как обычный регистр.
У PDP-11 они как раз очень предсказуемые — порядок отработки побочных эффектов аргументов чётко задан.
80188 использовался в некоторых моделях PC XT. Но самое знаменитое его применение — это в модемах USR Courier. В бСССР для него писали прошивки с заточкой под местную специфику, пользуясь лёгкостью понимания.
> с тех пор деление делать быстрее так и не научились!
Частично научились, но это действие вообще проблемное, и на его оптимизацию не тратят усилий.
Про условные переходы:
> С 80386 стало возможным использовать смещения из двух байт
В 32-битном режиме — все 4.
> С этого процессора начинается использование страничной виртуальной памяти – сегодня это доминирующая технология.
Мнэээ… IBM 370, VAX умели страничную адресацию сильно раньше.
Про 6502… он был удачный с точки зрения внутренней конструкции, да. Но писать что-то серьёзное под него было пыткой — говорю как краевед (Агаты в школе), из-за единственного аккумулятора и постоянных конфликтов за ячейки нулевой страницы. Если бы ему дали хотя бы 3 нормальных почти универсальных 16-битных регистра, он бы точно побил всех конкурентов. Боюсь, помешали этому те же причины, что потом убили его развитие.
не очень монструозный, чтобы не на полчаса времени
Полчаса на одного студента для такого теста это, мягко говоря, дофига. В этом и проблема — автоматизация позволяет и время сэкономить, и сделать задачу в достаточно разнообразном виде.
Имхо, Вы ищете сложные пути решения для простой проблемы)
Ни капельки. Как раз вызвать к доске и тщательно вникать в подробности… ну, при нашем стиле обучения можно один раз на студента в семестр такое позволить, но не больше.
задавались вопросы, если где-то логика перехода была преподу не ясна.
И наверняка половина наобум просто не проверялась — не успевал.
> Паскаль в той или иной ипостаси существует и поныне. А смысла в претензиях к версиям давно минувших дней — немного.
Ага, «существует». В следовых количествах.
> В этом нет никакой проблемы — это можно считать вариацией неопределенного списка параметров/необязательных параметров.
Когда нельзя самому такое сделать — это не вариация неопределённого списка, это другое, недоступное.
> Ваши некорректные ожидания — ваша проблема.
Ожидания совершенно корректные и конкретные — эргономические и POLA.
> Это снижет количество визуального мусора, делает код более компактным без потери читаемости.
Среди рассмотренных четырёх вариантов опциональные begin-end — самый мусорный вариант.
> Нет, это вы не поняли. Мой ответ относился ко второй вашей фразе, а не к висящему else.
Принципиально проблема не меняется. Посмотрите тут рядом рассказы от PVS-Studio — случаев «забыли обернуть в скобки», мягко говоря, дофига.
Питонист тут как раз скорее сам всегда будет ставить скобки, для страховки.
> И если по тем или иным обстоятельствам язык Х потерял рынок и ушел на обочину, это вовсе не означает, что все его свойства и особенности (включая синтаксис) плохи.
Про «все» я и не говорил. Но упомянул те, которые однозначно плохи.
> Взять даже обычные калькуляторы — оказывается, даже у них нет единого стандарта по приоритету операций.
Я знаю эту проблему, но это какое-то очень специфичное виндовое злонаследие. И именно оно показывает, что POLA лучше выполнять, где нет явных причин не делать это. Нормальный калькулятор с приоритетами сейчас укладывается в пару сотен строк кода. Если им нужно таки сохранять совместимость с древними багами, то лучше было бы переименовать «простой» режим в какой-нибудь dumb.
А неадекватные приоритеты в языках постоянно лечат, где нет необходимости сохранять старые баги. В C приоритет у &, | был занижен неадекватно — ниже сравнений. В Go, Swift — & на уровне с "*" "/", | — на уровне с "+" "-" — это уже не провокация, количество ошибок от нарушенных ожиданий резко ниже.
> А насчет выражений, так в любом языке лучше расставить приоритеты явно скобками
Вы реально расставляете скобки даже в выражениях типа a*b+c за пределами виндового калькулятора? Позвольте не поверить…
> Это — надуманная претензия. Никто не запрещает вам отказаться от встроенных средств и использовать библиотеки в стиле Си.
И вы отказываетесь читать то, что написано прямым текстом.
Сейчас, да, есть подобные библиотеки, и их можно использовать. Тогда — не было. Поезд ушёл тогда, до середины 90-х, а не сейчас.
> Как раз наоборот: то, что все работает с handle'ами — замечательно,
И во второй раз не хотите читать. Проблема не в самой работе с хэндлами, а в том, что в writeln с компанией или есть скрытый аргумент в виде stdout (или как он там зовётся в Паскале), или его нет.
> И замечательно — второй вариант читается лучше.
С такой аргументацией прямая дорога к Лиспу. У вас может сколько угодно «лучше читаться» второе, но если не ставить скобки, то ожидаемое не соответствует реальному.
> Строго наоборот — они лучше «отчеркивают» блоки.
Необязательные begin-end — худший вариант из четырёх рассмотренных.
> Естественно, если используются примерно так же, как скобки в С в GNU style, т.е. каждый begin и end строго на отдельной строке с соблюдением отступов.
А со стилем Modula/Ruby/etc., например, не надо ставить таких искусственных условий.
> Скорее это проблема тех, кто работает с Python или просто новичок.
Вы не в теме. Проблема висячего else это проблема, которая известна давно до появления Python (а в Питоне её не может быть по определению). А что «просто новичок» — согласен, профессионал, пару раз обжёгшись, просто введёт принцип «скобки обязаны быть всегда».
> Ни разу за уже 9 лет работы с Delphi (Object Pascal т.е.) такого не было.
А у меня было, когда с ним работал. И у тех, кто сейчас учится — постоянная проблема.
> Остальное все вкусовщина — кто к чему привык.
«Остального» не было, но статистика вкусовщины это уже не вкусовщина. А по ней таки упорно движутся в сторону тех подходов, что я описал как исправленные. Только паскалисты продолжают цепляться за своё легаси, хотя даже автор языка давно советует обновиться.
> Аналоги функций с переменным количеством аргументов появлялись в последних версиях турбопаскаля, когда там даже динамических массивов ещё небыло.
Ну да, когда поезд ушёл — тенденция перехода на C стала массовой.
> А насчет выражений, так в любом языке лучше расставить приоритеты явно скобками, паскаль просто подталкивает к этому порождая полезные привычки.
Извините, я не могу этот совет рассматривать всерьёз. Всегда есть какие-то естественные приоритеты, которым желательно не противоречить. В том же C, кстати, есть свои диверсии — исправленные в языках последних времён (см. таблицы приоритетов операций C и Go).
У Паскаля несколько тяжёлых недостатков, которые его по сути и убили, jIMHO, а в общем он просто сырой. Можно посмотреть на то, какими получились языки линии Modula, в которых некоторые самые тяжёлые проблемы были устранены.
Самое серьёзное — это стиль ввода-вывода. Язык явно задаёт особый стиль для read[ln]/write[ln], со всеми этими write(x:10:5). Программисту сделать свою функцию, которая будет уметь то же самое, нельзя. Сделать различие write() для stdout и write() для заданного хэндла — тоже нельзя. Сделать средствами языка свою реализацию файлов — тоже нельзя. В C — можно. Этого фактора было достаточно, чтобы слой хакеров (в реймондовском смысле) категорически отверг Паскаль и стал смотреть в сторону Си, у которого таких ограничений нет. Причём это не исправлено, насколько мне известно, даже в современных активно развиваемых реализациях! хотя могли давно придумать какие-то макросы, например.
Большая группа проблем при изучении языка (а каждая такая проблема вылазит и у профессионала, если он устал или не сосредоточен!) Я провёл через это нескольких школьников, пишу по своим впечатлениям:
Вечная борьба с блоковыми скобками — ставить begin/end или не ставить, ставить ';' перед else или не ставить, ставить перед end или не ставить (а некоторые психи настаивали, что перед end нельзя ставить ';')… И портит картину то, что постоянно эти скобки пропускаются в примерах и учителями, а понять, как их расставлять — например, как после then и после else раздельно ставить, или не ставить — это для совсем юных очень сложно.
В Си за счёт более коротких скобок эта проблема замаскирована, но осталась. В Modula — имплицитное begin и обязательное end — это один из лучших вариантов стиля. Go/Swift/Perl/etc. с форсированием {}, Python с отступами — это всё решения лучше, чем в Паскале. Для обучения вообще форсирование отступов очень полезно для формирования стиля.
Ещё сбивает с толку то, что repeat — until это само по себе скобки, а все прочие — нет.
И снова те же read[ln], write[ln] — тут пиши файл, а тут рыбу заворачивай — у школьников головы дымятся, у профессионалов тоже. Разделение printf/fprintf как в C — сильно лучше.
Вечная идиотская проблема с тем, что and, or приоритетнее сравнений, поэтому написать a=b and c=d нельзя, нужно (a=b) and (c=d).
Никлаус Вирт орал на весь мир «Не используйте Паскаль! Есть Modula, есть Oberon, в них все дурости Паскаля исправлены!», но так как в IT почти всегда идёт в массы не лучшее, а первое из минимально приемлемых, то застрял Паскаль.
> но это как раз и есть АД си-шечки — в более-менее сложных программах просто в глазах рябит от этих скобочек.
От begin-end рябит в разы хуже, потому что читается медленнее. И, повторюсь, блоковые скобки лучше форсировать даже для одного оператора — мировая практика постепенно пришла к этому. Сразу уходит куча дурных проблем типа «висячий не там else» или «тут воткнул ещё один оператор в теле под if, а почему старый перестал выполняться по условию?» Можно спорить, как именно должны выглядеть эти скобки, но они должны быть.
В области личных вкусов всё можно назвать извратом :) Например, я не понимаю, как можно хотеть переключать раскладки чем-то кроме CapsLock. А ещё один коллега ничего не хочет видеть в этой роли кроме правого Ctrl, благо драйвера позволяют. А за форму мышки можно глобальные войны устраивать, найдётся достаточно сторонников. Так что лучший выход — давать каждому жевать свой фломастер со вкусом нужной ягоды :)
Ссылки переслал.
Поэтому я бы сказал, что вопрос надо заменить на другой — «если так просто писать ручные парсеры, зачем нас мучают всеми этими LL и LALR?» И вот на него уже сложно ответить методологически корректно, потому что тут как раз тот случай, когда преждевременная математизация убивает понимание.
«Добавил» потому, что «прямая польская» запись это префиксная, как в LISP. И идут эти термины «прямая» и «обратная» от работ Яна Лукасевича в 1920-е годы. Слово «польская» добавили уже после него, но в его честь. И это были очень умные люди, которые основали нынешнюю Computer Science.
И ничего «неправильного» в этом нет, кроме того, что такую запись, в отличие от префиксной, сложнее парсить и модифицировать — надо рассчитывать просмотром назад, где части выражения.
> Естественную Польскую Запись
Своими нововведениями вы нарушаете устоявшуюся терминологию. Не думаю, что это будет принято обществом.
Это если считать, что T и Task<T> это принципиально несовместимые сущности из разных вселенных. Но есть и другая трактовка — где это разные, но родственные типы, и где можно сложить T и Task<T> и получить новый Task<T>.
Собственно, построение через async или futures делает почти это (нет синтаксической прозрачности).
Категорически прошу внимательно читать и не подтасовывать. Я не сказал, что она редко _нужна_, я сказал, что она редко _используется_. А используется она редко, в частности, из-за того, что мало где адекватно реализована, и из-за критиканства неосиляторов. Я её использовал и в Python, и в C++ (без общего базового класса), и как-то программы не рухнули и работают без проблем.
Остальной ваш пафос пропускаю мимо за непрактичной банальностью.
Задача 1 — почему область видимости obj заканчивается? Потому что дальше не используется?
При том, что его иначе использовать в этих условиях было невозможно (чрезмерно дорого). И размер нулевой страницы, и громоздкость временной заливки данных в неё и вылива обратно — провоцировали абьюзить её, используя под то, что в нормальных системах не сидит постоянно в регистрах.
> Но архитектура Spark с более чем сотней регистров не стала преобладающей.
Вы с IA-64 не путаете? SPARC имел с точки зрения пользовательского кода 32 регистра (включая пустой). Системному позволялось видеть полный ротор регистров, но к вопросу плотности обычного кода это уже не относится.
Для полностью самостоятельного приложения, которое берёт на себя всю работу с аппаратной частью и вокруг, это было неважно. А вот если хотел сделать что-то такое, что и было хитрое на ассемблере, и сочеталось даже просто с местным бейсиком (хотя бы не сломать его по выходу из своего кода!) — уже возможность использовать нулевую страницу резко сокращалась. А какая-нибудь Рапира использовала её реально всю — оставляя только несколько ячеек нетронутыми — причём какие именно, документация подвирала.
Да, с этим можно было банально не столкнуться. Но с тех пор утверждение «нулевая страница это те же регистры» вызывает у меня только саркастическую ухмылку — и применяется как объяснение, почему процессору нужны настоящие регистры, а не суррогаты.
Хм, я не нашёл с ходу упоминания специфики именно 8080A, все почему-то универсально говорят про оба. OK, сочтём это за сбой памяти.
> непредсказуемых эффектов PDP-11
Про это уже ответили — неродные процессоры могли как-то лажать, но DEC, насколько я знаю, чётко держал планку.
И эти эффекты не касаются самых важных вопросов — например, порядок выбора дополнительных слов в командах типа mov #1, 20(%2).
> Только это «сильно раньше» было без процессоров-чипов, о которых статья.
Не сходится: вы VAXʼу отдельную главу посвятили.
Не принципиально, но считаю необходимым заметить.
> Посмотрите на команду LDA ($55,X) — тaкое на z80 не представить.
И смысла в ней где-то на уровне ноль целых фиг десятых. Я ещё в те времена как-то заинтересовался осмысленностью этой адресации, пересмотрел (чёрт, грепа не было, листал и глазами смотрел) код стандартных программ типа Бейсика, Школьницы — случаи были просто единичные и тупо сомнительные, в отличие от $ABCD,X или ($AB),Y — последняя вообще использовалась на каждом шагу (ну ещё бы).
Был какой-то паттерн написания, при котором именно такая адресация была полезна? Если да, я его не знаю и не использовал.
В остальном, под что легче писать — вкусовщина, но меня постоянное гоняние байтиков через аккумулятор просто доставало, особенно видя рядом вкусные аналоги типа клонов PDP-11.
Если бы конкуренты не тратили попусту по 4 такта на ерунду, тот 6502 просто не взлетел бы.
Автоустановка на ошибку — хороший вариант, но пойдёт не всем, должно отключаться.
Тут интеловский 8080A был конкурентом их же 8085, и Z80 — наверно, поэтому 8085 оказался никому не нужен.
> Есть основание полагать, что GNU ассемблер для x86 делали под влиянием именно ассемблера PDP-11.
Да, но не напрямую. Сначала был порт System V на i386, сделанный AT&T. Именно в нём было принято такое решение — и множество других, напрямую склонированных с Unix ассемблера PDP-11 и VAX-11 — таких, например, как команды ассемблера, начинающиеся с точки (.byte, .word, .align...) Эти наработки были куплены и перенесены в SCO Unix. И уже под влиянием SCO был сделан GNU as.
Некоторые особенности их решений сохраняются до сих пор. Например, в AT&T отличие fsubr от fsub в том, что суффикс r означает укладку результата не в st(0), а в другой регистр — хотя в оригинальном Intel синтаксисе это означало укладку в регистр вычитаемого, а не уменьшаемого. Или, они заменили идиотски путаные обозначения Intel для команд расширений знака (кто помнит навскидку отличие cwde от cwd?) на свои такие же путаные (cltd против cltq).
> Очень странные и непредсказуемые эффекты можно получить, используя счётчик команд как обычный регистр.
У PDP-11 они как раз очень предсказуемые — порядок отработки побочных эффектов аргументов чётко задан.
80188 использовался в некоторых моделях PC XT. Но самое знаменитое его применение — это в модемах USR Courier. В бСССР для него писали прошивки с заточкой под местную специфику, пользуясь лёгкостью понимания.
> с тех пор деление делать быстрее так и не научились!
Частично научились, но это действие вообще проблемное, и на его оптимизацию не тратят усилий.
Про условные переходы:
> С 80386 стало возможным использовать смещения из двух байт
В 32-битном режиме — все 4.
> С этого процессора начинается использование страничной виртуальной памяти – сегодня это доминирующая технология.
Мнэээ… IBM 370, VAX умели страничную адресацию сильно раньше.
Про 6502… он был удачный с точки зрения внутренней конструкции, да. Но писать что-то серьёзное под него было пыткой — говорю как краевед (Агаты в школе), из-за единственного аккумулятора и постоянных конфликтов за ячейки нулевой страницы. Если бы ему дали хотя бы 3 нормальных почти универсальных 16-битных регистра, он бы точно побил всех конкурентов. Боюсь, помешали этому те же причины, что потом убили его развитие.
Мне тоже немного не нравятся. Но я осознаю, что это вопрос привычки. А объективная польза от них достаточно высока, чтобы это терпеть.
С 40 годами опыта можно наловчиться перечитывать код и на эту тему. Но это непродуктивный подход — тратиться на то, что лучше обеспечит машина.
Полчаса на одного студента для такого теста это, мягко говоря, дофига. В этом и проблема — автоматизация позволяет и время сэкономить, и сделать задачу в достаточно разнообразном виде.
Ни капельки. Как раз вызвать к доске и тщательно вникать в подробности… ну, при нашем стиле обучения можно один раз на студента в семестр такое позволить, но не больше.
Ага, «существует». В следовых количествах.
> В этом нет никакой проблемы — это можно считать вариацией неопределенного списка параметров/необязательных параметров.
Когда нельзя самому такое сделать — это не вариация неопределённого списка, это другое, недоступное.
> Ваши некорректные ожидания — ваша проблема.
Ожидания совершенно корректные и конкретные — эргономические и POLA.
> Это снижет количество визуального мусора, делает код более компактным без потери читаемости.
Среди рассмотренных четырёх вариантов опциональные begin-end — самый мусорный вариант.
> Нет, это вы не поняли. Мой ответ относился ко второй вашей фразе, а не к висящему else.
Принципиально проблема не меняется. Посмотрите тут рядом рассказы от PVS-Studio — случаев «забыли обернуть в скобки», мягко говоря, дофига.
Питонист тут как раз скорее сам всегда будет ставить скобки, для страховки.
> И если по тем или иным обстоятельствам язык Х потерял рынок и ушел на обочину, это вовсе не означает, что все его свойства и особенности (включая синтаксис) плохи.
Про «все» я и не говорил. Но упомянул те, которые однозначно плохи.
Я знаю эту проблему, но это какое-то очень специфичное виндовое злонаследие. И именно оно показывает, что POLA лучше выполнять, где нет явных причин не делать это. Нормальный калькулятор с приоритетами сейчас укладывается в пару сотен строк кода. Если им нужно таки сохранять совместимость с древними багами, то лучше было бы переименовать «простой» режим в какой-нибудь dumb.
А неадекватные приоритеты в языках постоянно лечат, где нет необходимости сохранять старые баги. В C приоритет у &, | был занижен неадекватно — ниже сравнений. В Go, Swift — & на уровне с "*" "/", | — на уровне с "+" "-" — это уже не провокация, количество ошибок от нарушенных ожиданий резко ниже.
> А насчет выражений, так в любом языке лучше расставить приоритеты явно скобками
Вы реально расставляете скобки даже в выражениях типа a*b+c за пределами виндового калькулятора? Позвольте не поверить…
И вы отказываетесь читать то, что написано прямым текстом.
Сейчас, да, есть подобные библиотеки, и их можно использовать. Тогда — не было. Поезд ушёл тогда, до середины 90-х, а не сейчас.
> Как раз наоборот: то, что все работает с handle'ами — замечательно,
И во второй раз не хотите читать. Проблема не в самой работе с хэндлами, а в том, что в writeln с компанией или есть скрытый аргумент в виде stdout (или как он там зовётся в Паскале), или его нет.
> И замечательно — второй вариант читается лучше.
С такой аргументацией прямая дорога к Лиспу. У вас может сколько угодно «лучше читаться» второе, но если не ставить скобки, то ожидаемое не соответствует реальному.
> Строго наоборот — они лучше «отчеркивают» блоки.
Необязательные begin-end — худший вариант из четырёх рассмотренных.
> Естественно, если используются примерно так же, как скобки в С в GNU style, т.е. каждый begin и end строго на отдельной строке с соблюдением отступов.
А со стилем Modula/Ruby/etc., например, не надо ставить таких искусственных условий.
> Скорее это проблема тех, кто работает с Python или просто новичок.
Вы не в теме. Проблема висячего else это проблема, которая известна давно до появления Python (а в Питоне её не может быть по определению). А что «просто новичок» — согласен, профессионал, пару раз обжёгшись, просто введёт принцип «скобки обязаны быть всегда».
> Ни разу за уже 9 лет работы с Delphi (Object Pascal т.е.) такого не было.
А у меня было, когда с ним работал. И у тех, кто сейчас учится — постоянная проблема.
> Остальное все вкусовщина — кто к чему привык.
«Остального» не было, но статистика вкусовщины это уже не вкусовщина. А по ней таки упорно движутся в сторону тех подходов, что я описал как исправленные. Только паскалисты продолжают цепляться за своё легаси, хотя даже автор языка давно советует обновиться.
Ну да, когда поезд ушёл — тенденция перехода на C стала массовой.
> А насчет выражений, так в любом языке лучше расставить приоритеты явно скобками, паскаль просто подталкивает к этому порождая полезные привычки.
Извините, я не могу этот совет рассматривать всерьёз. Всегда есть какие-то естественные приоритеты, которым желательно не противоречить. В том же C, кстати, есть свои диверсии — исправленные в языках последних времён (см. таблицы приоритетов операций C и Go).
> Как в таком мире жить?
Улучшать. При любой возможности.
Самое серьёзное — это стиль ввода-вывода. Язык явно задаёт особый стиль для read[ln]/write[ln], со всеми этими write(x:10:5). Программисту сделать свою функцию, которая будет уметь то же самое, нельзя. Сделать различие write() для stdout и write() для заданного хэндла — тоже нельзя. Сделать средствами языка свою реализацию файлов — тоже нельзя. В C — можно. Этого фактора было достаточно, чтобы слой хакеров (в реймондовском смысле) категорически отверг Паскаль и стал смотреть в сторону Си, у которого таких ограничений нет. Причём это не исправлено, насколько мне известно, даже в современных активно развиваемых реализациях! хотя могли давно придумать какие-то макросы, например.
Большая группа проблем при изучении языка (а каждая такая проблема вылазит и у профессионала, если он устал или не сосредоточен!) Я провёл через это нескольких школьников, пишу по своим впечатлениям:
Вечная борьба с блоковыми скобками — ставить begin/end или не ставить, ставить ';' перед else или не ставить, ставить перед end или не ставить (а некоторые психи настаивали, что перед end нельзя ставить ';')… И портит картину то, что постоянно эти скобки пропускаются в примерах и учителями, а понять, как их расставлять — например, как после then и после else раздельно ставить, или не ставить — это для совсем юных очень сложно.
В Си за счёт более коротких скобок эта проблема замаскирована, но осталась. В Modula — имплицитное begin и обязательное end — это один из лучших вариантов стиля. Go/Swift/Perl/etc. с форсированием {}, Python с отступами — это всё решения лучше, чем в Паскале. Для обучения вообще форсирование отступов очень полезно для формирования стиля.
Ещё сбивает с толку то, что repeat — until это само по себе скобки, а все прочие — нет.
И снова те же read[ln], write[ln] — тут пиши файл, а тут рыбу заворачивай — у школьников головы дымятся, у профессионалов тоже. Разделение printf/fprintf как в C — сильно лучше.
Вечная идиотская проблема с тем, что and, or приоритетнее сравнений, поэтому написать a=b and c=d нельзя, нужно (a=b) and (c=d).
Никлаус Вирт орал на весь мир «Не используйте Паскаль! Есть Modula, есть Oberon, в них все дурости Паскаля исправлены!», но так как в IT почти всегда идёт в массы не лучшее, а первое из минимально приемлемых, то застрял Паскаль.
> но это как раз и есть АД си-шечки — в более-менее сложных программах просто в глазах рябит от этих скобочек.
От begin-end рябит в разы хуже, потому что читается медленнее. И, повторюсь, блоковые скобки лучше форсировать даже для одного оператора — мировая практика постепенно пришла к этому. Сразу уходит куча дурных проблем типа «висячий не там else» или «тут воткнул ещё один оператор в теле под if, а почему старый перестал выполняться по условию?» Можно спорить, как именно должны выглядеть эти скобки, но они должны быть.
В области личных вкусов всё можно назвать извратом :) Например, я не понимаю, как можно хотеть переключать раскладки чем-то кроме CapsLock. А ещё один коллега ничего не хочет видеть в этой роли кроме правого Ctrl, благо драйвера позволяют. А за форму мышки можно глобальные войны устраивать, найдётся достаточно сторонников. Так что лучший выход — давать каждому жевать свой фломастер со вкусом нужной ягоды :)
Ссылки переслал.