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

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


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

элементов массива — с нуля.)

1.1 T "вводите числа, 0 — последнее"!; S N=-1;

1.2 A y; D 2; If(y) 1.2, 1.3, 1.2; C помещение в массив вынесли в группу 2

1.3 If(N) 1.4,1.4; X FSBr(3,0); T !"Всё."!; Q

1.4 t "Чего же сразу-то ноль? Вот даже выдавать нечего..."!; Q

C не только x[]=y но и ссылки на поддеревья устанавливаем...

2.1 S N=N+1; S x[N]=y; S m[N]=-1; S b[N]=-1; S i=0; If(-N)2.2; R;

2.2 S z=x[i]-y; S j=b[i]; I(z) 2.3; S j=m[i]

C то же самое на Си: j = (y>=x[i]) ? b[i] : m[i]; по-моему куда понятней!

2.3 If(j) 2.4; S i=j; G 2.2; C спуск по дереву линейный — можно без рекурсии

2.4 If(z) 2.5; S m[i]=N; R; C очередное число повесим как "листик"

2.5 S b[i]=N; R;

C Вот он — обход дерева с помощью рекурсии. Почти в одну строчку...

3.1 If(&) 3.2; X FSBr(3,m[&]); T x[&]; X FSBr(3,b[&]);

3.2 R

Надо ли тут чего разжевывать, или и так всё понятно? Ну разве что — что

квадратные скобки при обращении к массиву — выпендрёж чистой воды: это не Си,

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

такой задачки — тоже выпендрёж. А вот его обход (уж коли у нас дерево) — нет:

он возможен только рекурсией. (Но штука таки дорогая — стэк жрет неумеренно...)

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

факториала: произведения всех чисел от 1 до N (что обычно обозначается как N!)

потому что видите-ли: (N+1)! = (N+1)*N! Они что — опухли?! Здесь дерево

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

обычного цикла. Однако вместо того, чтобы написать:

s X=1; f i=2,N,1; s X=X*i; C и всё: X==N! — осталось только напечатать

t N,"! = ",X

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

4.1 if(1-&)4.2; x 1; r

4.2 x &*fsbr(4,&-1); r

t N,"! = ",fsbr(4,N)

Как ни странно, это будет работать, даже если переменная & не локальная.

А вот если бы написали не &*fsbr(...) а fsbr(...)*& — вот тогда нет! Понятно,

почему?

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

момент первого присваивания. Но уничтожаются при выходе из подпрограммы. При

этом становится доступным предыдущий комплект, если он был. Кроме того, если

данная локальная переменная не существует — это не ошибка, как для глобальной:

она ищется в предыдущих комплектах, а если так и не найдена — то будет ноль.


* * *

И вот теперь, когда с "каноном" — "базовым", исходным Фокалом, надеюсь,

всё более-менее понятно, краткое содержание первой части сего опуса.

(Напоминаю: опус это сам Фокал-1А.)

Всё вышеописанное я либо просто воспроизвёл (сохранив и то, что обычно

считают недостатками: всего два значащих символа в имени переменной и "вето"

на букву Ф), либо немножко модернизировал. Прежде всего уточнил и дополнил

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

системой ОС. Ну и так, кое-что по-мелочи — разные удобства и красивости:

