вторник, 28 февраля 2023 г.

Таблица-список готова

 Задача оказалась проще, чем я предполагал, однако потратил на эти несколько функций не один день.

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

суббота, 25 февраля 2023 г.

Связанные списки, написанные в панике

 Задался вопросом, как хранить данные в таблицах приложения. 

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

Придумал следующее решение. Хранить данные в списках например по 16 элементов на список. А указатели на списки хранить в массиве, память в котором тоже выделять блоками.

Тогда при поиске элемента можно будет посмотреть первый и последний элементы в списке - попадает ли искомый хэш в данный диапазон или нет. И если попадает, то дальше искать элемент уже в этом списке, а если нет - то, искать в меньшую или большую сторону.

Суть оптимизации проста - мы как бы имеем связанный список, отсортированный по возрастанию хэша, но имеем возможность перебирать его элементы методом прыжков, который весьма эффективен.

Но могу ли использовать контейнеры C++? - спросил я самого себя, и решил, что там вряд ли используются самые эффективные алгоритмы. Ещё до этого меня неприятно поразило, насколько в общем виде там всё реализовано, когда я увидел их исходник в отладчике.

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

Понял, что мне мешает сосредоточиться, когда я программирую. Как ни странно, это неведомо откуда появляющееся ощущение еле заметной паники. Как будто я пытаюсь что-то испортить, а не создать нечто новое.

Память подсказывает, что первый раз я с этим столкнулся, когда писал сценарии. Тогда это чувство бывало настолько сильным, что мне приходилось буквально продираться через эту пелену, сочиняя что-то совсем уж наобум - настолько не соображал от ужаса мозг.

Но я заметил, что правильная музыка помогает это чувство приглушить. Или наоборот - усилить.

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

Чтобы начать новый проект, требуется погрузиться в зону комфорта. Расслабиться, успокоиться, ни о чём не беспокоиться.

Но затем, начав писать, требуется работать, ни на что не отвлекаясь, по возможности быстро. И вот это "быстро" пугает, потому что становится страшно сделать ошибку. Чувство комфорта и защищённости рассеивается, и вместе с усталостью возникает паника.

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

Ведь если я настолько боюсь чего-то не слишком реального, каких-то иллюзий, то нужно просто напугать себя ещё сильнее.

Например: а что, если за мной шпионят? - такой страх например посещает.

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

А что, если именно я когда-то посоветовал им попробовать наркотики, но давно об этом забыл? - ещё страшнее вариант.

И так далее. В какой-то момент мозг начинает протестовать против подобной ахинеи, и страх уходит.

Но сейчас я вспомнил причину. Причина в том, что по мере роста объёма текста или кода начинаешь забывать, что было до этого. И панику вызывает именно эта потеря определённости.

Ведь наши воспоминания как бы формируют для нас основу уверенности в себе. Если вам только что стёрли память, то это не страшно, потому что вы не помните своих иллюзий, питавших ваши страхи.

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

При этом как мы боремся со страхами? Да просто спрашиваем себя: а чего я боюсь в данный момент?

А тут вы можете ответить себе только: я не помню, я слишком устал.

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

Не особо хочется, потому что алкоголь меня бодрит.

пятница, 24 февраля 2023 г.

Четыре потока

 Не так-то просто начать не с функции calc_hash - ведь она используется для поиска по таблицам объектов и функций.

Немножко повозился с консолью терминала. Новый алгоритм работы в терминале потребовал изменить логику потоков. Которая получается отличной от концепции терминала в языке C.

В C мы имеем три потока: 

  • поток ввода, 
  • поток вывода, 
  • поток вывода сообщений об ошибках.

Новый алгоритм предлагает четыре потока:

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

Теперь надо сделать функции открытия и закрытия файла для вывода текста. И команд в том числе.

Вижу себе это так:

text_out_file myfile = "~/my_texts/text01.txt" // Задаём имя файла
myfile rewrite // Открываем файл для перезаписи данных
               // Или append - чтобы открыть файл для добавления данных
out_stream = myfile  // Делаем myfile потоком вывода
myfile close    // Закрываем файл (потоком вывода снова становится cout

Значит нужно сделать:
  • таблицу объектов,
  • объект типа text_out_file
  • объект out_stream.
Насчёт объекта out_stream я пока не уверен, ведь это имя свойства консоли. Наверное правильнее сделать объект console, и обращаться к нему явно. Но это нужно придумать, как пользователь будет управлять консолями ввода-вывода.

Неявно консоль создаётся при запуске программы или при выполнении команды exec. Но правильно ли это?

Пока не хочу забегать вперёд.

Новый алгоритм работы в терминале

 Хотел поработать много, но поработал мало, а день таки прошёл.

