Второй день читаю в свободное время про язык программирования Форт. Даже не понимаю, почему меня он так заинтересовал. Может это просто желание размять мозги чем-то совершенно новым.
Интересно, что первой моей собственной, не библиотечной, книгой по программированию был русский перевод книги “Язык Форт и его реализации”. Купил её на книжном развале этак в 1993 году. Тогда у меня небыло доступа к компьютеру, тем более с фортом. Книгу я читал внимательно, но очень многое не понимал.
Форт - интересный язык, это промежуточное звено между языками высокого и низкого уровня. В книгах, конечно, пишут, что это язык высокого уровня. Но это по меркам 1970х-80х годов. По факту, он очень простой и допускает ассемблерные вставки. Т.к. новые команды Форт - “слова” становятся неотъемлемой частью языка - в нём можно создать сложные, высокоуровневые конструкции. Но базовый синтаксис останется ограничением языка. Кроме того, этот язык - компилируемый, но команды можно исполнять в интерактивном режиме.
Впрочем, с компилируемостью языка Форт вопрос сложный. Есть некоторая градация языков от интерпретируемых до компилируемых. Для чистых интерпретируемых языков интерпретатор читает исходный файл, делает его синтаксический разбор и исполняет его. И это происходит при каждом вызове программы. Дальше находятся языки, которые переводятся в некоторый промежуточный байт-код. Это может происходить при каждом запуске программы или однократно. Классический пример таких языков - Ява. Байт-код исполняется быстрее, так как не нужно тратить ресурсов на синтаксический разбор и можно выполнять ряд операций заранее, до того, как код начнёт исполняться. Форт преобразуются в так называемый “шитый код”. Этот код скомпилирован “в большей степени”, чем байт-код. Фактически, он разбит на подпрограммы, которые уже реализованы на машинном коде. Но конкретные адреса переменных, подпрограмм и некоторые другие вещи ещё не подставлены в программу на шитом коде и появляются в ходе исполнения. Подробнее описано в Википедии. Причем есть реализации с полной компиляцией в машинный код.
Так что Форт так же быстр или почти так же быстр, как компилируемые языки. Это было важно в 1970е-80е, но и тогда не дало Форту значительного преимущества. В конце концов, для кода критичного по времени исполнения есть C, C++ и даже Паскаль.
Наконец, у Форта практически отсутствует синтаксис, ноль калорий “синтаксического сахара”. Форт просто читает входной поток. Если это слово - команда языка, то нет разницы, это слово исходного набора команд Форта или определённое в программе. Язык программирования просто выполняет эту команду. Если встречает число или строку - кладёт их в стек, это хранилище временных данных Форт. Если то, что встречено ни число, ни строка, ни заранее определённая команда - это ошибка.
Определение новых слов - элементарная синтаксическая конструкция:
: слово 3 2 + ;
Как такового синтаксиса нет. Двоеточие показывает на определение нового слова. Далее следует название определяемого слова, набор инструкций, которые выполняет это слово и точка с запятой, завершающая конструкцию. Это всё, что нужно знать о синтаксисе языка.
Из-за такой простоты у Форта очень простое ядро, основа языка. Его можно реализовать и на 8-разряных процессорах и на современных машинах. Это было огромным преимуществом, когда был натуральный зоопарк процессорных архитектур. Сейчас реально применяется несколько процессорных архитектур, так что и это давно не преимущество.
Про недостатки Форта пишут меньше. Но один из них - самый очевидный. Форт - “write only language”. Он не самодокументируемый. Плюс, он вообще никак не ограничивает программиста. Там, где даже С выдал бы ошибку компиляции, Форт всё исполнит. Выдаст ошибку, только если встретит незнакомое слово или исчерпает стек. Если программист забыл положить на стек какие-то данные, но в нём уже есть другие, положенные туда ранее, данные - Форт без вопросов использует “не свои данные”. Так что ошибка потом может появится не в том слове, где не хватает параметров, а в том, где стек опустошился. Так что обнаружить ошибку может быть непросто. Учебники по Форту рекомендуют тестировать каждое слово отдельно и это разумно.
Сейчас Форт - полнейшая экзотика и это меня привлекает. Просто удивительно, как меня привлекают старые гаджеты, системы и языки.
То, что пишут про Форт можно найти и в учебниках по Лиспу. Тут и декомпозиция задач до лёгких в понимании, коротких слов/функций. Модульный подход и некоторое презрение к объектно-ориентированным языкам. Это обосновывается рядом доводов. Например, бессмысленно прятать всю внутреннюю механику работы программы от внешнего мира. Это не даёт значимых преимуществ, так что инкапсуляция не нужна. Классы ООП имеют тенденцию постоянно разрастаться и устанавливать сложные взаимосвязи друг с другом. Например, одному классу нужен один лишь метод из другого класса. Но чтобы воспользоваться им - нужно создать целый новый экземпляр этого другого класса. А он может также зависеть от других классов и получится, что для выполнения элементарного действия будет “работать” целый комплекс из разных классов. Из-за этого исполняемые файлы получаются неоправданно большие и страдает эффективность кода. Этого можно было бы избежать, используя модульный подход.
В качестве примера форт-программы в учебнике приводится программа для преобразования арабских чисел в римские. Честно говоря, аналогичная программа на С, использовавшая рекурсию, казалась мне куда более понятной и эффективной. Прочитать уже написанную программу тоже непросто. Конечно, это дело привычки.
В старых реализациях Форта была забавная особенность, код мерился “экранами” - блоками размером в 1 килобайт, это столько кода, сколько умещается на экране монитора. Такие экраны записывались на ленту или другой носитель по одному в файле. Их можно было подгружать по необходимости. Экран состоял преимущественно из пробелов, так как записывалось, фактически, всё содержимое экрана монитора. Наверное, записывался просто дамп видеопамяти монитора целиком. Как таковой файловой системы такой подход не предполагал. Перевод строки для Форта - не элемент синтаксиса, а знак того, что пора исполнять введённый код. Определение слов может не иметь символов перевода строки вообще, сразу за ; предыдущего слова можно начинать : определения нового слова. В современных реализациях Форт, конечно, такого уже нет.