Попробуем представить химию без Периодической системы Менделеева (1869). Сколько же элементов надо было держать в голове, причём в произвольном порядке… (Тогда — 60.)
Для этого достаточно подумать об одном или нескольких сразу языках программирования. Те же чувства, тот же творческий беспорядок.
А теперь мы можем пережить чувства химиков XIX века, когда им предложили все их знания, и немного сверху, в одной Периодической таблице.
Книга «Матрешка Си. Слойная система языка программы» представляет все единицы языка Си как на ладони. Это позволяет упорядочить их, исправить устаревшие сведения и даже уточнить само понятие программы.
Сегодня сведения по программированию нуждаются в систематизации даже больше, чем химические элементы 150 лет назад.
Первая необходимость — преподавание. Менделеев начал создание своей системы, когда встал перед вопросом — с какого элемента начинать читать лекции: O, H, N, He, Au… При этом ему было проще — он учил химии лучших — студентов СПб университета. А программирование уже преподают в школе и скоро начнут в детском саду.
Вторая необходимость — научный подход. С помощью Периодической системы были открыты новые элементы и исправлены сведения о старых. Она помогла в создании модели атома (1911). И так далее.
Третья необходимость — уточнение понятия программы.
Современное программирование одной ногой застряло в 50-х годах XX века. Тогда программы были простые, а машины и машинные языки — сложные, поэтому всё вертелось вокруг машин и языков.
Теперь всё наоборот: программы — сложны и первичны, языки — просты и вторичны. Это называется прикладной подход, который всем вроде бы знаком. Но студентов и разработчиков продолжают убеждать, что все по-прежнему.
Что возвращает нас к первой лекции приват-доцента Менделеева. Что говорить первокурсникам? Где истина? Вот в чём вопрос.
Свой ответ на него предлагает книга «Матрёшка Си. Слойная система языка программы». Причем она обращена не только к студентам, но и к подготовленным программистам, поскольку искать истину и переворачивать мировоззрение должны именно они, то есть мы.
Далее следует краткое содержание книги.
1. Введение
В 1969 году был создан язык Си, который стал основополагающим языком программирования и остается им вот уже 50 лет. Почему это так? В первую очередь, потому что Си — это прикладной язык, который придал программе человечный вид вместо машинного. Это достижение закрепили языки из семейства Си: C++, JavaScript, PHP, Java, C# и другие. Во-вторую очередь, это краткий и красивый язык.
Однако сам язык Си обычно смешивают с машинным ассемблером, тем самым усложняя и искажая его восприятие. Другой крайностью является навязывание в нагрузку к языку некой «философии»: процедурной, объектной, функциональной, компилируемой, интерпретируемой, типизированной и так далее. Это добавляет эмоций, но не помогает лучше описать язык.
Истина находится посередине, причем для языка Си — строго посередине между философским и машинным восприятием.
Язык Си — не самостоятелен, он подчиняется обычной письменной речи, и одновременно — сам управляет языком ассемблер. Это положение описывает Речевая модель программы, согласно которой программа разделена на три подчиненных вида: речевой, кодовый, командный. Язык Си отвечает за второй, кодовый вид.
Определив место языка в программе, можно упорядочить сведения о нём, что делает Слойная система языка программы, представляющая язык Си в духе системы Менделеева — на одной странице.
Система построена с учётом общности прикладных языков, вытекающей из их речевой подчиненности. Один набор единиц Матрёшки Си позволяет описывать и сравнивать разные языки, создав ряд Матрёшек: C++, PHP, JavaScript, C#, MySQL, Python и так далее. Достойно и правильно, что разные языки описываются единицами основополагающего языка.
2. ГЛАВА 1. Речевая модель программы. Понятный Си
В первой главе представлена речевая модель программы, отражающая прикладной подход. Согласно ему, программа имеет три очевидных последовательных вида:
- речевой — прямая речь программиста, решающего задачу,
- кодовый — кодирование решения в математический вид на языке Си (или любом другом)
- и командный — непосредственные машинный команды.
Речевая модель объясняет, почему Си — простой и понятный язык. Си построен по образу и подобию привычной нам человеческой речи.
Первый вид программы — прямая речь программиста. Речь соответствует человеческому
Умозаключения программиста, выраженные речью, преобразуются в кодовый численный вид. Это преобразование следует назвать отражением, поскольку речь и код имеют одну природу (отражение — рождение — род). Это вполне очевидно, если сопоставить речевой (слева) и кодовый (справа) виды программы.
Любопытно, что отражение происходит очень просто — всего двумя родами выражений.
Однако, современное описание языка Си (от 1978 года) не содержит достаточного списка названий ни для описания языка вообще, ни для задачи отражения в частности. Поэтому мы вынуждены заняться творчеством и ввести эти названия.
Выбор слов должен быть точным и ясным. Для этого потребовался особый подход, кратко выражаемый так — строгое использование родного языка. Для англичан это был бы английский, но мы не англичане. Так что используем то, что имеем, и будем стараться говорить по-русски.
Отражение выполняют два рода выражений:
- вычисление (Вч) — отражает изменение свойств предмета. Свойство предмета выражается числом, тогда действие над свойством — это действие над числом — операция.
- подчинение (Пч) — отражает изменение порядка действий. Прообразом Пч является речевое сложноподчиненное предложение, поэтому большинстве видов Пч начинается с подчинительных союзов «если», «иначе», «пока», «для». Другие виды Пч их дополняют.
Кстати, вы можете поверить, что в описании Си нет названия для выражений вычисление — они называются просто «выражения»? После этого уже не удивит отсутствие названия и объединения для рода подчинение, да и вообще скудность по части названий, определений и обобщений. Всё потому, что знаменитый К/Р («Язык Си», Керниган/Ричи, 1978) является не описанием, а руководством по применению языка.
Однако иметь описание языка всё же хотелось бы. Поэтому его предлагает Слойная система языка программы.
3. ГЛАВА 2. Слойная система. Краткий Си
Любое описание должно быть точным и предельно кратким. В случае языка программы лобовое описание затруднительно.
Вот у нас есть программа. Она состоит из модулей. Модули состоят из подпрограмм и подборок (structure). Подпрограммы состоят из отдельных выражений: объявлений, вычислений, подчинений. Подчинений — целых десять видов. Подчинения подключают подуровни и подпрограммы. Объявлений тоже несколько. Впрочем, объявления включаются не только в подпрограммы и подуровни, но и в модули и в подборки. И большинство выражений состоит из слов, которые описывать настолько сложно, так что обычно их просто дают двумя списками — исходные и производные слова, с которыми предстоит знакомиться на протяжении всего изучения и применения языка. Добавим к этому знаки препинания и ещё ряд выражений.
В таком изложении непросто понять кто на ком стоял.
Прямой иерархический подход описания языка будет чрезмерно сложен. Поиск окольных путей приводит к описанию языка на основе его речевой природы и командной стороны. Таким образом родилась Слойная система, частично совпадающая с Периодической системой Менделеева, которая тоже является слойной. Как выяснилось через 42 года после её издания (1869), периодичность системы связана с электронными слоями (1911, модель атома Бора-Резерфорда). Также Слойную и Периодическую системы роднит табличное размещение всех единиц на одной странице.
Описание единиц языка получается кратким — всего 10 родов выражений и 8 родов других единиц, а также содержательным и наглядным. Хотя и непривычным для первого знакомства.
Единицы языка разделены на 6 уровней:
- отряды — строки таблицы
- отделы — особые группы родов (части первой строки)
- рода — ячейки (главный уровень деления)
- надвиды — разделители видов (редкий уровень)
- виды — формулы единиц внизу ячейки или отдельно
- образцы — сами единицы (только для слов)
Образцы слов описывает словарь — отдельная подсистема, составленная из тех же шести уровней.
Речевая составляющая языка Си вполне очевидна, хотя всё равно заслуживает описания. А вот командная часть языка как раз связана с управлением компиляцией, в ходе которой создаётся третий вид программы — командный. Здесь мы подходим к самой захватывающей стороне языка Си — красоте.
4. ПОСЛЕДУЮЩИЕ ГЛАВЫ. Красивый Си
Язык Си лежит в основе современного программирования. Почему? Во-первых, в силу наибольшего соответствия речи. Во-вторых, потому что красиво обошёл ограничения машинной обработки чисел.
Что именно предложил Си? Образ и слой.
Слово «образ» — это перевод английского слова «type», которое происходит от греческого «прототип» — «прообраз». В русском языке слово «тип» не передаёт краеугольность выражаемого понятия, к тому же смешивается со служебным значением «вид».
Изначально образ решал чисто машинную задачу вычисления, а потом стал взлётной полосой для рождения объектных языков.
Слой сразу решал несколько задач — и машинных, и прикладных. Поэтому рассмотрение начнётся с однозадачного образа и перейдёт к многозадачному слою.
Одна из неприятных черт исторического программирования состоит в том, что большинство понятий, включая основные, даются без определений. «Язык программирования (имя рек) имеет целый и плавающий тип чисел…» — и почесали дальше. Что такое «тип» (образ) — определять необязательно, потому что авторы сами это не до конца понимают и замнут «для ясности». Если их припрут к стенке, то дадут размытое и бесполезное определение. Очень помогает спрятаться за иностранными словами: для русских авторов — за английскими (тип), для англичан — за французскими (subroutine), греческими (полиморфизм), латинскими (инкапсуляция) или их сочетаниями (полиморфизм ad-hoc).
Но это не наша судьба. Наш выбор — определения с поднятым забралом на чистом русском языке.
Образ
Образ — это прообразующее имя величины, определяющее 1) собственные свойства величины и 2) подбор операций к величине.
Слову «тип» (вид) соответствует первая часть определения: «собственные свойства величины». Но главный смысл образа — во второй части: «подбор операций к величинам».
Отправная точка для введения образа в языке Си — обычное вычисление, например, операция сложения.
Бумажная математика, записываемая от руки или печатаемая, не делает особого различия между видами чисел, обычно полагая их вещественными. Поэтому операции их обработки однозначны.
Машинная математика строго разделяет числа на целые и дробные. Разные виды чисел по-разному хранятся в памяти и обрабатываются разными командами процессора. Например, команды сложения целых и дробных чисел — это две разных команды, соответствующие двум разным узлам процессора. Зато команда сложения целого и дробного аргументов отсутствует.
Прикладная математика, то есть язык Си, разделяет виды чисел, но объединяет операции: сложение для целых и/или дробных чисел записывается одним знаком действия.
Чёткое определение понятия образ позволяет определенно говорить о двух других понятиях: величина и операция.
Величина и операция
Величина — обрабатываемое число.
Операция — обработка значений исходных величин (аргументов) для получения итогового числа (итога).
Величина и операция взаимосвязаны. Каждая операция является величиной, так как имеет числовой итог. А каждая величина является итогом пересылки значения в регистр процессора/из процессора, то есть — итогом операции. Несмотря на эту взаимосвязь, всё-таки главным является возможность их раздельного описания, пускай и с повторением одного слова в разных отделах словаря, что и происходит в ма3.
Машинный подход делил все числа, используемые программистом, на команды и данные. Раньше и те, и другие были именно числами, например, команды писались числовыми кодами. Однако в прикладных языках команды перестали быть числами и стали словами и знаками действий. Числами остались только «данные», но продолжать называть их так нелепо, потому что при переходе от машинной к математической точке зрения числа — это величины, которые делятся исходные (данные) и итоговыми (искомые). «Неизвестное данное» — это будет звучать глупо.
Команды тоже разделились на два вида действий: математические и служебные. Математические действия — операции. К служебным обратимся позже.
В языки Си привычные бумажные и машинные однозначные, или единичные, математические операции почти поголовно становятся множественными.
Множественные операции – несколько одноименных операций с разными образами аргументов и разными, близкими по смыслу, действиями.
Целым аргументам соответствует целая операция, дробным — дробная. Эта разница особенно наглядна при операции деления, когда выражение 1/2 даёт итог 0, а не 0,5. Такая запись не соответствует правилам бумажной математики, но язык Си и не стремится их соблюдать (в отличии от Фортрана) — он играет по своим прикладным правилам.
В случае смешения целых и дробных чисел включается единственно правильное приведение значений аргументов — подборочное преобразование значения из одного образа в другой. Действительно, при сложении целого и дробного числа итог — дробный, поэтому образ операции подбирает операцию преобразования целого аргумента в дробное значение.
Ряд операций остаются не множественными, а единичными. Такие операции определены только для одного вида аргументов: остаток деления — целые аргументы, укладка (побитовые операции) — натуральные целые. Ма3 указывает множественность операций знаками (#^) с указанием образов, для которых операция определена. Это важное, но пропускаемое раньше свойство каждой операции.
Все функции являются произвольными единичными операциями. Исключение составляют операторы — бесскобочные функции, встроенные в язык (исходные операции).
Содействие
Содействие — сопутствующее операции действие.
Если рассматривать операцию как основное действие, то можно выделить два сопутствующих, которые обеспечивают операцию и отличаются от неё. Это 1) управление переменной и 2) подчинение. Такое действие названо содействием.
Здесь надо отвлечься и отдельно сказать про русские переводы учебников по программированию. В тексте К/Р для записи действий было введено новое слово statement (выражение), которое сделало попытку разделить понятия машинной команды на разные действия: 1) операцию, 2) объявление и 3) подчинение (названное «управляющими конструкциями»). Эту попытку похоронили русские переводчики, заменив «выражение» словом «оператор», которое:
- стало синонимом машинного слова «команда»,
- оказалось синонимом словосочетания «знак действия»,
- а также получало неограниченное количество дополнительных значений. То есть превратилось в подобие английского артикля «ээээ…».
Рассмотрим сопутствующие действия, или содействия.
Управление переменной
Управление переменной (УП) — создание/удаление ячеек переменной.
УП происходит в неявном виде при объявлении переменной, которое и так уже пишется по другому поводу — для указания образа величины. Явно управляются только один вид добавочных переменных с помощью функций malloc() и free().
Надо отметить, что неявные действия удобнее для написания, так как вообще не требует ничего писать, но сложнее для понимания — их сложнее учесть и истолковать.
Подчинение
Подчинение — подключение/отключение слойных разделов.
Язык Си предложил отличный от ассемблера, прикладной способ управления порядком действий — подчинение. Оно отражает и развивает речевое сложноподчиненное предложение с явным разделением на главную часть (предложение подчинение) и придаточную часть (разделы подуровень/подпрограмма).
И объявление, и подчинение полностью построены на понятии слой.
Слой
Слой — это ограниченный одноуровневый избирательный набор выражений.
Слой явно и неявно взял на себя выполнение сразу же нескольких задач:
- упорядочение программы,
- ограничение видимости имён (неявно),
- управление переменными (ячейками памяти) (неявно),
- определение придаточных разделов для подчинения,
- определения функций и подборок и другие.
В машинных языках не было понятия слой, поэтому оно не появилось и в К/Р, а уж если чего не было там — то вводить это в последующих книгах было бы ересью и вольнодумством. Поэтому понятие слой не появилось вообще, хотя крайне полезно и вполне очевидно.
Без слоя невозможно коротко и ясно объяснить многие действия и правила программы. Например, почему простой как три копейки goto — плохой, а мудрёный while — хороший. Можно только бессильно ругаться, как делал Дейкстра («квалификация программистов — функция, обратно зависящая от частоты появления операторов goto в их программах». Короче, только козлы используют goto. Уровень обоснования — Бог.) Правда, это не так страшно, если ваши книги вообще ничего не обязаны объяснять, но, как мы уже сказали, это не наша судьба.
Кстати, можно предположить, что Ден Ричи оставил goto именно как ключ для поиска некого неназванного понятия, потому что никакой необходимости или красоты в выражении goto не было. Зато была нужда простого и понятного объяснения новых принципов языка, которые сам Ричи давать не хотел, и которые как раз основаны на понятии слой.
Отклонение
Отклонение — изменение обычных свойств нового имени.
Самое важное отклонение как раз связано со слойными свойствами программы, и описывается одним словом «static», имеющим разные значение в каждом из видов слоя.
5. ПОСЛЕДНЯЯ ГЛАВА. Общность прикладных языков
Прикладные языки — это образные языки (имеющие образ, «типизированные»). Они основаны на явном или неявном использовании образа. Причем здесь опять проявляется противоречие: явный образ — более понятный, но менее удобный, и наоборот.
(Разметку таблицы пока не подвезли, поэтому таблица дана картинкой.)
После Си развитие прикладных языков пошло по пути увеличения их образности. Наиболее важным для понимания высокообразности является прямой потомок Си — язык С++. Он развивает идею произвольного подбора операций к величинам и воплощает её на основе си-шного выражения подборка, которое получает новые название — объект. Однако Си++ не является таким же кратким и выразительным, как Си, в силу перегрузки новых видов подборки и связанных с ними правил. К слову, поговорим о «перегрузке».
Перегрузка и полиморфизм
Слово «перегрузка» (overload) — устаревший термин машинного подхода, обозначающий создание множественных операций.
Машинных (системных) программистов множественность операций вполне могла раздражать: «Что означает этот знак (+): сложение целых чисел, сложение дробных чисел или вообще смещение?! В наше время так не писали!» Отсюда отрицательный оттенок выбранного слова («перебор», «надоело»). Для прикладного программиста множественные операции — это краеугольный камень, главное достижение и наследие языка Си, настолько естественные, что часто не осознаваемые.
В языке Си++ множественность распространилась не только на исходные операции, но и на функции — как отдельные, так и объединенные в классы — методы. Вместе с множественными методами появилась возможность их переопределения в расширенных классах, которая была туманно названа «полиморфизмом». Сочетание полиморфизма и перегрузки дало взрывчатую смесь, которая разлетелась на два полиморфизма: «истинный» и «ad-hoc». Разобраться в этом можно только вопреки присвоенным названиям. Иностранными названиями вымощена дорога в ad.
Объявление вида «перегрузка» лучше выразить словом дообъявление — добавляющее объявление одноименной функции с аргументами другого образа.
Объявление вида «полиморфизм» лучше назвать словом переобъявление — перекрывающее объявление в новом расширяющем слое одноименной функции с аргументами того же образа.
Тогда будет легко разобраться, что одноименные методы разных образов (аргументов) — дообъявляются, а одного образа — переобъявляются.
Русские слова решают.
Взлётная полоса
Рассмотрение понятий высоко-образных языков подтверждает важность чёткого определения основополагающих понятий. С правильно описанным Си изучение высоко-образных языков будет лёгким и приятным.
Особенно это важно для неявных высоко-образных языков (PHP, JavaScript). Для них важность объектов (составных образов) становится ещё выше, чем в С++, но само понятие образа становится неявным и трудноуловимым. С точки зрения удобства они стали проще, а вот с точки зрения понимания — сложнее.
Поэтому начинать изучение языков программирования следует с языка Си и двигаться дальше в порядке появления языков семейства Си.
То же самое касается описания языков. Разные языки имеют совпадающий, или меньший набор родов единиц, чем язык Си. Число видов и образцов может отличаться в обе стороны: у Си++ видов больше, чем у Си, у ЯваСкрипт — меньше.
Особого упоминания заслуживает язык MySQL. Казалось бы — ничего общего, но он прекрасно описывается Матрёшкой, и знакомство с ним становится быстрее и проще. Что важно, учитывая его значение для веба — столовой дороги современного программирования. А где MySQL, там и прочие SQL. Ну, и всякие фортраны-паскали-питоны тоже описываются Матрёшкой, как только руки дойдут.
Так что, нас ждут великие дела — прикладное описание языка Си и единое описание следующих за ним языков. «Наши цели ясны, задачи определены. За работу, товарищи! (Бурные, продолжительные рукоплескания, переходящие в овацию. Все встают.)»
Ваши мнения будут выслушаны с большим вниманием, ваша помощь в создании сайта матрёшек будет принята с огромной благодарностью. Более полные сведения о книге лежат на сайте, хитро спрятанном в Матрёшке Си.
Автор: mikkoljcov