— оператор Help для получения справок; просмотрщик к нему (аналог

UNIX`овского more) чтобы их с удобством просматривать; "экранный" редактор

командной строки со всяческими прибамбасами, чтобы с удобствами её набирать.

Или править с помощью оператора Modify. Работающего поэтому только и

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

вывода.

— вот эти самые по-настоящему локальные переменные — как позиционные

параметры при вызове подпрограммы с помощью FSUbr, так и сами по себе. И плюс

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

встроенных функций (де лишние будут просто игнорироваться). А так же

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

расширения функциональности без увеличения количества этих самых встроенных

функций. Например FSQrt(X) — просто квадратный корень, а FSQrt(X,N) — корень

N-ой степени; FLOg(X) — логарифм натуральный, а FLOg(X,N) — по основанию N.

Или суровая и опасная функция FX( действие, адрес, параметр ) производящая

действия с управляющими регистрами внешних устройств (каковых действий всего

три: чтение, запись и побитовое-И — например на предмет проверки признака

готовности), без первого аргумента: FX( , А, Б) не лезет ни в какие

регистры или аппаратные порты ввода/вывода, а всего лишь выполняет побитовое-И

между А и Б, рассматривая их как длинные целые: бывает, что надо и в других

местах выделять отдельные биты. (Или, используя не вполне корректные

фокусы-покусы со знаками А и Б — другие побитовые операции...) Или например

так же самая FSBr() без аргументов, не вызывая никаких подпрограмм, сразу

возвращает содержимое аккумулятора. (Куда иногда могут "зелететь" и такие

вещи, как например количество строк, реально выданных на экран просмотрщиком,

которые не узнать больше никак...)

((Вот тут я должен покаяться: я же обещал, когда всё это затеял, не вводить

в Фокал ничего нового — использовать только то, что там было изначально.

Добавив ну может быть парочку функций и операторов. То есть расширять чисто

количественно. А я таки ввёл: концепции игнорирования выражения, пропуска его

без вычисления в традиционном Фокале небыло. Всё остальное там было, а вот

этого — нет. А это — отдельный механизм квазивычислений. Но деваться было

некуда: условному оператору If (см. далее) никак нельзя давать вычислять все

указанные в нём выражения — только одно. Из за их возможного побочного эффекта.

Но уж коли лошади уже убежали — нет смысла запирать конюшню: если что-то где-то

таки используется, значит это можно (и нужно) использовать везде! Это я про

игнорирование лишних, не предусмотренных конструкцией языка, аргументов функции.

А вот всё остальное там было...))

— парочка-троечка функций с побочными эффектами: FColoro (она же FЦвет) для

указания цвета выводимых на экран символов (включая коррекцию палитры);

FKурсор (она же FCS) для перемещения по экрану курсора (включая считывание

уже выведенных на экран буковок, изменение их цвета, а так же рисование на нём

линий и рамочек символами псевдографики); FBIp для издания звуков с помощью

встроенного в компьютер динамика (включая ноты и азбуку морзе); FMuso (она же

FMышь) для работы с мышкой; FMIn и FMAx (без побочных эффектов) призванные

(вместе со сменой знака в роли инверсии) служить логическими операциями И и

ИЛИ — в том числе для троичной или нечеткой логики. FTMp для получения текущей

даты/времени (в виде количества суток от начала тысячелетия, где время это

дробная часть суток) а так же для других действий с датой/временем, включая

преобразование в удобочитаемый вид и обратно.

А "удобочитаемый вид" это вообще-то текстовая строка! И единственное, что с

нею можно было сделать это отправить в канал вывода. Но потом, в части второй,

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

текстовую строку, она же — аккумулятор А2. И тогда стало естественным поместить

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

В общем этот исторически сложившийся бардак, когда у одних функций с этим

так, а у других эдак, продолжался буквально до вчерашнего дня. Когда наконец

все функции с текстовым побочным эффектом были приведены к общему знаменателю.

(Всётаки вот такие вот "акты ревизии" как вот этот, пишутся совсем не зря.

Таки позволяют выявлять имеющие место несообразности и/или технологические

потребности...) В общем я сделал по аналогии с функцией FTEll (она же теперь и

FOper) где этот самый текстовый побочный эффект включается наличием второго

аргумента. Которого может и не быть — достаточно отделяющей его запятой:

FTEll("имя_файла", ); Соответственно, переключение его на А2 — так же:

FTEll("имя_файла",, ); и для других подобных функций — аналогично: FTMp(t,)

FKurs("k",) FTEll(,,N_арг,)

Но вот если они вызваны внутри форматного выражения оператора Write %формат

(о котором пока что речи еще небыло) как раз и работающего с А2, то помещение

туда текстовой строки — подавляется. Однако она имеет шанс стать операндом — в

случае если в этом месте предполагается именно строка, а не число:

{"..."__FTMp(t,)...} или #{FTMp(t,)} в последнем случае конструкция %...

если есть — ингорируется. Впрочем, это мы безбожно забежали вперёд...

— оператор Vizual и парная к нему функция FViz на предмет "управления

визуализацией". А на самом деле получения параметров экрана (например высоты и

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

один из графических режимов и отрисовку там графичесских примитивов.

Однако, эти примитивы оказались слишком примитивными (и пока что этот

оператор отправлен на реконструкцию, а функции сией функции — урезаны): Фокал

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

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

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

"полигон" и закраска оного, а оси координат (вместе с началом координат,

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

и уже только после этого точки графика (возможно объединённые в "коллекции"),

положения которых на экране автоматически пересчитываютя в соотвтествии с

масштабом осей. Эта часть графики — "векторная". А "растровую" предполагается

поручить двум функциям FТочка и FЛиния, как это было в Фокале на БК-0010,

организованным по аналогии с FKурсор...

— некоторая модернизация некоторых операторов:

* Вычисление возвращаемого значения прямо в операторе Ret, делающее его

аналогом Xecut. (Чисто на будущее: чтобы если и когда будут параллельные

процессы, запускаемые оператором Job — чтобы между вычислением возвращаемого

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

всю малину.)

* Передача оператором Do параметров в подпрограмму по аналогии с FSBr

* Дополнительные ключевые слова в операторе Write чтобы сообщал дополнительные

сведения (в форме пригодной для последующего ввода), в том числе о результатах

деятельности операторов Set Oper Do Break... Аналогично и для Eraze — буде

там найдётся что очистить.

* Несколько выражений в операторе Xecut и несколько присваиваний в операторе

Set — выпендрёж чистой воды. (Ибо экономия получается — копеечная.) А вот

избавляться от ключевого слова Set (как первое что сделали в Бейсике — сделали

чтобы можно было не писать LET) — это фиг: нарушение принципов! Да и экономия

в два символа, включая пробел...

* Меры по повышению "скриптовости" операторов передачи управления If и Go.

Это когда программа не как обычно — сперва грузится в память и только потом

запускается на выполнение, а сразу выполняется по мере чтения из файла. Который

называют "командным" (а нынче — "скриптовым"). Особенность тут в том, что

все строчки командного файла — "прямые". А операторам передачи управления

подавай номер строки!. Чтобы от них здесь был хоть какой-то толк, надо бы номера

строк как ни будь того... Равняясь на оператор For, у которого тело цикла это

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

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

при условии сохранения разделяющих их запятых. И плюс к этому пусть нулевой и

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

(перейти к следующей строке), а отрицательный — к следующему оператору, то есть

к остатку строки, как и пропуск. (А то вызовем FSBr, а она...) И тогда можно

например так:

If (X) 0, ,0; Type " икс равен нулю "!

If (X) ,0 ; Type " икс не равен нулю"!

Дополнительно: из трёх выражений в операторе If теперь вычисляется только одно,

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

побочный эффект. И/или в выборе одного из них — смысл всего этого оператора...

По аналогии с If — оператор Go 0; передаёт управление на начало текущей

строки и таким образом позволяет сделать цикл в одной строчке. Например:

Set c=FCHr(-1); type c; If(c-27),0; Go 0; Coment 27 — код нопки ESC

Эта програмка в одну строку будет выдавать коды нажатых кнопок, пока

пользователь не нажмёт кнопку ESC, она же "эскейп".

* Модернизация оператора For на предмет борьбы с плавающей арифметикой:

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

конечное значение более чем на пол шага. (Но после завершения цикла остаётся

таким, каким был при последней итерации.) Ну и за одно — автоматический выбор

шага, если он опущен: еще и -1 если конечное значение меньше начального. А

опустить можно не только шаг, или даже конечное значение (получится аналог

оператора присваивания), но и вообще всё. Остаток строки выполнится ровно один

раз, но как подпрограмма — что нам тоже понадобится... (Чуть ниже.)

— Реакция на "события" и "ситуации" (в т.ч. ошибки). Она устанавливается:

Break С = реакция; "Реакция" здесь это номер строки или группы, которую

надо запустить, когда произойдёт оное событие или случится ошибка/ситуация.

Хотя это может быть и остаток строки: Break С = ; остаток строки...

Если С < 0 то это ВНЕШНЕЕ "событие". И ловушка на него — глобальная.

(Удалить — только явно, указав нулевую реакцию.) Для ДОС`а первые 256 из них

это реальные прерывания (а под UNIX`ом это будут сигналы); с номерами больше

1000 — свои собственные, типа окончания звукового фрагмента, временного

интервала, заказанного функцией FCLk, и.т.п. К сожалению количество таких

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

Фокала — медленный; реакция на событие "вклинивается" между выполнением

операторов и выглядит так, как будто между ними вставили оператор Do, но

когда это еще будет... Поэтому внешние события только "фиксируются" -

наращивается значение связанного с ловушкой счетчика. При запуске реакции оно

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

обнулить все эти счетчики: Eraze Break;

Если С >= 0 то это ВНУТРЕННЯЯ "ситуация", в том числе ошибка. Ловушка

на неё — локальная. (Автоматически удаляется при возврате из поставившей её

подпрограмы вместе с локальными переменными.) По аналогии с программными

строками, события объединяются в группы (ошибки: группы событий 0 — 5), ловушку

можно поставить как на всю группу, так и индивидуально. Возникнув, ситуация

123456 ... 141516
Предыдущая глава  
↓ Содержание ↓
  Следующая глава



Иные расы и виды существ 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)
Закрыть
Закрыть
Закрыть
↑ Вверх