Страница произведения
Войти
Зарегистрироваться
Страница произведения

Фокал - часть 3 (пишется)


Автор:
Опубликован:
24.05.2026 — 24.05.2026
Читателей:
1
Аннотация:
Типа продолжение к "Фокал снаружи и внутри"
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава
 
 

управление с помощью оператора вызова подпрограмм Do (а не Go или If, которые

просто передают управление строке с указанным в них номером) группа, по

достижении её конца, вернёт управление в точку вызова (следующему после Do

оператору) даже в том случае, если там в ней небыло оператора возврата из

подрограммы Ret.

Заметим, что "естественной подпрограммой" является так же и каждая

отдельная строка, и тело цикла — остаток строки после оператора For.

Чтобы вызвать подпрограмму-строку, адрес перехода в операторе Do должен

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

остальных операторах, имеющих дело с программными строчками. Если же надо

указать всю программу целиком, это делается с помощью ключевого слова Ales

(что собственно и значит "всё".) И, кстати: везде, где по смыслу нужен номер

строки, может быть вовсе не константа (как в большинстве реализаций всё того

же Бейсика), а как и везде, где по смыслу нужно число — выражение произвольной

сложности. Получается в том числе "вычисляемый переход"...

Пользуясь тем, что каждая строка — тоже естественная подпрограмма, можно

при отладке запускать строчки поштучно и после каждой смотреть что она сделала.

Если же в ней есть передача управления, то чтобы это отслеживать, есть режим

"трассировки" — включается (и выключается) оператором ? (вопросительный знак).

При которой выполнение оператора сопровождается выдачей его на терминал.

Оператор цикла сконструирован так, чтобы помещался в одной (в том числе

"нулевой") строке. Но ежели остатка строки под тело цикла мало — его можно

продолжить в другой строке, передав туда управление оператором Go. После её

завершения, управление опять вернётся заголовку цикла. (Ну или выделить под это

целую группу, передав туда управление оператором Do.) А вот досрочно выйти из

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

надо присвоить параметру цикла значение больше конечного. Или сразу

конструировать цикл по-другому: из операторов условной и безусловной передачи

управления. (Ну или применить "структурный переход" — вещь из второй части...)

Еще одно важное различие с Бейсиком: простая переменная и там и там

заводится одинаково: автоматически — при первом её упоминании. А вот

переменные с индексами (они же элементы массивов) — уже нет: в Бейсике массив

существует весь сразу целиком и для этого должен быть объявлен заранее

оператором DIM. При чем индексы в нём не как у всех нормальных людей — с нуля,

а почему-то с единицы! (Надо ли это так понимать, что рассчитано на обывателя?)

А вот в Фокале ничего и никогда заранее не объявляется. Переменная, что

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

первого присваивания ей чего либо. Это не эффективно, за то удобно. И сам собою

отпадает вопрос о границах массива. Но это таки вызывает некоторые

дополнительные сложности: к одной и той же переменной можно обратиться с

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

гарантируется, что нулевое значение индекса эквивалентно его отсутствию. Так

что и Y(0,0) и Y(0) это одна и та же переменная Y.

((Потому что сделано до ужаса просто: под имя и индекс — по два байта.

(Маловато? Потом побольше сделаем...) И как туда попали числа — нигде не

фиксируется! Так что индексы — не просто целые, а если число большое, оно еще

и обрезается... Была еще идея: сделать не только Y[i] или Y[i,j] но и Y.abcdef

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

вот пока не...

Да, это нам не Питон... (Или например Луа.) Где массив это набор пар:

ключ-значение. При чем и то и другое могут быть какого угодно типа -

полиморфизм, однако! Так что у них там даже переменных как таковых нет. Вместо

них — элементы массива: в качестве ключа — строка в роли имени, а значение

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

код — подпрограмма получается... Но неэффективно. Так что настоящие массивы с

пронумерованными элементами у них там вроде бы тоже есть... Но Питон да и Луа

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

реализации. А Фокал — первого. И очень-очень-очень простой.))

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

разом — оператором Eraze без аргументов. (Или им же с ключевым словом Ales, но

тогда уничтожается вообще всё...)

И наконец сами ключевые слова: в Фокале все они подобраны на разные буквы

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

(Остальные всё равно игнорируются.) Чем (вместе с отсутствием "шумовых" слов) и

достигается лаконичность Фокала: если в Бейсике в строке помещается максимум

три-четыре оператора, то в Фокале — пять-десять. ("Шумовые" слова нужны чтобы

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

примитивного...)

Если в операторе есть второе ключевое слово (вот это самое Ales например),

то к нему это тоже относится. А ежели в операторе может быть как ключевое

слово, так и число, вернее вычисляющее его выражение, которое тоже может

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

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

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