Неожиданно для себя я увидел следующий алгоритм работы в терминале.

Пользователь вводит текст, и этот текст записывается в файл. Но если он ввёдет на конце строки некий код (например ===), то терминал переключится в режим ввода управляющих команд. А затем, введя ===, можно будет продолжить ввод текста или данных.

Гениально, - сказал я самому себе. - Это почти как вставки кода в веб-страницах.

Поэтому вместо ставших уже традицией функций exec и calc_hash, я решил написать функции чтения текста из файла и записи текста в файл. 


Стоило ли спешить?

 Почитал, что я тут написал в блоге. Честно говоря, про это устаёшь даже читать - не то, что этим заниматься.

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

Затем начались бомбардировки, и я больше не мог ничем заниматься - всякое занятие вызывало у меня приступ паники. Как будто сейчас меня начнут бомбить за это.

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

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

К проекту своего языка мне с одной стороны вроде бы хочется вернуться, поскольку по своему опыту я знаю, что так или иначе всё упрётся в необходимость этой программы. Но с другой стороны мне хочется попрограммировать нечто более развлекательное - какую-нибудь 3D-графику или нейросети.

Парадокс нейросетей я бы сформулировал так. Ими можно управлять, только если добавить классификатор.

Например, логический элемент A & B -> C. Результат его работы - классификация входящих данных: A и B.

Мы можем добавить класс D - получится A & B -> C, D. Пока что всё ОК.

Но что, если A и B - это два пикселя картинки, C и D - тоже два пикселя, а нейросеть - это такой фильтр: почему A не B, как это изменит C и D?

И вот тут получается, что нейросеть, инициализированная случайными значениями, даёт случайный результат. Чтобы определить закономерность для пикселей C и D, нам требуется ввести классификацию, с помощью которой управлять работой нейросети.

Но ведь мозг человека каким-то образом имеет классификатор, который сообщает нам, что яблоко не должно быть фиолетового цвета. Или почему бы и нет, и всё дело только в среде, в которую нас помещает предназначение?

Всё это связано с моей программой таким образом, что я так и не смог ответить самому себе на вопрос, что именно я собираюсь автоматизировать.

Вот, например, язык JavaScript. Есть браузер, задача которого - показать веб-страницу. И вот язык скриптов, который позволяет пользователю автоматизировать взаимодействие пользователя с этой веб-страницей.

Этот язык создан именно для этого, и больше нигде (разве что кроме плат Iskra Neo) не применяется.

А я свой язык стал создавать, не имея перед собой цели - что именно я хочу автоматизировать. Поэтому задача выглядит слишком абстрактной, и поэтому объём работы получается невероятно гигантским. Просто удивительно, насколько много самого разнообразного кода написали люди на том или ином языке.

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

Вот, допустим, мы хотим создать DSP на языке Verilog. Но средства этого языка не позволяют использовать классы и объекты. Это условный, хотя и наглядный пример.

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

Но я приводил здесь пример работы со строками:

Дело в том, что элементы Форта были в ней привлекательной частью. Но работа со строками получилась очень странной из-за этого. Только представьте - как выглядит функция substr на объектном Форте:

"Hello World!" 0 5 rot sub_str "Hello" == if
    "How are you?" cout <<
;

Здесь мы берём слово "Hello", и если это "Hello", то отвечаем "How are you?". В целом неплохо, но были варианты просто дикие - например разбор аргументов командной строки.

Но вот, к чему я пришёл в итоге нескольких лет разработки:

create function add 2

param int x

param int y

result int

return math.add x y

end


Примерно так выглядит псевдоассемблер компилятора. Очевидные достоинства - абсолютно понятная логика. Недостатки - очень сложную функцию очень сложно написать, и следовательно - легко сделать ошибку.


Парадокс, который мне открылся, можно описать так: всё в программе - это набор таблиц. Данные - таблица, код - таблица, и чем лучше они упорядочены, тем лучше работает программа. Поэтому в моей программе нет смысла - ведь если я не могу упорядочить программу на C++, то и любой другой язык мне в этом не сможет помочь.


Тем не менее, сейчас затея снова кажется мне интересной.


Глядя на свой предыдущий код, я вижу, насколько он плохо структурирован. Даже зная, как это работает, невозможно отыскать ошибку.


Простой пример: пользователь вводит "hello и Enter. Консоль сообщает ошибку: глобальное имя "hell не найдено.


Почему символ o пропал? Надо исправить, - сказал я самому себе, и так и не смог отыскать, где же в программе происходит обработка этого токена.


Но читая блог, я понял, в чём моя ошибка - я слишком спешил писать код.


И в самом деле - прошло 2 года, программа так и не написана - так стоило ли спешить?