Comments 289
Лет 30 пишу на Паскале, все никак не могу перейти на C++. Всё в Паскале нравится кроме begin-end — слишком засоряет код многословием, фигурные скобки в этом плане лаконичнее.
В свежерелизнутом 10.4.2 вроде пофикшено — для ErrorInsight сейчас задействован LSP (Language Server Protocol), использующий внутри тот же парсер, что и в компиляторе.
Не могу сказать, это самому надо проверить на том же проекте. Но этот релиз выглядит довольно стабильным и работает быстро, даже без традиционных хот-фиксов.
RAD Studio 10.4.2 integrates over 30 IDE Fix Pack changes!
Вообще общее впечатление от станции 10.4.2 очень положительные. Шустрая, стабильная, LSP сильно помогает.
Проблема в том что при объявлении "на месте" можно задать контекст переменным. Например из раста:
let (x1,x2) = {
let d = b*b-4*a*c;
((-b+d)/(2*a), (-b-d)/(2*a))
}
Сразу видны области видимости, переменная d
не засоряет весь скоуп всей функции. Чем больше временных переменных (а их обычно дофига) тем лучше.
Просто для сравнения, из моей дрейней программы на паскале:
procedure InFile (var n0,k0:byte);
Var
InRec0 :TInputRec;
BufChar :char;
BufString:TString;
C,CharCheck,DigitCheck,DelBool,IncorBool:Boolean;
I,J,K,M,M1,M2,M3: Integer
begin
да, студенческий код весьма некачественный и щас бы я написал лучше, но тем не менее если в теле функции используются всякие переменные цикла и т.п., то из-за отсутствия скоупов приходится все эти M1,M2,M3 переизобретать. Ну или переиспользовать одну переменную в разных контекстах, тогда нужно не забыть что i на третьей строчке это одно, а на седьмой — другое, при этом ни разу не использовав случайно i
до обнуления.
Никогда не задумывался о том, что объявление переменных только в начале процедуры может создавать неудобства программисту. А сейчас подумал и вижу, что процедуры могут быть такими длинными, что каждый раз прыгать к их началу (пока сочиняешь процедуру) во первых забодаешься, а во вторых — внутри процедуры бывают такие внутренние блоки (в циклах или в ветвях условного ветвления), в которых нужны "локальные" переменные только этих внутренних блоков. А тут на тебе — объявляй локальные переменные для всей процедуры — во где ещё неудобство зарыто. Не так ли?
А по-моему так удобно. Сразу их все видишь и с самого начала знаешь, что есть что.
Например объявлением функций и вообще, «орднунгом».
Перейти с Паскаля на Го — по моему вообще наилучший путь миграции для специалиста.
А зачем С++? Есть много прекрасных языков которые не требуют 5 лет сидеть в обнимку с книгами чтобы начать писать без детских ошибок.
Зачем нужен именно машинный код — отдельный вопрос, в частности для шароварных программ на машинный код защиту можно более качественную повесить.
Возьмите хаскель: гц, компиляция в машинный код, компилируемый ассемблер такой что ни один реверс-инжинер не возьмется разбирать. Производительность чуть хуже плюсов (но скорее всего лучше паскаля), потребление памяти лучше чем у джавы.
Но шаровары в 2021 это действительно очень странно
- Для начала, не стоит зацикливаться на локальном GUI, весь мир более или менее успешно, но массово переходит на Веб-интерфейсы, а там картина кардинально другая;
- Далее, хороший выбор локального GUI у С, у С++, у D;
- Сюда же записывается любой компилятор, имеющий биндинги к C-GUI библиотекам вроде GTK или Qt, это будет и Freebasic и Ada и Rust и Nim и много еще чего;
- Еще, не так давно, чуть более года, C# научился компилировать в маш.код. Java, кстати, тоже;
Мир не стоит на месте, в отличие от Паскаля.
Впрочем, FreePascal хоть и медленно, но прилично подтянулся в части качества оптимизации за последние 10 лет.
Для начала, не стоит зацикливаться на локальном GUI, весь мир более или менее успешно, но массово переходит на Веб-интерфейсы, а там картина кардинально другая;
Представляю себе какой-нибудь 3D-принтер или там МРТ-сканер с веб-интерфейсом :-/
Увы, не распарсил что написано
Это я понял, я скорее про вторую часть предложения.
Согласен, но даже у языков вроде расте есть довольно большое количество библиотек, и тулинг хороший, а местами даже отличный. Что уж говорить про условную джаву, под которую либ думаю побольше чем под плюсы будет.
И да, как это парсится из вашего предложения я честно говоря до сих пор не понял. Если убрать несущественные детали то диалог выглядел:
— Есть много языков которые не требуют 5 лет сидеть в обнимку с книгами
— Примерно пяток
Извиняюсь что к этому возвращаюсь, но то ли я дурак, то ли лыжи не едут.
Потом смотрим рейтинги востребованных у работодателей языков и считаем те, «которые не требуют 5 лет сидеть в обнимку с книгами». Сколько получилось?
Да сколько угодно. За 5 лет можно стать гуру джавы которые знает все нюансы языка. Тоже для шарпа. То же для практически любого языка из топ-10 рейтингов.
Плюсы крутой язык, но им 40 лет уже. Это не проходит бесследно. А то так ещё придем к выводу что индустрия всё время стояла на месте и ничего лучше придумать не смогла за все это время.
И стал доволен ещё больше…
Так для C/C++ они написаны, а "другие языки" чаще всего повторяют всё одни и те же процессорные грабли.
Как будто-то Машина Тьюринга (чистая абстракция, полный фейк по факту) будет их интерпретировать, компилировать или выполнять!
Если умолчал о проблеме это решил проблему, то всё ясно с такими программистами.
много прекрасных языков которые не требуют 5 лет сидеть в обнимку с книгами чтобы начать писать без детских ошибок
Вы человек далёкий от каких-то серьёзных вычислений если такое говорите.
А у меня немецкая клавиатура. Ненавижу фигурные скобки. Так что begin...end forever.
Да, поэтому правильный компромисс: просто отступы. Скала3 хорошо показала, что этого вполне достаточно. Для компилируемого языка в отличие от того же питона нет проблем с тем что скрипт может неправильно проинтерпретироваться: у нас есть компилятор. Читается куда чище и проще чем скобки, ну и конечно на порядок лучше бегин/эндов
О, теперь я знаю, почему в части программ на ZX Spectrum у меня появлялись ÄаÜ
. Спасибо :)
Можно, но зачем? Отступы и так являются обязательным элементом любого уважающего себя языка, за некорректные отступы в некоторых обществах можно даже услышать много нелицеприятного про себя. Делать же в языке 2 механизма для одного и того же (и отступы, и скобки) излишне.
Вся аргументация против отступов что я слышал — "а вдруг я со стаковерфлоу код скопирую, а он неправильно вставится". Что тут скажешь — обычно разработчики достаточно интеллектуальные, чтобы суметь нажать tab/shift+tab несколько раз чтобы выравнить код
Лет 30 пишу на Паскале, все никак не могу перейти на C++
На Паскале программировать начал тоже 30 лет назад. На C немного в университете тоже попрограммировал немного. Но после окончания универа как на перл перешёл, так и не вылезаю из него. Паскаль-то хорош. Но мне ж нужно ваять сайты, ну и всякие скрипты для управления системой и контроля над ней.
#perl -Mstrict -wc
map{while(1){}}@a;
которая завешивала компьютер и под Windows и Unix сервер при её трансляции(!) Было такое впечатление, как будто я первый, кто начал программировать на Perl. :-)
Как-то поспорил с одним профи, что смогу написать для Perl 5.8.x одно re, которое проверяет на правильность арифметич. выражения с неограниченным уровнем вложенности скобок и написал, дав пример, как можно по кирпичикам составлять такие re.
По поводу проверки арифм. выражений и другие мои продвинутые re можно глянуть в моём разделе на www.cronc.com/ru Жаль, я не нашёл, как на этом материале можно зарабатывать, пришлось оставить это дело…
Время, вне IT, течёт несколько медлненнее.
Раз, когда был Perl 5.8.1, написал программку ... которая завешивала компьютер и под Windows и Unix сервер при её трансляции(!) Было такое впечатление, как будто я первый, кто начал программировать на Perl. :-)
Perl это реально write-only язык. Как будто даже не выполняют потом!
А месяц назад я решил вспомнить C, чтобы стать, как все, и переписал свой быстрый LZ компрессор с Delphi 7 на C (под GCC, пока только декомпрессор) и получил значительный выигрыш в скорости, я на асм пока такой скорости не достигал. Хотя, под Lazarus отлаживать программу удобнее, чем в GCC. Я вообще не пользовался отладчиком, когда переписывал… Теперь постараюсь превзойти zstd на быстрых уровнях сжатия с пом. своих типсов с триксами. :-)
В пень фигурные скобки! У меня немецкая раскладка. Мне в разы легче набрать begin/end.
А держать три разные раскладки - переключать замучаешься.
Всё это происходило без международных проектных организаций, без бюрократии и бюджетов на исследования. Сегодня это было бы невозможно.
Но почему сегодня невозможно работать без бюрократии и бюджетов? Почему запрещено работать за свой счёт? Я знаю людей, которые именно так и работают, «без бюрократии и бюджетов».
Все базовые вещи на нем выучил: структуры данных, алгоритмы (вычисления, линейную алгебру, графы), работу с файлами. Основы, без которых дальнейшее обучение программированию бесполезно.
Это останется навсегда:
uses Graph
Turbo Pascal был моим первым языком программирования.
И моим, нас ещё всякими формами Бэкуса-Наура мучили, синтаксом на диаграммах.
Кстати, странно что в статье Вирт обошёл вниманием Аду и VHDL, они вроде тоже если не дети, то внучатые племянники дедули Pascal-я.
Модуль Graph и подключение egavga.bgi
Прямо так и говорили "подключить егавгу"
Поэтому нам CGA/EGA было уже неинтересно совсем ;)
Даже в том месте, где я первый раз полапал Паскаль, адаптеры работали с EGA-драйверами, при этом игры (Dangerous Dave) их как EGA не видели. Прелюбопытные были железяки. А уж потом — какой CGA, вы о чем? 16 цветов красивее.
Зачем в этой программе в заголовке
uses crt, graph;
если ни то ни другое в коде не используется?
В детстве нравился Паскаль, потом его и сам преподавал в школе, а ещё позже даже выполнил пару заказов на фрилансе с этим языком. Можно сказать, что именно детище Вирта и сформировало меня как программиста.
Но сейчас бы программирование на нём было бы лично для меня пыткой, я бы не стал на нём работать даже если бы предложили солидные деньги. Даже сам толком не понимаю почему так — ведь это же эталон структурированности и понятности в написании программ. Даже на богомерзком VBA я с огромным удовольствием делаю pet-проекты, но не на Паскале.
Первая статья в журнале Монитор, про баг в ТурбоВижн! За что получена 5ка по информатике автоматом в 11 классе :) Ностальгия.
Очень заинтересовали (именно как работа школьника). Нет ли ссылки или скана.
Ничего себе!!! Я думал журнальчик то все — почил в Бозе совсем и навсегда :) Спасибо! Не поленился — нашел заметочку :) 3.94 на 4й странице :)
По этому поводу был анекдот из конца 80х:
Знаете, почему Никлаус Вирт никогда не ездит в Испанию?
Потому что он один раз спросил у своих испанских коллег:
— Правда, что Паскаль — один из лучших языков программирования?
— Si!, ответили испанцы.
Обиделся Вирт, и с тех пор в Испанию ни ногой...
P.S Уже лет… дцать в своих проектах успешно применяю Паскаль совместно с
С++
Потому что каждый инструмент хорош, если его использовать по назначению.
Потому что каждый инструмент хорош, если его использовать по назначению.
А вот про это расскажите поподробнее, пожалуйста. Какой назначение у Pascal?
Если в алгоритме сказано «достань в таблице третий элемент», я могу написать table[3].
А вот «достань в записной книжке телефон Маши», написать phone[«Masha»] уже не получится, хотя с чего бы. Ну или «пройдись по всем элементам таблицы». Возможностей для построения абстракций там не хватало.
Можно реализовать через Variant. Такое используется, например, в подлибе mORMot для работы с JSON. Тормозить не будет.
В Дельфи, помнится, придумали мега-фичу для тех далёких времён, когда борланды ещё изобретали дельфи:
Для операции присваивания сделали возможность наваять свой метод write (точное название не помню), а для операции чтения значения из свойства (из переменной), соответственно, метод read.
Вот это была фича так фича!
Получалось, что я мог написать целую процедуру установки значения, которая вызывалась бы в момент обработки оператора присваивания:
a := b
`- а в это момент запускается написанная программистом процедура, которая реализует подарограмму установки значения. Поприменять эту фичу я:
а) тогда так и не успел
б) в других языках подобных фич больше нигде не видел
И как теперь в Паскале получить phone.name? Может, я чего-то путаю, но не помню такого синтаксиса.
А то в развитии и фичах С++ никто не отказывает, а на паскаль смотрят через призму 40-летней давности
А можно минимальный пример программки на паскале, которая делает 3 вещи:
- определяет свою структуру данных типа MyArray, которая является оберткой над динамическим массивом некоторой длины (передается в конструктор аргумнетом)
- реализует возможность итерирования по всей структуре данных (for each), которая работает очевидным образом
- написать функцию
foo
, которая должна получить на вход MyArray и указатель на функцию-предикат. Задача найти элементы MyArray удовлетворяющие предикату из аргументов, отсортировать их и вернуть первые 3. Функция должна работать для массива любого типа, который поддерживает сравнение.
Не переходим. Можно сделать "конструктор"-функцию с тем же самым. Или по-вашему есть принципиальная разница между foo := new Foo(args)
или foo := NewFoo(args)
?
Именно так, да.
Смысл же в том, чтобы писать поменьше, а получать побольше, чем меньше бойлерплейта тем лучше, нет?
Напомни, где там в Тиобе появляются чистые ЯП?
И да, писать ТЗ из области хотелок, просто смешно. Вам пуговицы, или…?
где там в Тиобе появляются чистые ЯП?А причем тут вообще чисто функциональные ЯП?
В современные ООП-языки типа C# и Kotlin добавляют много фишек из функциональщины, и таким образом они в себе сочетают достоинства разных языков и парадигм.
Точно так же оригинальный паскаль был чисто процедурный, но потом в него добавили ООП, и благодаря чему в том числе Delphi имел в былые времена свою рыночную долю.
Ну а заявлять про «ТЗ из области хотелок» вообще странно с вашей стороны, подобная задача не чисто-теоретическая, а вполне может встретиться реальном проекте.
Ухх сколько сочных и интересных офферов я видел на паскале! (ровно ноль, что, к слову, строго меньше числа офферов на каком-нибудь идрисе)
А «По запросу «Idris» ничего не найдено»
Я про интересные офферы. Например, на идрисе — верифицированный блокчейн, или верифицированные распределённые вычисления. А на дельфи?
Ну, в этом нашем США на indeed.com меньше сотни вакансий по "delphi developer" (из которых значимая часть — на самом деле какой-нибудь front-end developer, просто в тексте вакансии пишется что-то типа «and we have some projects in delphi»). И мы, к слову, обсуждали pascal — а там по «pascal developer» их вообще 24 с описаниями типа такого:
Developers reporting to the CTO. Requirements include, knowledge of relational databases, in any object oriented language such as Javascript, Java, Pascal, Delphi, C #, VB.net. Duties and responsibilities include unit level debugging, interaction in development and QA cycle with QA department and beta sites.
или такого:
[...] Working knowledge of and/or experience with at least one object-oriented programming language; e.g. Object Pascal, Java, C#, C++, etc. [...]
Не знаю, сколько там на самом деле паскаля в продакшене.
По идрису их, конечно, существенно меньше (целых три), но, опять же, почему-то так получилось, что когда я интересовался работой, на идрисе она находилась, а на дельфи — нет.
var phones: TDictionary<String, String>;
...
phone := phones['Маша'];
Посмотрите пожалуйста задачку из https://habr.com/ru/company/vdsina/blog/544006/#comment_22736692
Очень хотелось бы увидеть максимально упрощенный и идиоматичный код на паскале, реализующий задачу
К слову, этот текст опровергает распространенную байку, что Паскаль изначально создавался как язык для обучения программированию. Судя по этому рассказу, Вирт сначала создал язык так, как ему представлялся хороший язык программирования, а уже потом он стал популярен в обучении.
Есть ещё вот такой паскаль, его в школе учил
http://pascalabc.net/
Да, ностальгия сумасшедшая. Тоже начал с него постигать программерскую науку. Буквально на днях попались под руку две книжки по Паскалю, начала нулевых, полистал, повспоминал…
Сейчас, конечно, язык кажется тяжеловесным (впрочем, после JS/TS любой таковым кажется), особенно дико выглядит то, что после строки "uses что_то_там" в глобальную область сыпется всё содержимое модуля (привык поштучно импортировать и знать, что и откуда).
Покупал Turbo Pascal for Windows 1.0 на трех пяти дюймовых дискетах. Какая там была документация!)
Не то что ASCII C, который долго жевал дискетки, прежде чем скомпилирует программу.
Т.е. программы получалась не рабочей.
Приходилось его просматривать, исправлять, оптимизировать, после этого все работало)
Именно с тогои не заладилось у меня с C и С++.
Какая там была документация!
Дома где-то лежит коробочный седьмой паскаль с турбовижном до кучи. По размерам — куб со стороной полметра, по весу килограмм так 10, и таки да, почти всё из этого — чисто документация %)
Ностальгия:) школьные агаты и паскаль:)
github.com/gnanev/fun/blob/master/GAME.PAS
А потом… потом разные диалекты начали разбредаться. А как раз у C началась стандартизация (ANSI C89, который, в отличие от Pascal, разработчики компиляторов реально старались поддерживать, потом C++, где вначале диалектные фичи появлялись, но потом их все дружно изводили). И популярность Pascal начала стремительно падать.
Думаю эти вещи связаны друг с другом, но всё равно непонятна причина. Почему разработчики C стремились поддерживать стандарты. Почему разработчики Pascal на них плевали?
А у C хоть и не было международного (ANSI/ISO) стандарта, но был Unix. И этого оказалось более чем достаточно для всеобщего признания K&R C как Стандарта, который надлежит соблюдать. А потом уже ANSI/ISO подтянулись.
А потом уже ANSI/ISO подтянулись.Вот в том-то и дело, что не “потом”. Многие фишки были добавлены в разные компиляторы C синхронно, одновременно и совместимо в конце 80х. А стандарт вышел только в 1989м.
Это уже потом Microsoft “забил” на C и поддержку более новых стандартов, чем C89 не добавлял десятилетиями (я не издеваюсь: до 2020го года он только C89 поддерживал… в 2020м наконец-то ситуация изменилась).
Однако “забив” на C Microsoft и другие разработчики компиляторов вложились очень сильно с поддержку стандарта C++ (использование разных вендоро-специфичных вещей постепенно уменьшалось).
А вот в Pascal мире над идеями стандартизации и поддержки ISO все откровенно смеялись. Ну и досмеялись почти до полного забвения, по итогу.
В мире Паскаля стандартом де-факто стал Turbo Pascal, а затем Delphi. Другие известные компиляторы, такие как FPC и Oxygene, умеют работать в режиме совместимости.
Проблема в том, что Delphi как язык очень консервативен и медленно развивается. Smart Pascal (Smart Mobile Studio), Oxygene — диалекты Pascal/Delphi, которые получили разные классные фичи, и они продолжают улучшаться. Но в этой части им приходиться жертвовать совместимостью.
Все библиотеки и все разработки затачиваются под конкретный комплиятор.
Поддерживающих хотя бы пару — крайне мало.
А вот в мире C/C++ — это было нормой уже в 80е.
Почему так получилось?
Delphi как язык очень консервативен и медленно развивается
Сложно развиваться, когда ближайший конкурент играет грязно и жёстко. Майки перекупили двух главных идеологов, Хейлсберга и Гросса, и сделали всё, чтобы развитие остановилось. Наверняка читали все эти истории про скупку акций через подставные фирмы, своего человека от MS в совете директоров Борланда, передачу технологий и другое. Проблема не в идеологии Делфи и не в технологиях. Большая политика и большие деньги всё предрешили. Компанию просто съели, раздавили. www.sql.ru/blogs/ozka/360
Но сейчас дела бодро идут в гору :)
Майки перекупили двух главных идеологов, Хейлсберга и Гросса, и сделали всё, чтобы развитие остановилось.А много эти
“главные идеологи” наразвивали в C++?
Главная проблема Pascal — в том, что в какой-то момент Pascal стал восприниматься только как Turbo (потом Borland) Pascal. Так что как только у этой одной фирмы начались проблемы — сразу всё и посыпалось.
А вот в случае с C++ идеолог хотя и работал, формально, на одного из вендоров, однако Sun никогда не был лидером в мире C/C++. И даже когда Sun исчез — это не привело к катастрофе.
Имхо из существенных минусов, что прочувствовал это небольшой выбор среди уже готовых библиотек.
А так, язык как язык, быстрый, понятный, билдится под любую платформу.
Кстати вроде бы Skype раньше был на Delphi, и только потом они перевели на реакт, и все стало дико тормозить, даже просто набор сообщения иногда. Хотя сейчас вроде получше.
Юзаю на свежем Redmi 9c.
Андроидовый скайп никогда не был ни на Delphi, на Electron :)
У них, кстати, есть Skype Lite для low-end телефонов, летает ощутимо быстрее: play.google.com/store/apps/details?id=com.skype.m2&hl=ru&gl=US
Интересно, сколько народу не видело этот древний текст: "Настоящие программисты не используют Паскаль"
thesun2003.github.io/armageddon
даже прикупил и реанимировал ноутбук под него
Так можно же в DOSBox'е носталигировать?
Запускать программу неудобно — по умолчанию Ctrl+F9 убивает досбокс. Это меня когда-то ТАК выбесило...
“Algol 60 was intended for scientific calculations (numerical mathematics) only.”
Да ладно! Algol-60 был у меня первым в промышленном программировании. И то были не scientific calculations only, а очень даже real-time missile defense systems. В отличие от fortran (как же я признателен мирозданию за то, что первым у меня всё же был не он, а именно algol).
Pascal was easy to teach, and it covered a wide spectrum of applications, which was a significant advantage over Algol, Fortran, and Cobol. The Pascal System was efficient, compact, and easy to use.
О как! По прошествии 50 лет изначальный pascal (в том числе и стандартизованный ANSI) внезапно оказался универсальным языком! При том, что имел лишь жалкие намёки на io, и вообще не имел ничего подобного хотя бы сишной (читай “файловой”) модульности (да-да, вы правильно поняли — программа людого размера могла быть только в одном единственном исходном файле, что лишь подтверждает назначение языка, см.след.абзац), из-за чего мне в своё время пришлось написать для него препроцессор.
Дедушка Никлаус сам же и заявлял, что создавал pascal как язык не для практического программирования, но для обучения программированию (структурному). И я, кстати, преподавая программирование, с огромным удовольствием именно его и использовал, pascal для этого действительно был в те временя the best. Для работы Вирт сам же взялся за Modula-2 и Oberon. А увидев взрывную популярность pascal (куча несовместимых между собой диалектов, и при этом ни одного из опробованных мной соответствующего Стандарту ANSI), Вирт сам же и сказал что-то в стиле “Главная беда pascal в том, что очень многие восприняли его слишком всерьёз”. Спустя 50 лет это решил сделать и сам создатель? Только он путает свой pascal с тем, во что его превратили early adopters.
Впрочем, Вирта я и впредь буду уважать, не pascal'ем единственным (да и вообще не pascal'ем) ценен он отрасли. С 50-летием отпрыска тебя, дед!
Algol-60 был у меня первым в промышленном программировании. И то были не scientific calculations only, а очень даже real-time missile defense systems.
Ого! Стесняюсь спросить, а на какую страну вы тогда работали? Неужели советские противоракеты программировали на Algol-е?
В виртовском паскале ещё и обработки строк не было.
Вся заслуга превращения паскаля в язык, пригодный для практического использования, принадлежит UCSD. И дальше это развил Borland.
Идеальный язык должен определяться в категориях математической логики, аксиом и правил вывода. Для его понимания не должно требоваться никакой отсылки к любому компьютеру или механизму. Это основа портируемости.
По моему скромному мнению — это и привело к тому, что Паскаль не стал таким-же популярным ЯП как С или Java, хотя такие предпосылки и были. Слишком он академичен, это хорошо для преподавания и обучения, но плохо для повседневной работы, обычной программистской рутины.
Типичный пример: в начале метода объявляются все переменные, а потом проверяются на нулл несколько раз)
Впрочем писать лучше так, что-бы таких огромных «портянок» кода не было, так что тут в общем-то недостаток спорный, если писать правильно, декомпозируя задачу и разбивая на небольшие модули, то и объявление переменных вначале метода не сильно мешает. Проблема только в том, что в реальных, рабочих проектах классы обычно довольно быстро распухают и становятся трудно читаемыми.
Т.е. так или иначе, но вам приходится иметь дело с «портяночным кодом», и в этом случае такой стиль объявления переменных реально делает код еще более трудночитаемым.
И проблему доступности переменных во всем блоке это не решает. Могу ошибаться, но вроде бы классический Паскаль не разрешает объявлять переменные внутри begin… end;?
И в принципе бесполезно объяснять почему так делать плохо/не надо, пока он не прочитает-изучит определенное количество книг и сам не разберется.
Одно помогает в рабочих проектах — анализатор кода SonarQube. С ним спорить бессмысленно), расшифровка как исправлять есть.
Даешь задание чтобы были исправленны найденные им ошибки.
Я на перле раньше переменные тоже только объявлял, а значения им давал "когда-то потом". Но после того, как я начал применять FastCGI, неприсваивание значений переменным в месте их объявления стало приводить к неожиданным результатам — во время следующих запусков процедуры её внутренние переменные стали помнить свои прежние значения их прошлой жизни — из предыдущих запусков процедуры. С тех пор переменным значения даю сразу же в момент их объявления. На крайний случай просто обнуляю их, если реально нужных значений для них в момент объявления пока не существует. Но главное, чтобы в них не оказывались значения случайные, неожиданные.
Суть в том чтобы переменную было видно только там где она действительно нужна и не приходилось заботиться с проверками её предыдущего значения.
В турбопаскале-6.0 такая штука иной раз тоже попадалась, если в цикле вызываешь одну и ту же процедуру несколько раз. Это меня заставило инициализировать переменные. А вот сегмент данных строго заполнялся нулями, и когда начали учить Си, пришлось ещё и переменные в main() инициализировать сразу, иначе начинались проблемы.
3.6.2 Initialization of non-local variables [basic.start.init]
2. Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.
А еще в TP можно делать вставки на ассемблере и в школе небольшая лабораторная работа по перестановке байт в слове решалась в 3 инструкции tasm.
Turbo Vision — очень хорошая библиотека. Полноценный многооконный интерфейс на минимальных аппаратных ресурсах. Даже сейчас она смотрится достойно. Правда, из-за использования досовских прерываний и прямого доступа к видеопамяти она оказалась привязана к DOS, и нормально портировать ее на другие платформы не получилось. Именно эта библиотека способствовала росту популярности паскаля, но именно из-за нее он и застрял в досе. Потом эту же проблему повторили в delphi.
вставил в него ассемблерные вставки для перевода интерфейса в графику для EGA и VGAНо ведь TurboVision был целиком и полностью основан на псевдографике, а не на графических примитивах, и простого переключения видеорежима было явно недостаточно, чтобы выводить всё то же, но не в в 0xB8000 в текстовом, а в 0xA0000 в графическом режиме, модифицировать пришлось бы явно гораздо больше.
Или все-таки речь про упомянутый выше GraphicsVision? (кстати, а вы знали, что его автор — известный в широких кругах Solar Designer?)
Английское слово "complex" совсем необязательно переводить как "комплексный", намного чаще (и в этой статье тоже) это просто "сложный".
И насчёт того, что для Турбо-Паскаля разрабатывали спец. операционную систему, тоже скорее всего ляп переводчика. Наверняка имелась в виду среда разработки.
к слову, операционки полностью на Паскале существуют:
ultibo.org
компилятор — fpc, для Raspberry Pi
Вирт имел в виду специальную ОС для UCSD Pascal, из которого впоследствии вырос Borland.
Конечно, Вирт упоминает оберон, как "правильное" развитие паскаля. Потому, что автор оберона — он сам.
Но фокус в том, что самое массовое развитие паскаля — это, всё-таки, турбо-паскаль и далее дельфи. Где-то в погоне за строгостью и простотой Вирт всё-таки нарушил правило Эйнштейна насчёт "как можно проще, но не проще".
Паскаль был очень прост для написания компилятора. Его синтаксические диаграммы в какой-то книжке популярной переводной занимали три странички, и не самым мелким шрифтом.
Что касается крупных проектов, то для них он был негоден. Ибо вся программа была одним большим блоком между begin и end. (с точкой, в отличие от вложенных блоков).
И кстати нельзя сказать, что он был высокоуровневым — там были операции, которые явно отсылали к способу хранения переменных в памяти. Например, строки (длиной не более 255 символов, так как нулевым была длина). Или совмещение в памяти массивов — так, что некоторые элементы разных могли физически совпадать.
Плюс, хотя это может уже буквоедство, сам компилятор не полностью мог быть написан на Паскале, поскольку в нем присутствовала, к примеру, функция write() с переменным числом аргументов, чего стандарт языка для определяемых программистом функций не допускал
begin
и особый end
-с-точкой", а «блок begin..end
и после него точка, означающая конец программы». Эта точка вполне могла отделяться от end
переводами строки и/или комментариями.Например, строки (длиной не более 255 символов, так как нулевым была длина).Самое смешное, что подобных строк у Вирта не было. Хотя они использовались во многих популярных компиляторах.
Интересно, кто первым до них додумался.
Или совмещение в памяти массивов — так, что некоторые элементы разных могли физически совпадать.Опять-таки: у Вирта это было сделано так, как сейчас в
Rust
'е: через селектор с проверкой при обращении. То есть безопасно.Опять-таки — многие реализации этот «лишний» код не генерировали.
Плюс, хотя это может уже буквоедство, сам компилятор не полностью мог быть написан на Паскале, поскольку в нем присутствовала, к примеру, функция write() с переменным числом аргументов, чего стандарт языка для определяемых программистом функций не допускалКомпилтор-то мог быть написан на Паскале, просто уже потом, в этом языке другую такую функцию нельзя было написать.
Вирт это поправил в Модула-2… но к тому времени Паскали разбрелись “кто куда” и его мнение уже никого не волновало…
Самое смешное, что подобных строк у Вирта не было. Хотя они использовались во многих популярных компиляторах.У Вирта строк вообще не было. См стандарт 1972г.
Даже в Стандарте ISO 7185:1990 строки implementation defined и совсем нет функций для работы с ними, что чертовски неудобно.
Вот реально непонятно почему так вышло. В 1980е переносимость между разными компиляторами C была, мягко скажем, аховой. Но в 1990е разработчики C и C++ компиляторов начали изводить несовместимости (даже Borland и Microsoft, заклятые враги в то время, уменьшали со временем зависимость от проприетарных технологий), а разработчики всей этой толпы несовместимых между собой Паскалей — наоборот.
Может быть потому, что в мире C++ был Страуструп, а Вирт увлёкся новой игрушкой (Обероном), не знаю.
Но в 1980е Паскаль был популярнее, в 1990м они были сравнимы по популярности, а в 2000м уже всё было кончено: все последующие языки уже даже не пытались соревноваться с C/C++, они надстраивались «поверх».
«Программирование без goto» стало модной фразой, но народ не знал, что первоначально здесь имелся в виду оператор Фортрана goto для перехода по списку меток. Вот это действительно был умопомрачительным оператор.
Любопытный факт: я во времена Фидо скачал с московской BBS White Bear полные исходники Turbo Pascal 6.0, которые компилировались с пом. tasm, tpc.exe и make файла с добавлением tpu файлов для Turbo Vision. Получался файл turbo.exe, который работал (я сам проверял). Видимо, в Борланде кто-то у кого-то с раб. стола это стащил. Там в исходниках чёрт ногу сломит: одни только asm подпрограммки для Intel 286 с макросами чего стоят… Вот так давалась быстрая трансляция.
Один программист по фамилии Свердлов (автор статей о ПК Радио-86РК в журнале «Радио») хотел с пом. этих исходников сделать то ли 32-разрядный TP, то ли под ДОС-экстендер (типа TMT Паскаля Антона Москаля), сказав афоризм Ш. Холмса: «Если какой-то человек что-то смог сделать, то другой человек сможет это понять». Но действительность не подчинилась формуле Конан Дойля, и после попытки Свердлов сказал, что у него задница не чугунная. Как известно, чугунной задницей обладал не Свердлов, а Молотов. ;-)
Интересно, зачем надо убирать из языка оператор goto? Из-за этого порой приходится повторять одинаковый код. В операторе if… then begin… end; фактически есть goto, но найти в листинге end, парный к этому begin, значительно труднее, чем метку. :-)
goto позволял легко и непринужденно превратить код в жуткую кашу с трудноуловимыми переходами (чем многие тогдашние программисты с удовольствием и занимались), тогда как у if-then строго определенная структура, облегчающая чтение и понимание кода.
Интересно, зачем надо убирать из языка оператор goto? Из-за этого порой приходится повторять одинаковый код. В операторе if… then begin… end; фактически есть goto, но найти в листинге end, парный к этому begin, значительно труднее, чем метку. :-)
Потому что любой goto можно (и нужно) переписать через другие средства (вложенную функцию, например). Goto нужен был когда языки были плохенькие и нужен был максимальный контроль. Как легаси, оставшееся от ассемблера. Впоследствие стало понятно, что для программирования абстрактной машины куда лучше использовать известный математический аппарат. Ну там, функции, композиции, это всё
У нас в школе была программистская практика и нам как раз такое досталось.
А goto был строжайше запрещён. Не, мы всё написали, конечно, но, честное слово, понять это было сложнее, чем если бы мы писали с goto.
Тогда у блоков были бы, хотя бы, осмысленные имена, а так мы их просто перенумеровали и переменную
state
числовую завели… без «секретной тетрадочки» понять было нельзя ничего.А потом приносит тебе заказчки блок-схему на листе бумаги A0 с сотнями стрелочек и ромбиков и… усё.
Везет вам. У нас заказчик говорит обычно предлагает поиграться с формой квадрата.
А goto был строжайше запрещён. Не, мы всё написали, конечно, но, честное слово, понять это было сложнее, чем если бы мы писали с goto.
Не, если все чисто на ифчиках и с единой точкой выхода — тогда конечно. Но какие-нибудь break/continue за goto не считаются — такие же конструкции управляющие как иф. А лямбды, паттерн матчинги и остальное дают очень много альтернатив для удобного написания логики.
Тогда у блоков были бы, хотя бы, осмысленные имена, а так мы их просто перенумеровали и переменную state числовую завели… без «секретной тетрадочки» понять было нельзя ничего
О, так вы на практике применили структурную теорему :)
Но какие-нибудь break/continue за goto не считаются — такие же конструкции управляющие как иф.Вот только в Pascal их нет. Их Borland добавил. Причём довольно поздно.
Странно, я на паскале в универе ими по-моему пользовался и все было хорошо. Правда, я все время какими-то дикими компилями пользовался, вплоть до дотнетовского порта pascal.abc (за то, что там можно было мышкой код выделять в отличие от синей трубы).
Как-то очень сильно на лабе удивился, когда безотказный флоу "сделал дома в паскальабц -> показал в универе в трубе" внезапно дал сбой и программа отказала компилироваться. Так я узнал, что у разных версий паскаля разный СТД, и что апи дотнетовской даты-времени с турбопаскалевским не совпадает.
Предположим, что нужно посмотреть, какой код выполняется, если условие if ложное, а оператор if содержит другие if и begin — end. В этом случае, как я написал, надо искать end, парный к этому begin, а на это можно потратить много времени, вплоть до того, что в редакторе приходилось искать end с таким же числом отступов слева, как и begin…
И ещё: пусть надо по ошибке выйти из внутреннего цикла через несколько циклов наружу. Без goto приходилось заводить флаг и проверять его в каждом внешнем цикле и делать break (фактически тот же goto...)
> Goto нужен был когда языки были плохенькие и нужен был максимальный контроль.
Но ведь тут речь о Паскале. В Perl присутствует goto и ещё другие операторы перехода. А в php у меня без него как-то были неудобства (см. выше).
А ещё бывает нужно сделать много выходов из процедуры по ошибкам с соотв. сообщениями, вот тут удобно использовать goto на конец этой процедуры. Эти выходы по ошибкам нисколько не затуманивают кода (хотя бы путём выбора имён меткам err1, err2 или аналогично). А как в Паскале это сделать без goto и не менее удобно, это надо долго думать.
Помню, я в одной программе на TP придумал такой работающий финт: в основной программе запоминал значение регистров BP и SP и путём их восстановления выходил из много раз вызванной рекурсивной подпрограммы в основную программу. С академической точки зрения это было нехорошо, но с практической, как в TP ещё можно было бы выйти из глубокой внутренней или рекурсивной подпрограммы? Она на 55555 рекурсивном вызове находит выигрыш в логической игре, теперь что, с помощью проверки флага и лишнего кода постепенно выходить наружу через все промежуточные рекурсивные вызовы?
Предположим, что нужно посмотреть, какой код выполняется, если условие if ложное, а оператор if содержит другие if и begin — end. В этом случае, как я написал, надо искать end, парный к этому begin, а на это можно потратить много времени, вплоть до того, что в редакторе приходилось искать end с таким же числом отступов слева, как и begin…
Щас проверил — на полсотни микросервисов суммарным объемом кода под миллион строк у меня ровно 8 мест где есть два вложенных ифа. В остальных случаях оно имеет вид
if (something) { DoStuff(); }
и все вложенные ифы уже спрятаны в функцию. Поэтому нет, не надо. 3 и более вложенных условий можно спокойно делать ворнингом.
И ещё: пусть надо по ошибке выйти из внутреннего цикла через несколько циклов наружу. Без goto приходилось заводить флаг и проверять его в каждом внешнем цикле и делать break (фактически тот же goto...)
Так гоуту тут не нужен:
if (condition) {
throw new MyError();
}
Отличие от гоуту в том что я по одному кейворду сразу знаю куда пойдет поток выполнения, искать меток не нужно.
А ещё бывает нужно сделать много выходов из процедуры по ошибкам с соотв. сообщениями, вот тут удобно использовать goto на конец этой процедуры. Эти выходы по ошибкам нисколько не затуманивают кода (хотя бы путём выбора имён меткам err1, err2 или аналогично). А как в Паскале это сделать без goto и не менее удобно, это надо долго думать.
Можно привести пример? Потому что обычно можно сделать что-то такое:
public void SumFiles(string f1, string f2)
{
using var file1 = File.Open(f1);
if (ProblemsWith(file1))
{
throw new MyErrorWithFile1();
}
using var file2 = File.Open(f2);
if (ProblemsWith(file2))
{
throw new MyErrorWithFile2();
}
// много кода
return result;
}
При возникновении ошибки в любом месте она будет передана выше по коллстеку, ресуры все закрываются в случе успеха и в случае неуспеха, сначала выполняются проверки unhappy path, в результате чего happy path — линейный и чистый. При этом гоуту — нету.
Она на 55555 рекурсивном вызове находит выигрыш в логической игре, теперь что, с помощью проверки флага и лишнего кода постепенно выходить наружу через все промежуточные рекурсивные вызовы?
Именно так. Правда, если у вас код написан в хвосто-рекурсивном виде то никакого коллстека не будет, оно всё в цикле единственного вызова прокрутится.
Верю, что хак был полезен в вашем случае, но можно было просто немного переписать и получить чистое решение с теми же свойствами.
А эти примеры точно годятся для Турбо Паскаля?
И ещё: пусть надо по ошибке выйти из внутреннего цикла через несколько циклов наружу. Без goto приходилось заводить флаг и проверять его в каждом внешнем цикле и делать break (фактически тот же goto...)
Намного лучше вынести внешний цикл в отдельную фунцию, и во внутреннем делать
return
. (У Вирта return
не было, но в практических реализациях Паскалей его добавили.) Благодаря поддержке вложенных функций, вынесение цикла в отдельную функцию тривиально — в отличие от Си-подобных языков, где нужно вручную передавать весь локальный контекст.Только в классическом C нельзя, уже даже в GNU C можно.
(Не только в классическом Си нельзя, в Java тоже нельзя.)
Во-первых, делает: это разделяет место вызова и место создания лямбды, поэтому место вызова ничего знать про контекст того, что оно вызывает, не должно. Абстракция, типа, все дела.
Во-вторых, явно перечислять тоже нужно не везде. В тех же плюсах вполне можно написать [&]
, и захватится всё по ссылке (что, конечно, может привести к выстрелу в ногу, если лямбда переживёт контекст, но это другая история), или [=]
, и всё захватится по значению (со своими проблемами).
final
-переменную.Но работает. В C++ — просто работает, только & нужно написать. В GNU C даже & не нужен.
А то в Паскале-то оператор goto был издавна, ещё со времен Вирта: берем книгу Йенсен и Вирта «ПАСКАЛЬ Руководство для пользователя» в переводе Подшивалова (М.«Финансы и статистика», 1989) и на стр. 57 видим рис. 4.15, на котором изображена синтаксическая диаграмма пресловутого оператора goto.
Выше правильно пишут — достаточно разбить функцию на две части: до того места с которого нужно продолжить эти рассчеты и после. Сначала вызвать обе функции чтобы выбрать котлы, затем вызвать только вторую чтобы повторить рассчет не с самого начала.
Самый известный пример: с какого бодуна Tомпсону и Ритчи взбрело в голову переставить местами присваивание и равенство? Ну да, я знаю, что это исторически сложилось, но все равно это их не извиняет. Это все равно бездумная халатность безграмотных технарей, сиюминутно взятая с потолка. Или подростковый бунт против авторитетов, иначе это расценивать не получается.
В результате я до сих пор, после четвертьвековой С-практики, регулярно попадаюсь на if (var=1)… Не уверен, что если бы меня учили сразу на С, я бы не попадался: написано же «вар РАВНО единице».
Вирт создал язык, который можно читать, как обычный текст на естественном языке, а С не получится при всем желании.
Тут как с дорожными знаками. Можно вешать таблички на пересечении дорог с читаемыми надписями: «Уступи дорогу» или «Главная дорога», или «Проезд без остановки запрещен», а можно повесить соответствующий знак.
Человеку, который не учил ПДД первый вариант покажется более удобным, для него, в отличии от надписей, все эти разноцветные ромбики, шестиугольники и и треугольники ни о чем не говорят. А вот водителям знаки удобнее читать.
Так и с С получилось, на листингах в книжках код на Паскале выглядит лучше, академичнее, а вот работать с большими объемами кода оказалось удобнее на С, с его более лаконичным синтаксисом (хоть и далеким от идеального).
Там как раз читаемые надписи вместо условных значков.
Это я не к тому, что их система «правильная и удачная», а к тому, что привычки ста миллионов людей — важнее, чем любые внутренние качества системы обозначений. Работать с большими объемами кода на Си кажется удобным потому, что привычно, а не потому, что его синтаксис «правильный и удачный».
Кстати, если бы я такой переход организовывал, то использовал бы метод «варки лягушки». Просто для начала продублировал знаки старого образца, знаками нового, а потом уже, когда водителям эти новые знаки примелькались бы, убрал старые знаки совсем. Переход получился бы безболезненным, постепенным.
Возьмите четыре знака из группы stop and yield — R1-5 (и подзнаки a, b, c). Вы серьёзно будете из машины вчитываться в текст? Вангую, что нет, что вы увидите красную хреновину сверху, изогнутую стрелку чуть ниже, и всё, распознаете знак на базе этих данных.
А знаки типа таких:

вы не рассмотрите, когда они от вас на другой стороне перекрёстка, даже с близким к идеальному зрением (по крайней мере, я в DMV тест на зрение прошёл успешно, а время запрета или разрешения там нихрена не вижу). В итоге им следуют только те, кто там часто ездит и успел рассмотреть, а остальные забивают (и копы забивают на тех, кто забивает).
Или вот на пути из одного хорошего парка знак о том, что поворот направо на красный разрешён только в определённое время (так-то в Техасе делать right on red можно по умолчанию). Я конкретное время даже в очках разглядеть не мог.
50 лет Паскаля