более чем достаточно. И тоже приучает к лаконичности. Для сравнения: в Бейсике

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

Имена встроенных функций опознаются по первым уникальным буквам и все

обязательно называются на букву Ф. А вот переменные на букву Ф называть нельзя,

увы. (Можно, но использовать её потом не получится.) То есть не sin, tg, sqrt,

а FSIn, FTG, FSQrt... А чтобы не запоминать, как правильно: например FTAN или

FTG — сделано чтобы и так и так.

Символы в Фокале делятся на три категории: буквы, цифры и разделители.

При чем буквой считается всё что не цифра и не разделитель, которых Фокал

знает "в лицо и по фамилии". В том числе буквами считаются: # $ ~_ @ & | :

Но ведь буквы еще бывают заглавные и строчные, а так же русские и

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

именах переменных все они различались, а в ключевых словах и именах функций

были эквивалентны.

А строку, начинающуюся вот с такой якобы-буквы, повелел считать

комментарием. Наряду с начинающейся с оператора Coment (вернее с буквы Ц).

Потому что в UNIX`е есть такая полезная традиция: распознавать тип файла не по

"расширению" (часть имени после точки), а по "сигнатуре". Каковая — первые два

(четыре, или нынче уже бог весть сколько) символов самого этого файла. В том

числе, в случае если файл — выполняемый, пользователю, какой на самом деле тип

этого файла и как его будет выполнять UNIX — без разницы. А вот для самого

UNIX`а... Если файл не в машинных кодах, а текстовый (а уж коли он выполняемый,

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

строка должна начинаться с символов # ! и содержать командную строку для

запуска евонного интерпретатора. А для самого этого интерпретатора — выглядеть

как комментарий. Вот и. А остальные такие символы — за компанию.

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

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

какими-то другими символами-разделителями. Впрочем, в этом случае — если

границы слов Фокалу очевидны, то и запятые без надобности. (Что известно как

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

и пропуск элемента. Ну и в выражениях правила более строгие...


* * *

Таким образом в памяти фокаловского интерпретатора (а значит и в

распоряжении пользователя) есть два вида ресурсов: программные строки и

переменные. Переменная хранит одно число, любое, а программная строка — тоже

любую строку, совсем не обязательно "программную": никто же не проверяет этого!

Только когда попытаются это выполнить...

Далее: программные строки различаются номерами, а это числа, с которыми

Фокал и работает. А вот переменные различаются по именам, а это строки (пусть

пока и всего из двух символов). Симметрия проглядывается? Вот только со

строками Фокал работать не умеет. Или (пользуясь тем, что строка — это

последовательность символов, а символ обозначается коротеньким целым числом)

таки умеет, но очень-очень-очень ограниченно... (С помощью спецфункции

ввода/вывода FCHR.)

Научить Фокал работать со строками было бы очень желательно: пригодилось бы

для множества практических целей... Вот только действия со строками совсем не

такие как с числами...

Первый подход к снаряду (а для Бейсика и единственный) — "полиморфизм".

(Оно же "динамическая типизация".) Вот те самые типы данных, от которых я выше

шарахнулся, как черт от ладана. Однако в Бейсике именно так и сделали,

сотворив из маленького и простого языка (хотя и малость аляповатого и не

больно то хорошо продуманного) сложного и громоздкого монстра...

Полиморфизм это когда одна и та же переменная может принимать значения

разных типов. И одни и те же операции применимы к ним ко всем. (Ну может быть

с некоторыми ограничениями?...)

В общем я тоже было решил хранить строки, с которыми собираемся работать,

в тех же самых переменных что и числа. Проигнорировав (или скорее просто не

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

все и во всех алгоритмических языках... Ну вот и я туда же: придумал, как

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

собственно и начался проект модернизации языка "Фокал-3", числа в котором

должны были быть не простыми, а гиперкомплексными. Так до сих пор и не

реализованный. ("Три" потому что Фокал-2 уже был. И было там много чего,

включая "псевдонимы" — чтобы можно было давать подпрограммам "говорящие" имена,

подгружать код, не занимающий пространства номеров строк и доступный вот через

такое имя; переименовывать встроенные функции, сняв с имён переменных "табу"

на букву Ф, а так же передавать подпрограмме параметры "по ссылке" а не только

"по значению"... Вот только числа там были обычные — с плавающей запятой...)

Но перед этим, в качестве тренировки (да и кое-для каких практических

целей) решил сперва немножко развлечься — сделать слегка "доведенную до ума"

реализацию традиционного Фокала (назвав это Фокал-1А). Вот до сих пор и

развлекаюсь...

Идея там была вот какая: строка + строка это их сцепление ("конкатенация");

строка * число, равно как и в обратном порядке (потому как от перестановки

сомножителей произведение не меняется) — это размножение строки, дублирование

указанное числом количество раз. При чем число может быть и дробное. (И тогда

порядок операндов уже имеет значение...) А если отрицательное, то строка

инвертируется. Унарный минус — чисто инверсия строки (т.е. буковки в обратном

порядке), а унарный плюс — получение длины (т.е. результат — число). (А для

комплексного числа унарный плюс это получение комплексно-сопряженного.)

Соответстенно деление строки на число это её разрезание. Вернее — взять часть

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

было делить нельзя. В обратном порядке (т.е. число / строка) можно — результат

будет ноль или указанное числом количество символов. Если число отрицательное,

то с конца.

Вычитание строк это их сравнение: поиск позиции, с которой одна строка

входит в другую: числа в операторе If сравниваются именно так! Если вторая

строка "больше" — результат будет отрицательный, а если ни одна из них не

часть другой — то ноль.

Вычитание значения из самого себя это еще и возможность определить его тип:

для числа получится ноль, для строки — единица (она же сама в себя входит с

первой позиции!), а вот для "пустого" значения результат будет -1.

Это самое пустое значение при любых других операциях даёт ошибку, а содержится

в неинициализированной переменной, в том числе локальной, если был пропущен

параметр соответствующий её позиции.

Сложение и вычитание строки и числа я было хотел запретить — сделать чтобы

они давали ошибку, но если трактовать число как код символа и соответственно

числовое значение как односимвольную строку... Встроенная в Фокал функция FCHr

делает именно так, значит можно и тут.

Операция ^ и для чисел самая трудозатратная, так пусть такой же будет и

для строк: "полукорреляция" — сопоставление двух строк на предмет поиска общей

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

А "полу" потому, что неполная. А то полная корреляция строки с собою найдёт её

всю целиком. (А то мы не знаем, что совпадает сама с собою!) Нам вообще-то надо

повторяющийся фрагмент: (S/2)^S (здесь мы в первом операнде отрезали от S

первый символ — теперь не совпадёт). А коли так уж нужна полная — извольте:

fmax(S1^S2,S2^S1).

Ну что можно сказать? Всё вроде бы логично, разве что, с одной стороны,

слишком много внимания не больно-то реально нужным реверсу строки и её

размножению (но это диктуют имеющиеся у нас операции), а с другой — всего этого

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

Например буковки бывают заглавные и строчные, а так же русские и латинские.

При сравнении двух строк (в том числе на полное равенство: (S1-S2)*(S2-S1)) в

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

(Ввести некие внутренние признаки эквивалентности, устанавливать и сбрасывать

их некоторой спецфункцией? Некрасиво получается...) И это далеко не

единственное...

Вон в Бейсике ввели для работы со строками кучу функций, "поручив"

встроенным операциям только самое очевидное, типа конкатенации. Нам такого

щастья и даром не надь... Сложно, громоздко и необозримо даже с помощью

встроенной справочной системы.

В общем оставались у нас две "неокученные" операции: умножение и деление

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

строка, а специальная — составленная по некоторым правилам. Строка1 / строка2

это будет сопоставление с шаблоном, а строка1 * строка3 — "перекодировка".

Здесь строка3 это последовательность ПАР шаблонов: включающих анализирующий

1234 ... 121314
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава



Иные расы и виды существ 11 списков
Ангелы (Произведений: 91)
Оборотни (Произведений: 181)
Орки, гоблины, гномы, назгулы, тролли (Произведений: 41)
Эльфы, эльфы-полукровки, дроу (Произведений: 230)
Привидения, призраки, полтергейсты, духи (Произведений: 74)
Боги, полубоги, божественные сущности (Произведений: 165)
Вампиры (Произведений: 241)
Демоны (Произведений: 265)
Драконы (Произведений: 164)
Особенная раса, вид (созданные автором) (Произведений: 122)
Редкие расы (но не авторские) (Произведений: 107)
Профессии, занятия, стили жизни 8 списков
Внутренний мир человека. Мысли и жизнь 4 списка
Миры фэнтези и фантастики: каноны, апокрифы, смешение жанров 7 списков
О взаимоотношениях 7 списков
Герои 13 списков
Земля 6 списков
Альтернативная история (Произведений: 213)
Аномальные зоны (Произведений: 73)
Городские истории (Произведений: 306)
Исторические фантазии (Произведений: 98)
Постапокалиптика (Произведений: 104)
Стилизации и этнические мотивы (Произведений: 130)
Попадалово 5 списков
Противостояние 9 списков
О чувствах 3 списка
Следующее поколение 4 списка
Детское фэнтези (Произведений: 39)
Для самых маленьких (Произведений: 34)
О животных (Произведений: 48)
Поучительные сказки, притчи (Произведений: 82)
Закрыть
Закрыть
Закрыть
↑ Вверх