Мой личный язык программирования

Кон В. Г.   май 2025 г.   http://kohnvict.narod.ru   kohnvict@yandex.ru

01 . 02 . 03 . 04 . 05 . 06 . 07 . 08 . 09 . 10 . 11 . 12 . 13 . 14 . 15 . 16 . 17 . 18 . 19 . 20 . 21 . 22 . 23 . 24 . 25 . 26 . 27 . 28 .

01. . . . Рассмотрим как создается личный язык программирования (ЛЯП) первого уровня. В любом ЯП есть процедуры (функции, подпрограммы, разные названия). Они имеют название и аргументы. И в теле этих процедур делается какая-то работа, результаты которой либо выдаются в число или текст, в зависимости от того какой тип имеет процедура. Но чаще всего результаты передаются в глобальные переменные, которые существуют не только в теле этой процедуры, но и за ее пределами.
. . . Работа, которую выполняет эта процедура, может быть специальной или достаточно общей, но важно, что ее нельзя выполнить непосредственно командой или оператором того языка, который используется. А с другой стороны, такую процедуру можно написать при использовании любого языка программирования. За первой процедурой будет написана вторая, третья и очень скоро таких процедур может накопиться большое количество.
. . . И закончится все тем что любая ваша программа будет состоять из набора ваших же процедур, а конкретного ЯП, на котором они написаны, не будет видно. А раз так, то и переменные будут использоваться только глобальные. Другие переменные будут в процедурах. И вот такой набор ваших же процедур и будет вашим ЛЯП-ом. Интересно, что точно такой же набор процедур можно написать на другом языке программирования. Хотя работа эта не простая, но фокус в том, что переводить с одного языка на другой можно чисто формально, даже не понимая что именно делает код.
. . . В моей практике так и было. Я свой ЛЯП придумал и сначала написал на фортране. А потом переписал на Java для персональных компьютеров. А потом еще и на Java для десктопов. Это общее название для компьютеров, которые стоят на столе. То есть они могут быть в ящике (коробочке), в мониторе или ноутбуки, не важно. Важно, что у них большой экран. Интересно, что перевод кода процедур с одного языка на другой -- вполне достойная работа для ИИ (искусственного интеллекта).

02. . . . Вообще говоря, набор процедур существует в любом языке. Есть общие процедуры, которые поставляются вместе с языком, точнее с компилятором языка, если он компилируется, или с интерпретатором, если исполняется. В компилируемых языках процедуры, как правило существуют уже в откомпилированном виде, а в интерпретируемых языках общие процедуры являются частью языка. ЛЯП-ом могут стать только те, процедуры, которые программист написал сам для себя. Такие процедуры, как правило, не очень универсальные и годятся только для программ, решающих определенные задачи.То есть по большому счету их нельзя назвать языком программирования, если они не способны решать любые задачи.
. . . Нужен хотя бы какой-то набор средств, которые были бы способны запускать процедуры в каком-то порядке и по какой-то системе. Если использовать процедуры в комплексе, то их возможности значительно возрастают. То есть ЛЯП должен уметь оперировать процедурами с учетом их взаимодействия друг с другом. И хотелось бы попроще, чтобы не особенно напрягаться. Самым простым языком, который оперирует не процедурами, а программами является язык операционных систем. Он существует во всех операционных системах, но я буду говорить только о двух системах: Виндовс и Линукс.
. . . В системе Виндовс этот язык программирования является просто продолжением системы ДОС, в которой он был основным. Но сейчас этот язык пользователям не предлагается потому что есть графические средства делать то же самое и это как бы проще для начинающих. А начинающие, как правило и начинают в этой системе. потому что там все красиво и можно сразу что-то делать. И даже не беда, если неудобно, долго и медленно. Ведь графические средства не умеют программировать, все надо делать вручную и через клавиатуру или мышку. Но командный язык программирования есть.
. . . Основным в этом языке является запуск готовых программ из командной строки. Указывается какую команду запустить и какие ей аргументы передать. А в самой программе есть способ эти аргументы прочитать из командной строки. Есть и средства передавать аргументы или лучше говорить входные данные (ВД) из файла, а результаты записывать в другой файл или на экран или другой программе. И это уже позволяет что-то автоматизировать. Но есть еще и способы запускать программы по условию или не подряд, а в более сложном порядке.
. . . В системе Линукс практически такая же командная система с набором стандартных программ называется ядром системы. Эта система бесплатная и устроена таким способом, что можно начинать только с ядра системы. То есть сначала скачивается ядро и уже можно работать. А если чего не хватает, то в ядре есть способ добавить любой набор программ в систему и ее возможности возрастают. Но команды системы все равно используются наравне с готовыми программами, которые тоже способны реализовать графический интерфейс. Для начинающих сложно то, что они должны сразу что-то учить, и потом знать что им нужно. Им система как бы ничего не предлагает просто так.

03 . . . Текст этого рассказа добавлялся постепенно. А содержание зависело от вопросов, какие поступали в разной форме, в том числе через сообщество МЛЯП.
. . . Первый вопрос был такой. Зачем создавать новый ЛЯП, когда языков программирования и так уже больше, чем нужно. Ответов может быть много. В природе огромное число разных видов животных. Зачем? Компьютерных программ тоже очень много, причем многие делают одно и тоже. Например, текстовые редакторы. Наверно все дело в том, что люди разные, и у них разные вкусы, возможности, способности и много чего еще. И часто то, что сделал один, другому не нравится. А многие ЛЯПы просто по другому записывают то, что делают те ЯП, которые уже есть. И даже такой мотивации вполне достаточно.
. . . Кто-то хочет быть богатым, а кто-то не хочет. Кто-то хочет иметь власть но большинство точно этого не хочет. Кого-то устраивает то, что уже есть, а кто-то во всем видит недостатки и хочет их исправить. И ведь очевидно, что многое, что уже сделано, не очень-то удобное, правильное, удачное и так далее. Большинство терпит, а кому-то не хочется терпеть. Если конкретно взять мою историю -- почему я пишу программы на ЛЯПе, то она не совсем стандартная. Дело в том, что я начал программировать тогда, когда еще ничего не было совсем. Программы писались в коде компьютера, и каждый работал на компьютере сам, как теперь на персоналках.
. . . Не было никакой операционной системы, никаких файлов, ничего. Тогда каждый, кто программировал, а таких было мало, создавал свой ЛЯП. Потом появился фортран и какая-то операционная система, но на компьютер пускать перестали. Там работали специальные люди. Текст на фортране набивался на перфокартах, компьютер их прочитывал, компилировал текст в свой код и выполнял. Результат компиляции не сохранялся. Кроме фортрана не было ничего. Но даже на фортране уже можно было писать подпрограммы и формировать свой ЛЯП. Потом появились персональные компьютеры, но они очень медленно работали. И тратить время на компиляцию графики не хотелось.
. . . Нужна была программа, которая как двое из мешка все выполняет по приказам. И вот эту программу я как раз и сделал. Это и был интерпретатор моего ЛЯПа. Меня никто не учил это делать, я все придумал сам. Была и другая мотивация, но про это я уже рассказывать не буду, это не всем интересно. Дело в том, что шел 1992-й год. Кто знает что тогда было в России, тот поймет. В то время я уже умел программировать не только на фортране, но и на ассемблере. И мой интерпретатор умел такое, что многим было не доступно. Но все это работало в ДОС, текстовой операционной системе с ЯП в виде команд.
. . . Многим молодым людям такая система не нравится. А мне нравится, и она очень хорошо используется до сих пор в системе Линукс (Юникс). Фактически мой ЛЯП просто несколько расширил эту систему, сделал ее более универсальной. А название моего ЛЯПа -- это сокращение от слов Victor Kohn Advanced Command Language (vkacl). Но история на этом не закончилась. К концу 90-х годов система Виндовс уже вполне быстро работала и была повсюду. И эта система мою программу не запускала, мол очень опасная. Я от нее отказался. А в 2003 году появились карманные компьютеры. Они работали в системе Виндовс Мобайл. И в этой системе была виртуальная машина языка Java. Не от авторов, а чужая и бесплатная.
. . . Я научился ее использовать, переписал код своего интерпретатора с фортрана на Java и программа заработала на карманном компьютере. А программ, которые на нем умеют считать и рисовать графики тогда не было. Так что моя программа имела успех, ее обсуждали на форумах, в каталогах программ и пользователи были. Свой сайт я сделал еще в 1998 году и сделал отдельный сайт о программе. Его посещали. Я сам читал книги на карманном компьютере по своей программе. Но и это закончилось. Появились смартфоны на системе Андроид, а там бесплатной виртуальной машины для языка Java нет. Там вообще мало ЯП, но есть. Однако мне это уже не интересно. Я переписал свой интерпретатор на систему Виндовс для десктопов и работаю на нем на ноутбуке.
. . . На моем сайте есть специальная ссылка на страницу о программе, с которой ее можно бесплатно скачать и попробовать. Более того, учить мой ЛЯП сразу совсем не обязательно. Есть очень много весьма интересных готовых программ, которые на нем написаны мной. Более того, они все работают даже в демонстрационном режиме. В интернете есть описание всех программ. есть записи видео, на которых показано как это работает. Но программа все еще развивается и появляются новые возможности. Ну а если вдруг обнаружите ошибку, то можно мне написать, и я ее исправлю. Адрес моей почты kohnvict-собака-yandex.ru , а ссылка на сайт есть в контактах сообщества.
. . . Сейчас есть возможность тестировать программу в системе Линукс не выходя из Виндовс. В Линукс программа может работать прямо на ядре, то есть кроме нее, виртуальной машины Java и браузера можно ничего не скачивать. При этом даже слабые десктопы могут очень эффективно работать. Зависит от того что и кому надо. Лично мне интересно делать сайты, фото-альбомы, анимации и презентации, математические расчеты и вообще автоматизацию всех процессов на компьютере. ЯП Java реально очень мощный язык с огромными возможностями. Но у него очень сложный синтаксис и организация. Мой ЛЯП во много раз проще, а возможности те же. Даже еще больше, так как за свою жизнь я программ написал очень много и они лучше, чем многие платные программы.

04. . . . Итак, я решил писать интерпретатор своего языка в начале 90-х годов. В то время я работал на фортране, который был на работе. И надо было каждый день туда ездить. Я каждый день и ездил. Приезжал между завтраком и обедом, уезжал после ужина. Но ужина не было. Сухари из засохшего батона и чай, можно много раз. Как раз тогда я и заработал себе гастрит. Но во всем остальном было вполне сносно. Условия для работы были. ЯП фортран мне вполне нравился как язык для расчетов. Но графика на нем делалась с помощью библиотеки функций языка С и надо было писать многочисленные интерфейсы. Это если на экран. А если в файл, то была другая библиотека и надо было каждый раз компилировать.
. . . Вот как раз это я и не хотел. То есть мне нужен был интерпретатор. Интерпретаторов в то время на Западе было уже много, но об этом я узнал намного позже. В то время я не знал ни одного. Делать вычисления на интерпретируемом языке просто невозможно (было бы ОЧЕНЬ долго). А графику мало кто делал. Фортран сам это не умел, а других языков у нас не было. Точнее, языки то были, кобол, например, но они тоже ничего не умели. Мне нужен был язык для графики, но и для всего остального тоже, но попроще. ООП тогда еще мало кто знал, да и компьютеры это не потянули бы. Были процедуры.
. . . Я тоже решил делать процедурный язык, но без излишеств. Что, на мой взгляд, было лишнего в фортране. Память. А уже неплохо знал ассемблер и понимал, что в компьютере нет многого, чего придумали для программирования. Память должна быть едина для всего кода. И программист должен сам ее распределять. Да, это немного сложнее, чем общие блоки памяти, зато возможности манипулировать памятью самые высокие. Но есть типы памяти. Есть целые числа, есть реальные числа и есть символы текста. Вот это разумно оставить, просто потому, что разные типы по разному записываются в компьютере, то есть имеют разное число байтов для записи чисел.
. . . Разного рода профи и знатоки ЯП мне сразу скажут что так программировать нельзя. Что бывают ошибки, люди в основной своей массе неграмотные и неумные. Что за такой памятью надо очень жестко следить, иначе разные части кода будут портить память друг друга и программа просто никогда не будет работать. Все верно. Но ведь я писал личный ЯП, я писал его для себя. И мне нужны были возможности, а с трудностями я сам и буду искать способы справиться. Фактически я уже давно так работал и на фортране. Я объявлял один большой массив и других не было.
. . . Но надо еще понимать разницу между ЯП интерпретируемым и компилируемым. Я переписываюсь с некоторыми программистами и они все меня уверяют, что нет никакой разницы. Что мол сейчас компиляция быстро делается. Это не так. Исправлять программу и сразу пускать ее в работу намного проще и быстрее. Компилятор дает возможность быстрее считать, но не дает возможности быстро искать ошибки На компиляторе с такой памятью я бы работать не стал. Кстати, через много лет после начала 90-х фирма Майкрософт разработала упрощенный ЯП для детей. Они назвали его small basic. И там тоже была глобальная память. То есть единая для всего кода.
. . . Это очень важный момент при построении ЯП. Когда я придумывал свой ЛЯП, я других языков с такой памятью не знал. Правда они были. Только в конце 90-х я выучил язык Постскрипт, и там вообще нет массивов. Только стек. Стек -- это такой массив без индексов, в который все закладывается как в пенал или в узкую комнату с одной дверью. Но всем наверно понятнее как заходят в автобус. При такой закладке тот, кто последним зашел, первым должен выйти. Но так очень часто и бывает. Даже в автобусе. Тот, кому скоро выходить, не торопится сесть первым. Он всех пропустит и сядет последним. В программах тоже можно так делать.
. . . Но в моем ЛЯПе массивы все же есть: один целый (4 байта), один реальный (8 байт) и один символьный (2 байта). Это для работы. И есть один служебный массив для удобства чтения кода программ. Размеры этих массивов достаточно большие, но вот это можно менять при создании программы интерпретатора. Если сделать мало, то не все задачи можно решить. Если очень много, то программе может не хватить оперативной памяти компьютера. Размеры этих массивов я периодически менял по мере увеличения параметров компьютера. И всегда на заказ можно сделать вариант с любыми размерами. Сейчас интерпретатор написан на ЯП Java для 64-битных операционных систем (ОС) и размеры массивов соответствуют возможностям любых современных компьютеров. Но для специальных задач я делал вариант интерпретатора с массивами, размер которых был намного больше. Это делается несложно,, но надо компилировать.
. . . Второй по важности момент -- это синтаксис. Именно в этом вопросе разные вкусы людей видны лучше всего. Я читал много рекомендаций про то, что хороший язык -- это понятный язык, что он должен быть близок к разговорному языку. И даже есть такие любители, которым не нравится язык программирования из английских слов. Мол, как раз поэтому американские программисты работают быстрее русских. Русские не знают английский язык и потому плохо понимают что писать и как. Но мой ЛЯП я делал для себя. И я знаю не только английский язык, но и математику. А как раз законы природы, то есть языком природы является математика. И там все записывается компактно и непонятно для непосвященных. Лично для меня компактность кода значит намного больше, чем длинные комбинации букв из нескольких слов.
. . . К сожалению такой стиль у языка Java, на котором написан мой интерпретатор. Как раз по этой причине мне не нравится писать программы на этом языке. А вот интерпретатор я написал, потому что сам язык по всем остальным параметрам очень хороший и мощный. И я придумал промежуточный вариант. В моем языке можно писать длинные слова, если кому это интересно. А можно и не писать, потому что интерпретатор все понимает по первым буквам. Для каких то слов можно писать одну букву, для каких-то две, и максимум три -- для всех. Но буквы все же латинские. И они являются началом слов на английском языке.
. . . Почему так. Чисто практически. Американцы были первыми, кто разработал программирование. В том числе и запись символов. Именно латинские символы стоят в самом начале таблицы юникодов и записываются одним байтом в кодировке utf-8. Для них все кодировки одинаковы. А русские символы записываются двумя байтами в кодировке utf-8, и одним байтом в большом числе кодировок и каждый раз иначе. Это создает определенные сложности в записи кода программ. По этой причине лучше все слова не писать, а на запись кода программы реагировать как на китайские иероглифы, только их намного меньше. Достаточно их выучить и код станет понятным и легко читаемым.
. . . А компактная запись при чтении кода интерпретатором очень даже нужна. Даже разработчики ЯП Java это понимали. Поэтому перед использованием интерпретатора они предложили компилировать код программ в байт-код, который как раз записывается компактно. Ну а в моем ЛЯПе лучше сразу все компактно записывать. Компактная запись быстрее читается, легче усваивается. требует меньше места на экране и это все плюсы, есть и другие плюсы. Например, при поиске ошибок иногда надо временно дописать какой-то код, а может и несколько И это намного быстрее сделать при компактной записи. Более того, при такой записи нет разницы между русским и английским языками. Это просто другой язык, но латинскими буквами.

05. . . . Я уже писал, что синтаксис ЯП в моем понимании должен быть компактным. Многие говорят, что, мол надо, чтобы было понятно. Но это весьма относительное утверждение. Для китайцев индо-европейские языки очень даже непонятны. Наверно это главная причина той ситуации, что восточная Азия не очень то любит общаться с Европой и Америкой. Но и в России полно людей, не знающих иностранные языки. И им подавай синтаксис на русском языке. Невозможно сделать синтаксис понятный всем сразу.
. . . Лично я должен был учить английский язык по работе. Наука более всего развита в европейском мире. Весь этот мир знает английский язык. Если в целом по странам его роль разная, то в науке -- это международный язык, как и доллар -- международная валюта. Его все должны знать, или ищите себе другую работу. Поэтому я все комментарии в программе пишу на английском языке. А короткие названия команд и параметров как бы являются началами английских слов. Например, в командах вместо window -- w, вместо file -- f, вместо message -- m и так далее. В параметрах вместо begin -- b, вместо number -- n, вместо operation -- op, и так далее.
. . . Но компактность и простота в синтаксисе -- это не только короткие команды. Структура самих операторов должны быть более простой. Вот в языке С и затем в большом числе других языков, включая Java, есть оператор цикла for( k=0, k < 25, k++){ a[k]=1; } или оператор условия if( a < b){} else if{} else{}. Когда то давно авторам ЯП C показалось, что это красиво, понятно и удобно. И плюс к этому еще много других операторов и условий и прочих конструкций. Про излишество типов данных я уже писал. По этой части большим изобретателем был автор Питона. А сейчас мода на постоянные переменные. То есть переменные, которые не изменяются. Авторы языков соревнуются в том, кто придумает позаковыристее новую бессмысленную конструкцию.
. . . И ведь не все понимают, что ничего этого компьютер не понимает и ничего этого нет в его реальных командах. Но, мол, компилятор все исправит. А если писать интерпретатор, который ничего не исправляет просто так, а только во время вычислений, то понятна затратность такого языка. Это и лишний расход электроэнергии, и лишнее время ожидания результата и просто неудобно даже писать. Я для себя такого не хотел с самого начала. И главный фокус моего языка в том, что он делает то же самое, что и Java, но записывает это совсем иначе. Нужно все же сказать, что языков, которые все записывают иначе, тоже много Например тот же постскрипт. Это очень старый интерпретируемый язык для принтеров. Там важно, чтобы принтеры не тратили время на разбор человеческой дурости, а сразу делали что надо. И в языке нет таких наворотов. Там как раз все просто.
. . . Но зато человеку не очень удобно. Приспособиться можно. Я, например, приспособился и легко пишу сложный код на постскрипте. Но в своем ЛЯПе я выбрал промежуточный вариант. То есть команды ОС Виндовс или Линукс (Юникс). Программа представляет собой поток однотипных команд. В других языках так пишут процедуры, а у меня вообще все. А процедуры пишутся несколько иначе, хотя и тоже командой. Любая компьютерная программа выполняет определенную работу, то есть делает операции. И это самое главное. Но таких операций очень много. И было бы полезно отсортировать их по типу. Это сделано на уровне команд. Вся программа -- это просто поток команд. Причем снова все перевернуто.
. . . Во всех языках операторы пишутся нормальным текстом, а вот комментарии, то есть просто текст, который не исполняется, отмечают разными знаками. В моем ЛЯПе как раз нормальный текст, который не исполняется, пишется свободно. А вот сам ЛЯП отмечается специальным знаком и этим знаком является Шарп #. Не знаю почему он так называется, но он хорошо заметный, почти симметричный и он мне понравился. То есть можно писать рассказ, в нем показывать элементы моего ЛЯПа и этот рассказ одновременно будет программой, которая реально может работать.
. . . И это решает проблему понятности языка. Если хотите писать понятный код, то пишите непонятные значки и к ним вполне понятное объяснение чего они делают. Причем на любом языке. А когда программа просто нужна для работы, то текст объяснений можно исключить, компьютер и так все поймет. Во многих языках большую роль придают символу конца строки. Его не видно, но он является частью языка. Например, так в Питоне. Как раз за это я не люблю Питон. В моем ЛЯПе символ конца строки ничего не значит. Иногда он мешает, иногда используется, но к программе он не имеет никакого отношения. Вместо него как раз и используется символ #.
. . . Но тот факт, что символ конца строки не используется, не мешает любому писать код программы как в Питоне, то есть с отступами и красиво с учетом символа конца строки. В том-то и дело, что в ЛЯПе нет никаких ограничений ни в чем. Каждый делает как ему нравится. И самым разным способом. Можно все писать в одну строку, можно каждый оператор на отдельной строке. Тут такая же история как и с массивами. Можно делать себе массивы как хочется и как удобно. И код можно писать как угодно. После символа # без пробелов надо писать не операцию, а тип операции. Бывают команды с одной операцией, но как правило операций много. И название команды просто указывает какой тип операции будет сделан. Например #f -- операции с файлами, #m -- сообщения на экран, #w -- что-то показать на экране графически, то есть картинку в окне, и так далее.
. . . А вот сама операция указывается текстом в параметрах. Грубо говоря, любая команда -- это как отдельная программа. Она выполняет какой-то набор операций, и для ее работы нужны параметры, которые указывают ей что делать. И еще могут быть аргументы. В командах ДОС параметров нет, только аргументы. Точнее не так, параметры тоже есть, но они работают как аргументы. В моем ЛЯПе параметры -- немного другое. Это просто массив целых чисел, которые имеют названия для удобства чтения программы. Можно весь код написать без параметров, но его совсем уже будет неудобно читать. А с параметрами, у которых есть названия, читать код удобнее и понятнее.
. . . Правда 4 текстовых параметра писать обязательно, без них компьютер не будет понимать что делать. Можно было бы и их сделать числами, но было бы хуже. А различие между параметрами и аргументами в том что параметры принимают значения и запоминают их. И второй раз писать это значение, если не требуется его изменить, не обязательно. Нужно указывать только новое значение. А вот аргументы -- это просто значения. Они прочитываются один раз и нигде не запоминаются. То есть их надо каждый раз писать заново. Но есть способы делать это компактно.

06. . . . Итак, есть команды, их легко заметить по символу Шарп #. У команд есть короткое имя, но многие команды имеют еще и параметры, среди которых главным является параметр op, который указывает какую операцию команда будет выполнять. Но часто и даже этим дело не заканчивается. Операция может иметь модификации и на это указывает параметр mo. Наличие остальных параметров, а также аргументов зависит от указанных. Другие параметры просто сообщают программе что, с чем и как надо делать. Например, очень многие операции выполняются над числовыми массивами, которые являются частью единственного массива, потому что массивы в ЛЯПе динамические. С ними можно выполнять самые фасонные манипуляции. Массив реальных чисел имеет просто часть индексов единственного массива, элементы которого записываются так r(25), то есть буква r и индекс в круглых скобках. Но индекс можно писать не только числом, а любым математическим выражением.
. . . Как известно, в математике бывают массивы разной размерности, одномерные, двумерные, трехмерные и так далее. Все такие массивы есть и в ЛЯПе, но они определяются динамически при задании параметров. В этом и состоит главная роль параметров. Они как бы дополняют язык своими названиями. Так очень часто параметр b (begin) указывает начало конкретного массива в общем массиве r(), то есть его первый индекс. А размер массива, если он одномерный, указывает параметр le (length). А если он двумерный, то параметры nx (number along X) и ny (number along Y) указывают размеры матрицы. Специальных параметров для трехмерного массива нет, но их можно задавать в любой переменной. При этом легко двумерный массив трактовать как одномерный, если в этом есть необходимость, а одномерный массив рассматривать как двумерный. Ведь по сути -- это просто части одного массива на все программы, которые могут быть написаны на ЛЯПе.
. . . Многие параметры были введены в ЛЯП для описания графики. Ведь первоначально ЛЯП для графики и создавался. Список всех команд и параметров есть в интернете. Все ссылки есть на моем сайте в конкретной статье, откуда программу можно скачать для использования. Здесь я не собираюсь описывать конкретные конструкции языка. Я просто хочу объяснить как он сделан, по каким принципам, и как он работает. Список самых главных команд и их операций имеет чуть больше 200 комбинаций. В языке Постскрипт, который делает только графику, их 400. Но реальных комбинаций всего со всем в ЛЯПе намного больше. И я, конечно, сам не помню весь свой ЛЯП, и тоже вынужден пользоваться справочниками. Там все написано и есть примеры правильной записи команд.
. . . Первоначально предполагалось, что программа записывается в файл, интерпретатор читает команды одну за другой и последовательно выполняет. Так во всех ЯП. Но ясно, что этого мало. Нужны переходы и условия, которые меняют порядок выполнения команд. И самым главным условием, без которого компьютеры просто бесполезны, являются циклы. То есть возможность повторить определенное количество команд много раз. Вот как раз повторять одно и то же человек не любит. Капитализм придумал конвейер, а люди, которые работают на конвейере, и как роботы много раз повторяют одну и ту же операцию -- самые несчастные. А компьютер не думает, ему все равно что делать. Он может и повторять.
. . . Тут я хочу сделать отступление. Дело в том, что среди команд языка ассемблер, который копирует код, который компьютер выполняет, даже такой операции как цикл нет. Там все двоичное и самое простое, что может делать компьютер -- это определить содержание бита (0 или 1) и делать разные операции в зависимости от этого. Собственно. конструкции почти всех языков, в которых есть операторы if(){}else{} (так в языке С и Java) как раз на это и указывают. Если условие выполняется (true), то делаем одно, а если нет (false), то делаем другое. Таким способом можно пропустить часть команд или вернуться назад и выполнить часть команд снова. И цикл на самом деле ставит метку в самом начале, а в конце возвращает порядок выполнения команд на эту метку.
. . . Но в разных ЯП можно встретить разную фасонную запись циклов, а все почему. Причина простая. Известный специалист по работе мозга Савельев все время повторяет, что мозг обеспечивает три фундаментальные функции -- это кушать, размножаться и доминировать. Вариантов доминирования много, в том числе и просто выпендреж, когда хочется делать глупости. В моем ЛЯПе такого нет. Команда #rep n (repeat n) ставит метку и указывает сколько раз повторять, можно числом или переменной. А команда #end возвращает указатель выполнения команд на эту метку точно n раз. В ЛЯПе нет фигурных скобок совсем. Есть круглые скобки в математике и для индексов, квадратные скобки отмечают поле, внутри которого определяются параметры, а фигурных скобок нет.
. . . А в разных языках можно встретить много вариантов циклов, в том числе с параметром, с условием в начале и с условием в конце. И чем больше конструкций, тем лучше себя чувствует автор языка. Он определенно доминирует, то есть мучает людей. И показывает какой он умный. Лично мне все это не нужно. Чем проще, тем лучше. Но кроме цикла есть и просто условия, причем снова разных типов. Все простые условия я перечислять не буду, но какое-то одно должно быть, иначе программа не сможет выполнять работу. Во многих языках есть конструкция типа select case(n) case 1 end case 2 end и так далее.
. . . Вот этот вариант я выбрал для условий. Но в ЛЯПе он реализован несколько иначе. Есть просто команда #case n и снова команда #end . Очень похоже на команды цикла. Да, таким способом и цикл можно записывать. Но тут все намного сложнее. А вот как, об этом я напишу в следующий раз.

07. . . . Итак для условий я выбрал вариант выбора одного случая из многих, так как он самый простой, и немного его доработал, то есть придал ему больше функций. Работает это так. Команда #case N ставит первую метку блока команд, а команда #end ставит вторую метку, определяя блок. В Java для этого используют фигурные скобки. А вот параметр N у команды имеет совсем другой смысл. Это просто число, желательно 0 или 1. Но может быть любым. А среди переменных, о них я еще не писал, но скоро напишу, есть переменная, которая обозначается символом &. И весь отмеченный блок команд выполняется только при условии, что N = &. Вот пример. # &=n; #case 1 . . . #end | #case 2 . . . #end | #case 3 . . . #end |. И будем менять значение n в цикле. Тогда при n=1 выполнится case 1, при n=2 выполнится case 2, и так далее.
. . . Напомню, что в английском языке слово case означает случай, вариант. Но оно уже и в русском языке употребляется среди молодежи. Вообще-то достаточно писать cas. Но тут я делаю исключение и вместо 3-х букв пишу 4. Все равно кратко. Выбор одного варианта из многих мы делаем, но этого же мало. А если нам надо что-то сделать при значениях n от 1 до 3, а при других значениях не делать. Это тоже возможно, но более сложным образом. В математике есть такие функции max(a,b) и min(a,b). Они выдают максимальное значение из двух и минимальное значение из двух. Тогда запишем так # &=min((n-1)*(3-n),0); #case 0 . . . #end | и все получится. Но в моем ЛЯПе эти очень важные функции записываются более кратко, как операции < и > математики. Так запись a<b означает минимум из a и b, а запись a>b означает максимум из a и b. Например, a<5 означает a для всех значений меньше или равно 5, и 5 для всех значений больше 5. А вот функция знака числа есть, она записывается как sgn(n) и это очень полезная функция для условий. И она уже имеет три значения -1, для отрицательного аргумента, +1 для положительного, и 0 для 0. И ее тоже можно использовать.
. . . А дальше дело техники. Практически любые условия можно записать математически и даже формальную логику. И совсем не обязательно запоминать кучу значков мат. логики и разных вариантов условий. Все законы природы описываются математикой, в том числе и логика. За много лет работы на своем ЛЯПе я ни разу не имел никаких проблем в том, что чего-то не хватает. Но это в начале. А что в конце. Помните, в операторе цикла в конце проверялось число повторений. Тут тоже делается проверка, но та же самая, что и в начале. Снова нужно проверить равенство условия & = N. Но N изменить нельзя, это аргумент, он прочитан и все. А вот значение переменной & изменить можно и нужно. Иначе будет бесконечный цикл.
. . . Но тут есть небольшое отличие. Равенство в конце проверяется на целых частях чисел. Если в начале N имело дробную часть, то в конце она не используется. Это не последовательно, но исправлять я не стал. Разумно вообще всегда проверять все условия на целых числах и тогда все будет хорошо. И если блок по условию надо выполнить всего один раз, то просто ставим вертикальную черту через пробел после end и это указание на то, чтобы изменить значение & на 12345 перед проверкой условия. И вот всего этого нет ни в одном языке программирования. Поэтому программисты глядя на мой код ничего не понимают. Ну что же, мне тоже противно писать программы на Питоне. Я считаю автора Питона не вполне адекватным человеком, который мучает бедных студенток заставляя их учить что такое кортеж и постоянные переменные. Скорее всего он меня тоже считал бы не нормальным если бы знал..
. . . 20 лет Питон никого не интересовал. И вдруг оказалось, что интерпретируемые языки удобные, а кроме Питона ничего нет. А в Питоне уже искусственный интеллект программируют. А то что графика и редактор в Питоне написаны 30 лет назад и с тех пор ничего не изменилось, и то, что там сложностей выше крыши, не говоря уже и про неудобный интерпретатор со своими пакетами и кучей типов переменных. Ясно, что если долго мучиться, то все получится. Впрочем в моем ЛЯПе тоже можно наделать ошибок и не знать куда бежать, потому что плохо распределили память в массиве и в переменных. Но научиться можно. И можно придумать методы. Зато в моем ЛЯПе все делается однообразно и код легко читается если знать что он означает. С другой стороны, зачем писать новый язык, если он похож на старый.
. . . Моя проблема в том, что мой язык тоже старый, но я сам постоянно его совершенствую и за последние годы он стал практически совсем другим. Кроме того, он легко наращивается и есть относительно простой механизм добавления процедур для интерпретатора, написанных на языке Java. По крайней мере это полезно для ускорения математических расчетов. Мой ЛЯП почти не тормозит. Как и Java он работает со скоростью компилируемых ЯП. Но концерт еще не окончен. Продолжение будет. Я только добавлю в ответ на некоторые замечания к моему тексту, что любой язык программирования придумывается одним человеком в соответствии с его пониманием как устроен мир. И это его понимание вовсе не всегда самое лучшее. Но молодые люди выучив и привыкнув к чему-то начинают на это молиться как на икону. Мол только так и по другому нельзя. Это очень напоминает религиозных фанатов. Они все не нормальные, но сами такими считают всех, кто с ними не согласен.
. . . Не знаю какой был замысел у тех, кто все это создавал, но пока все плохо. Да, есть таланты, есть прогресс, но организовать людей в единый механизм не получается и вряд ли получится. А значит постоянно будут катастрофы, войны и зверства. И когда-нибудь все закончится.

08. . . . Итак, у нас уже есть команды, циклы и условия. Все очень примитивно, но имея глобальную память ничего больше и не надо. Немного непонятно с логикой, но приспособиться можно. Можно просто всегда использовать функцию sgn(), которая принимает три значения, а в ее аргументе могут быть операции < и >, и этого вполне достаточно. Я более 20 лет работаю на этом языке и никогда не было проблем. Но нет информации о самом главном -- процедурах. В моем ЛЯПе это самый мощный инструмент. Пришло время рассказать как он устроен. Процедуры есть в любом языке. Многим покажется, что тут снова оригинально. Но нет. Есть ЯП Постскрипт и там сделано точно так же, как у меня, но у меня больше возможностей.
. . . Короче, процедуры -- это просто кусок кода, который имеет имя. И все. Открывается этот кусок командой #pro NAME, где вместо NAME можно писать любые комбинации символов не более 4-х, но я сам всегда пишу 4. И у меня часто имена -- это 0001, 0002 и так далее. Но это не обязательно. Имена могут быть любые, например, find, look, и так далее. Наверно можно и по русски писать, но я не пробовал. И не советую. То есть эта команда открывает код, который будет телом процедуры и присваивает ему имя. А закрывает код символ @. Кто-то называет его собака, он используется в почтовом адресе. Но я его выбрал потому что он как бы похож на жирную точку. Мол, написали и точка. Закончили писать.
. . . В языке Постскрипт имя процедуры после того, как она определена, можно сразу писать в коде. Но когда я создавал свой язык, я языка Постскрипт еще не знал. Я выучил его через 6 лет, когда попал во Францию и в библиотеке научного центра обнаружил книгу с примерами кода. Описания не было, я все выучил просто по примерам кода. Описание я нашел уже в Германии через еще пару лет. Кстати, на моем сайте есть очень компактная и неплохая книга по этому языку. Я сначала создал компилятор своего другого языка в постскрипт, а потом научился писать процедуры и написал книгу с описанием и примерами. Было время, когда Яндекс по запросу на слово Постскрипт выдавал ссылку на мою книгу сразу после Википедии. Потому что ссылку я вписал в Википедию. Но потом сайт пришлось перенести, ссылка исчезла, а заново я ее ставить не стал. Но я до сих пор часто использую постскрипт в работе.
. . . Также на моем ЛЯПе есть программы, которые генерируют рисунки научной графики на постскрипте. Была (точнее есть) и универсальная программа создания рисунка, но я ее уже не использую. А старый компилятор моего языка в постскрипт, написанный еще на фортране до сих пор работает в ОС Виндовс. Это программа VKPS. Ее последняя версия была сделана в 2000 году Ее можно найти на моем сайте и скачать. Сам я ее уже не использую, но тот язык проще и его легче выучить. На постскрипте намного проще сделать весьма сложную графику. В языке Jаvа, а также и в моем ЛЯПе есть два варианта графических программ. Первый -- более простой, но у него меньше возможностей. Второй -- самый продвинутый, был просто скопирован с языка Постскрипт. Все по другому записывается, но возможности те же.
. . . Однако, вернемся к процедурам. Они записываютcя так
. . . #pro abcd #com1 #com2 . . . #comN @
. . . И есть условие -- процедура должна быть записана раньше того места, где она будет использована в коде основной программы. И понятно почему. При чтении процедуры интерпретатором команды не выполняются, но к ее имени формируется метка куда надо перейти при вызове процедуры и метка, где надо вернуться обратно. После того, как метки сформированы, процедуру можно использовать хоть миллион раз. Но вызов процедуры в процедуре возможен всегда. И снова понятно почему. Ведь процедура в процедуре не выполняется. И потому ограничений нет. Но как вызывать процедуру на исполнение? Как и всюду -- командой execute. Но можно писать одну букву e. То есть пишем команду
. . . #e [с=1;] abcd другие процедуры ! Команда использует один параметр c (code). Он указывает условие -- выполнять процедуру или нет. Дело в том, что очень часто надо писать какой-то код, который нужен для тестирования, получения дополнительной информации, но в работе не нужен. И вот можно этот код записать в процедуру, а потом иногда выполнять, а иногда не выполнять.
. . . Условие снова реализуется через равенство значения параметра и переменной &. Например, пишем такой код # &=0; #e [c=1;] abcd ! Выполнение процедуры записано. но она не будет выполняться. Потому что для запуска процедуры надо выполнить условие c=&, то есть значение параметра c должно совпадать с значением переменной &. Если не совпадает, то интерпретатор процедуру не исполняет. Ну а если написать #e [c=&;] abcd ! , то тогда процедура будет железно выполняться всегда. И это часто так нужно. Но чтобы не писать лишнего я для этого случая ввел более простой вариант #e _abcd ! Символ подчеркивания указывает выполнять процедуру всегда и параметр c можно не определять.
. . . В ЛЯПе есть несколько команд с переменным числом аргументов. И команда #e одна из них. За названием первой процедуры через пробел можно написать вторую и так далее. Они все будут выполняться по цепочке. Условие выполнения для всего списка одно. А заканчивается список после того, как появляется символ # (новая команда) или @ (конец процедуры) или ! (для всех других случаев). Вот теперь с процедурами все понятно. Однако это только начало длинной истории о том, как еще можно использовать процедуры. Но об этом в следующий раз.

09. . . . И снова о процедурах. В самом начале, в 1-й части, я писал, что процедуры позволяют создать новый язык программирования более высокого уровня. Это может быть новым ЛЯПом любого пользователя. Ведь любой код программирования только для того и создается, чтобы решать задачи. А задач бесконечное множество. И совсем не обязательно каждый раз писать новый код. Часто процедуры представляют собой блоки кода, но могут быть и полноценной программой. Чтобы их можно было часто использовать в многих ЯП процедуры что-то получают на входе и что-то выдают на выходе.
. . . И вот от того, что они получают и что выдают, зависит как много раз их можно будет использовать. Процесс передачи входных данных и получения выходных в многих языках оформляется по разному. В некоторых нет процедур, а есть функции, то есть аналогично математике. У функции есть значение и есть аргументы. Так и записывают как в математике. А если нет, то все равно пишут void (пусто) и все равно ставят скобки для аргументов, а внутри пусто. Кому-то кажется, что это красиво. Еще раз хочу сказать, что любой язык пишется одним человеком, автором языка. И он, как пророк. создает религию. А сколько будет верующих зависит от многих факторов.
. . . В моем ЛЯПе функций нет. Процедура -- это просто кусок кода. Передавать входные данные и получать результат можно бесконечным числом способов, кому как удобно. Есть два числовых массива и один текстовый. Туда все можно записать и оттуда взять. И нет никакой разницы между готовой программой и процедурой. Кто-то скажет, что это минус, и будет неправ. Это очень большой плюс. И сейчас я попробую это доказать. Начнем с того, что среди текстовых параметров есть параметры file и form. Их я сам тоже пишу 4-мя буквами хотя достаточно 3-х. И есть специальная процедура, которая так и называется file. Тут уже нужны все 4 буквы. Выглядит это так #e [file=name.acl; c=1;] file . Конструкция _file для безусловного выполнения тоже используется.
. . . То есть все стандартно за одним исключением. Эту процедуру не надо определять заранее в коде программы. Но нужно указать имя файла с расширением acl относительно папки интерпретатора. И такой файл должен быть по указанному адресу. А в нем должна быть записана процедура. Интерпретатор найдет этот файл, прочитает его код и выполнит его. И ему не придется писать о том какие пакеты надо подключить, какие массивы и переменные использовать. Вызов таких процедур можно делать с любого места и в любой программе потому что тут точка входа и точка выхода определяется началом и концом файла. Таких файлов на компьютере можно записать тысячи. Раньше можно было даже из интернета брать файлы. Но с этим все время происходят изменения. Из соображений безопасности постепенно интернет зажимают, особенно для языка Java.
. . . И это главное преимущество подхода к программированию с глобальной памятью. В Питоне тоже есть нечто подобное, но сделано это во много раз сложнее. Про Java и говорить не приходится. Это хороший ЯП с большими возможностями, но не для всех. Для людей со слабыми умственными способностями он просто недоступен. И есть там такой недостаток, как очень длинные названия операторов. Автор считал, что так ему будет понятнее. А для тех, кто не знает английского языка, все это бесполезно. Чтобы с этим справиться стали писать огромные программы среды разработки. И снова глупость. Впрочем люди разные, некоторым нравится. Java программы могут иметь очень большое число файлов. Эти файлы собираются в зип архивы и все это неплохо продумано. Но в моем ЛЯПе еще проще.
. . . Но и это еще не все. Лично я сам решил делать библиотеку особенно часто используемых процедур и записывать их в папку (proc) внутри папки интерпретатора. И для таких процедур команда их вызова записывается особенно просто, вот так ##name . Это вместо #e [file=proc/name.acl;] _file . Казалось бы и первоначальная запись была не длинной, но такая короче. И более информативная, так как ничего лишнего. И вот такие процедуры я назвал суперкомандами. Они упрощают запись кода, делают его более понятным, не отвлекаясь на лишнее. Сразу скажу, что и этим дело не закончилось. Но об остальном чуть позже.
. . . А пока я расскажу и еще об одной возможности интерпретируемых языков, которой нет в языках компилируемых. Процедуру можно еще записать в текстовый массив t(). Выглядит это так #e [b=2345; le=250;] _text. И вот эту процедуру перед выполнением надо записать, но не в код программы, а в текстовый массив, который состоит из символов текста. Это такая огромная строка текста длиной в 2 миллиона знаков. Каждый знак имет свой индекс. И нужно указать начало текста и его длину. Интерпретатор прочитает этот текст и выполнит его так, как будто он был записан в программу.
. . . На самом деле интерпретатор и записывает его в программу, но временно, исполняет, а потом исключает из программы. Такая возможность в ЯП Питон тоже есть. Когда я работал в Питоне, я только так и делал. Писал код как хотел, потом записывал его в строку, делал нужные преобразования и исполнял. Это была единственная возможность в Питоне отказаться от его грамматики, которая лично для меня кажется дикой. Но, в других интерпретируемых языках я ее не видел. ни в постскрипте, ни в javascript такого нет. В моем ЛЯПе -- это тоже очень мощное средство, потому что есть много возможностей манипулировать с текстом. Об этом я расскажу позднее.

10. . . . Метод суперкоманд очень облегчает написание кода и делает его более компактным. Однако у него есть два недостатка. Для новичков неприятность заключается в том, что надо больше учить и запоминать разных имен и конструкций. Есть люди, способные усваивать только простые вещи и немного. Сложность выше определенного предела им не нравится, так как они не чувствуют себя счастливыми в таких условиях. И таких людей большинство. Тут можно спастись тем, что выучить часть и не учить все. А для конкретных операций суперкоманды очень даже удобны. Но есть и другой недостаток. Суперкоманды невозможно ставить в циклы. Они как бы для одноразовых работ. Например, построить график, или показать анимацию.
. . . Дело в том, что в цикле придется много раз читать код из файла, хотя он уже есть в оперативной памяти. Это не только медленно исполняется, но и напрасно изнашивает винчестер, расходует электроэнергию и вообще неразумно. Кроме того, программа обрастает файлами как снежный ком. Новых суперкоманд можно написать много и часто их код совсем небольшой, а файлы маленькими не бывают. Но и эту проблему удалось решить. Метод решения примерно такой же как кэш в браузерах. Там тоже есть сложность в том, что надо много раз скачивать какой-то файл из интернета и это не быстро и интернет нагружает. Поэтому удобно все, что скачано, временно запомнить и показывать из своих запасов на компьютере.
. . . Ну а в ЛЯПе есть текстовый массив. Можно написать программу, которая перед тем, как выполнять суперкоманду, будет смотреть -- есть она в кеше или нет, если есть, то сразу и исполняем ее из текстового массива, то есть из оперативной памяти. А вот если нет, то тогда скачаем и запомним. Получается так, что первоначально все скачивается, но потом то, что уже скачано, второй раз не скачивается, а сразу используется. И выгодно долго работать с программой. А если какие-то проблемы возникли, то можно программу закрыть и снова открыть. Такие суперкоманды уже и в цикле можно использовать. Интересно, что сама программа, которая анализирует -- скачивать или нет, у меня написана на ЛЯПе, а интерпретатор просто с самого начала записывает ее в тестовый массив и там она работает.
. . . Это было сделано всего несколько лет назад и работает только в последних версиях программы интерпретатора. Но лично у меня старые версии, если и есть, то я их уже не смотрю. И в интернете наверно их нет, даже не знаю. Хотя возможно у кого-то и есть. И еще одно новшество последних версий состоит в том, что хотя старый механизм суперкоманд и существует, но есть новый. Имена старых суперкоманд должны начинаться с буквы и это текст. А есть еще новые суперкоманды, имена которых -- это номер. И вот все эти пронумерованные суперкоманды записываются в один файл proc00.txt в главной папке, каждая суперкоманда в отдельную строку этого файла. При этом символ конца строки в коде самой суперкоманды заменяется на ~. Для интерпретатора все равно что исполнять. А для человека есть специальная программа, которая скачивает из файла одну строку и заменяет символ ~ на признак конца строки. И код можно легко читать и редактировать. А потом вернуть на место.
. . . И это уже весьма существенное расширение языка при небольшом числе файлов дистрибутива. А описание языка я разделил на два файла. В одном описаны все команды и их операции, в другом все пронумерованные суперкоманды, которые я предлагаю скачать в архиве вместе с интерпретатором. Размер текста там небольшой, а возможности ЛЯПа сильно увеличиваются. Но интерпретатор способен исполнять и очень много специальных программ по любому вопросу. А также готовых программ универсального назначения. Есть возможность очень много всего сделать вообще не изучая ЛЯП. Список готовых программ все время растет, и я сам иногда предпочитаю использовать готовую программу, а не писать новую. По этой причине есть еще третий список с описанием готовых программ. И они тоже все пронумерованы. И код всех готовых программ тоже записан в один файл pro00.txt
. . . Есть также и механизм использовать готовые программы в коде новой программы, но я его еще не достаточно оптимально отработал. Также требует оптимизации механизм вставки новых пронумерованных суперкоманд в файл proc00.txt. а также редактирования уже существующих суперкоманд. Но я сам пока справляюсь, а других пользователей нет и потому вопрос не актуальный. Про процедуры я все написал. Осталось только сказать, что одни процедуры могут вызывать другие процедуры и так далее. И это все работает. Но так нельзя делать до бесконечности. Пока в программе предел вложений 45. Это очень много, но могут быть отказы и по этой причине.
. . . И еще один лайфхак. Получается так, что надо сначала писать все процедуры, а потом код программы. Не всем это нравится. Мне тоже не нравится. Но можно и саму программу тоже написать в процедуру, назвать ее main и поставить в начале. А в конце только написать #e _main ! И все. Тогда весь код будет состоять из процедур. Разные процедуры будут выполнять разные работы, можно организовать таблицу кнопок и выбирать что конкретно исполнять. Но у такого метода есть и альтернатива. Вместо таких процедур можно писать просто #case 1 . . . #case 2 . . . и так далее, а выбор тоже делать из таблицы кнопок. В этом месте я закончил рассказывать об общей структуре ЛЯПа. Пора переходить к описанию отдельных команд. И впереди еще много информации.

11. . . . Самые первые языки программирования умели только вычислять. Причем вычислять в циклах, с процедурами, получать много чисел из файлов и записывать результаты расчетов в файлы. Про массивы я уже написал. В моем ЛЯПе есть целый массив i(), реальный массив r(), текстовый массив t(). И все можно читать в массивах, но не совсем удобно. Удобно иметь еще и переменные, которые имеют имена. В МЛЯПе переменные тоже организованы в три массива. Есть отдельный массив однобуквенных переменных от a до z, затем от A до Z и еще $, %, &. Всего 55. Большие и маленькие буквы -- это разные переменные. Они реально разные, то есть имеют разный номер в таблице юникодов.
. . . Однобуквенные переменные используются чаще всего. Но есть еще один массив, в котором все указанные переменные можно писать с цифрой от 0 до 9. Этот массив образует матрицу 55*10. Сначала идут все переменные с 0, потом с 1, и так далее. И есть еще третий массив переменных из двух букв, которые образуют матрицу 55*55. И есть и есть команды, которые реально используют переменные как массивы. Но у этих массивов своих имен нет. Просто нужно знать порядок, кто за кем идет. Есть еще целый и массив параметров s(), я о нем рассказывал раньше. Вот этот массив имеет имя, и его элементы тоже имеют имена, и он достаточно часто используется и как массив, и по именам.
. . . В каждый момент все переменные имеют какие то значения, которые могут изменяться. Присвоение значений делается так a=25; То есть слева переменная, знак равенства, число, точка с запятой. И между этими знаками может быть сколько угодно пробелов. Но я их не пишу, всегда пишу слитно. А все операции присваивания значений переменным, являются аргументом команды вычислений. Она имеет имя c (computing), но его можно не писать. Это единственная команда, которую можно использовать без имени. Но символ # и пробел после него писать надо. Также, как и в команде #e аргумент переменный и заканчивается на символах #, @ и ! .
. . . Вот пример вычислений # a=25; b=sin(a); c=a*b; ! Все математические функции имеют имена из трех букв, вот их список abs() == абсолютное значение, sqr() == квадратный корень, log() == натуральный логарифм, exp() == экспонента, sin() == синус, ars() == арксинус, cos() == косинус, arc() == арккосинус, tan() == тангенс, art() == арктангенс, rnd() == случайное значение, int() == целая часть, sgn() == знак числа, 1 если аргумент > 0, 0 если 0, иначе -1, sfi() == синус интеграл Френеля int(0,x)dt*sin((pi/2)*t^2), cfi() == косинус интеграл Френеля int(0,x)dt*cos((pi/2)*t^2), bj0() == функция Бесселя J[0](x), bj1() == функция Бесселя J[1](x). То есть список кроме стандартных функций, какие учат в школе, имеет еще интегралы Френеля и функции Бесселя.
. . . А математические операции записываются так { ( ) < > ^ * / + - }. Порядок внутри { } указывает порядок выполнения. Я уже писал ранее, что кроме стандартных операций есть еще вычисление минимума и максимума из двух. Эти операции нужны для задания логики. Вся логика записывается математически. При этом (a == 0 ИЛИ b == 0) записывается так a*b=0. Или еще (a == 0 И b == 0) записывается так abs(a)+abs(b)=0. В других языках на этом все и заканчивается. Но в ЛЯПе есть еще две интересные команды. Все дело в том, что раз память глобальная, то одни процедуры могут портить память, которая нужна для других процедур.
. . . Чтобы этого избежать приходится вручную временно запоминать значения всех переменных в элементах большого реального массива, а потом восстанавливать их обратно. И для этого надо писать цепочки типа r(k)=a; r(k+1)=b; и так далее. Если переменные идут подряд, то есть команда #pas n a r(k) . Она копирует n значений массива переменных, начиная с a в реальный массив, начиная с индекса k. Но бывает, что необходимо копировать разные участки самого реального массива r(), или участки одного массива в другой массив. Это все тоже выполнит данная команда. В вычислениях она очень часто используется. В других языках я ее не видел. Тут, фактически, используется цикл но он записан в неявной форме.
. . . Однако иногда надо запоминать переменные в произвольном порядке или присваивать разные значения элементов массива. Для этого есть команда #d 4 r(k) a b f g ! . Здесь первый аргумент команды -- это число присвоений. Далее указывается тип и начальный индекс массива и потом значения или переменные. Написанная команда эквивалентна такой цепочке r(k)=a; r(k+1)=b; r(k+2)=f; r(k+3)=g; . Ясно, что первая запись короче и более наглядная. Но есть и обратная команда #v 4 r(k) a b f g ! . Она делает обратные присвоения. То есть эквивалентна такой цепочке a=r(k); b=r(k+1); f=r(k+2); g=r(k+3); . Эта пара команд как раз удобна для операций временного сохранения значений в начале кода и их восстановления в конце. Таким способом глобальные переменные временно превращаются в локальные. Эти команды особенно часто используются в суперкомандах, но могут использоваться и в основном коде. Следует отметить, что аргументы этих команд тоже переменные, за одной группой из (n r(K) a b c . . .) может следовать другая и так далее. И все заканчивается так же, как и в других случаях, то есть на символах # @ ! .

12. . . . В предыдущем разделе рассказ о вычислениях не закончился. Точнее вычислять уже можно все. Векторы и матрицы, то есть одномерные и двумерные массивы, можно вычислять в цикле. Но такой способ вычислений не очень хорош, так как результата вычиcлений придется очень долго ждать, если число повторений порядка миллиона и больше. И вот как раз для вычислений векторов и матриц существует команда #ma от первых букв слова mathematics. Я уже писал ранее, что векторы определяются параметрами b (begin) и le (length), а матрицы -- параметрами b, nx, ny.
. . . Во всех операциях, где используется константа, она берется из переменной C, а вторая из D. Если используются два массива, то первый индекс второго сдвинут от первого индекса первого на параметр trx. А операции указываются параметром op и с векторами они такие: vac [ vector add constant, v()+C ], vmc [ vector multiply constant, v()*C ], vic [vector init constant, v()=C], via [vector init ariphmetic, v(i)=C+D*i], vig [vector init Gaussian], vsi (sine), vco (cosine), vex (exponent), vlo (logarithm), vpo (power), var (limit by aria), vor (ordering), vin (integer), vba (byte to r()), vva (v v add), vvm ( v v multiply), vvs (scalar product).
. . . Если надо всю матрицу изменить, например, сложить с константой, умножить на константу, или еще что, то она трактуется как вектор размерности nx*ny. Но есть и специальные операции с матрицами, например, транспонирование (mtr), интерполяция (mmi), инверсия индексов (mii), свертка с гауссианом (mcg), нормировка строк (fno), быстрое преобразование Фурье (fft) и много других. Более подробную информацию можно получить в справочнике по моему ЛЯПу. Вот ссылка на этот справочник https://kohnvict.ucoz.ru/acl/acl-info.htm . Для ускорения расчетов с большими массивами надо использовать команду #ma с указанными операциями. Но разумно ознакомиться со всеми операциями. Возможно среди тех, что не указаны в этом тексте вам тоже что-то понравится.
. . . В файлах обычно записано много чисел, которые образуют массив. Для полного цикла расчетов надо уметь читать числа из файла и записывать числа в файл. В моем ЛЯПе это делает команда #io . Название взято из первых букв слов input, output. Но для работы с файлами надо знать основы операционной системы (ОС), в которой работает программа. Программа тестировалась в двух ОС: Виндовс и Линукс. Для простоты первоначально я предполагал, что интерпретатор работает в какой-то папке ОС и использует только файлы внутри этой папки. Главная папка имеет название null, но в ней может быть много папок.
. . . И есть рабочая папка, в которой находится файл с той программой, которая исполняется. Но эту папку можно переопределить. Делает это операция fold команды #f, вот пример, #f [op=fold; file=new;]. После выполнения этой команды рабочей папкой становится папка new относительно папки null. В ОС Линукс лучше так все и делать. А в системе Виндовс, если рабочей папкой объявлена папка null то можно указывать путь начиная с буквы диска, например, c:/_vk/и_так_далее. Интерпретатор проверяет наличие символа : во второй позиции имени файла. И если он есть, то путь общий, а если нет, то относительно папки null. Определение рабочей папки позволяет короче писать имена файлов. Но не всегда и не во всех командах рабочая папка используется. Есть команды, где нужно всегда указывать имя файла относительно папки null. Например, команда #sys .
. . . Вернемся к команде #io . У нее есть 8 операций, 4 для чтения и 4 для записи. Операции имеют имена из двух букв. Первая буква r (read) для чтения и w (write) для записи. Два варианта. Вторая буква имеет 4 варианта f (format), d (data), b (byte), t (text). Для чтения и для записи используются одни и те же параметры, но для чтения дополнительно используется параметр le, который принимает разные значения при разных значениях второй буквы. Какие же это параметры. Параметр file=имя_файла; указывает имя файла с учетом сказанного выше. Параметр fir (first) указывает тип и первый индекс массива, например, fir=r(1); . параметр n указывает сколько единиц (чисел) будет записано или прочитано.
. . . Параметр form указывает формат. В основном он используется при записи данных типа f. Дело в том, это запись чисел текстом, который понятен человеку, который учился в школе. При чтении нужно писать *N, где N -- это число или переменная, указывающая сколько строк надо пропустить в файле прежде, чем начать чтение. А считываются все n чисел, разделенные пробелами и записанные в произвольном порядке. Запись чисел в формате возможна только из массивов i() и r() и есть только два формата (form=*N;) указывает сколько чисел надо записать на одной строке, N может быть числом или переменной, и (form=EN.M.L;), где N указывает число чисел на одно строке, M -- полное число позиций на одно число, L -- число позиций на дробную часть. Должно выполняться условие M > (L+7).
. . . Запись чисел текстом и чтение таких чисел удобны при чтении человеком. Но если чисел десятки тысяч, то человек так много прочитать не сможет, а для этой записи надо много символов и интерпретатор дольше работает. По этой причине часто числа записывают в компьютерном коде (тип d). Его невозможно прочитать, но для компьютера эта запись легче. Но компьютер может записывать числа разными способами. Чтобы это указать используется параметр mo (modification). Если mo=1 то запись реальных чисел длиной 4 байта. Если mo=2 то запись целых чисел длиной 4 байта. Если mo=3 то запись реальных чисел длиной 8 байт. Если mo=4 то запись целых чисел со знаком длиной 2 байта. Порядок записи как в Java, то есть старшие вперед. Если mo=5 то запись целых чисел без знака длиной 2 байта и порядок байтов указывает параметр ord. Если он равен 0, то как в Java, а если 1, то как в Виндовс. И при чтении параметр le указывает сколько байтов надо пропустить в файле перед тем как начать чтение. Есть специальные режимы, которые можно прочитать в более подробном описании.
. . . Запись и чтение типа b имеет дело с байтами и используется в основном для чтения или записи текстов в Виндовс кодировке. Но тем не менее байты записываются со знаком. Первые 127 чисел соответствуют ascii таблице сразу, а при записи русских символов в юникод-кодировке из них вычитается число 1104 и они попадают как раз во вторую часть байта из 128 символов. А при чтении число 1104 добавляется. Дело в том, что массив t() состоит из юникодов (два байта) и все получается. Параметр le используется в том же смысле. что и выше, то есть пропускается столько байтов, сколько он указывает.
. . . Запись и чтение типа t тоже работают с текстовым массивом. Но эти операции проверялись только для первых 127 юникодов. Такая запись хороша для записи программ и чисел. Подробности можно посмотреть в более полном описании. Про этот тип записи пока рано говорить, он нам понадобится позднее. Важно, что уже на этом уровне, если даже больше ничего не учить, можно выполнять различные вычисления после чтения массивов из файла и записи обратно в файл. Именно так я работал много лет на фортране на компьютере БЭСМ-6 в прошлом веке. И какие-то задачи удавалось решать. Правда результаты нам выдавали на бумаге, а сейчас принтеры редко используются. Но текстовые файлы можно смотреть в любом текстовом редакторе.
. . . В заключение этого раздела я покажу пример конкретной программы, которая вычисляет две функции Бесселя и рисует их на графике. Вот код этой программы
. . . # J=99; n=400; C=0; D=0.2; xm=C+D*(n-1); #ma [op=via; b=J; le=n;] # j=J;
. . . #rep n # x=r(j); r(j)=bj0(x); r(j+n)=bj1(x); j=j+1; #end
. . . #d 7 A J n 2 0 xm 247 1100 #pr test|Bessel 0,1\E ##1
Здесь все уже должно быть понятно за исключением последней строки, в которой записан аргумент суперкоманды номер 1, которая рисует график двух функций Бесселя, которые были вычислены в первых двух строках. Если скачать интерпретатор и записать эту программу в файл, а потом открыть в редакторе для программ, то по клавише F12 можно получить график на экране и в файле test.png в папке, где записана файл программы. Описание суперкоманд есть в интернете, вот ссылка https://kohnvict.ucoz.ru/acl/acls-info.htm .

13. . . . После 12 мини-глав уже можно писать программы с вычислениями, читать и записывать массивы в файлы и даже рисовать график. Но современные программы очень плохо выглядят, если у них нет интерфейса с пользователем. Чтобы создавать полноценный интерфейс нужно уметь пользоваться графикой и манипулировать с текстом. В этом разделе мы рассмотрим что можно делать с текстом. Преимущества одного большого глобального массива символов t() в том, что вся такая работа предельно упрощается. Очень легко можно писать программы с разбором текста. В разных языках есть такое понятие как регулярное выражение. Они есть в Javascript и Java. Мне приходилось использовать их в Javascript и это всегда головная боль. Мой язык ругают за компактность и сложность, но там все запредельно сложно.
. . . Такое я не люблю и такого у меня нет, то есть возможности есть, но все сделано иначе. Дело в том, что я иногда перевожу свои программы на моем ЛЯПе в Javascript, чтобы показывать их в интернете. И это возможно и даже не сложно. И вот с текстом всегда проблемы. Без регулярных выражений все сделать невозможно. Итак, все тексты находятся в текстовом массиве, но в разных местах. Снова начальный индекс строки является ее именем. а длина строки просто указывается как обычно, только по разному записывается. Это сделано с помощью служебного массива, элементы которого не имеют имен. То есть от s(3) до s(5).
. . . Тут мне могут быть претензии, что это не красиво и не очень удобно. Согласен, виноват, не постарался. Но попробую объяснить почему так получилось. Дело в том, что у меня таблица имен элементов служебного массива сопряжена с самим массивом целых чисел s(). Но первые 6 имен относятся к текстовым параметрам, из которых используются только 4. Это fir (1), op (4), file (5), form (6). Были еще и 2, 3, но потом я от них отказался, места оставил для будущего расширения языка, но так пока и не расширил. И вот первые 6 элементов массива s() остались без имен. Но не использовать их мне было жалко и я все же решил их использовать только как целые числа -- элементы массива s(3). А потом привык и уже не захотел ничего менять. Так что начало конкретной строки определяется параметром s(3). А записывает строку в текстовый массив команда #pr (print). Она как раз появилась в примере конца предыдущего раздела.
. . . То есть результат выполнения такого кода . # s(3)=1; #pr abcd\E . будет такой t(1)=97; t(2)=98; t(3)=99; t(4)=100; Почему так? А все просто. Текстовый массив -- это тоже числа. но не простые, а юникоды символов. Команда # s(3)=1; устанавливает запись в текстовый массив с 1-го индекса. А команда #pr принимает текст, конвертирует символы в юникоды и записывает их в массив t(). Но надо указать где закончить читать символы. Для этого используется конструкция \E . То есть вот так все просто. Пишем текст, получаем в массиве t() целые числа. Потом их можно записать в файл, а в файле редактор снова покажет текст. Причем в кодировке Виндовс массив t() можно записать байтами. А вообще текст операциями rt и wt команды #io должен записываться юникодами. Но я до сих пор даже не проверял это. Записываю только первые 129 символов. И вообще очень редко так записываю. Но должно работать.
. . . Итак, простой текст мы записываем. Но хотелось бы больше. Например, записывать числа текстом по определенному формату. В фортране это делается очень просто. И вот тут облом. В языке Java форматов нет. Я уже много раз писал. Каждый ЯП пишется человеком. А у человеков свои заморочки. Автор языка Java не захотел этим заниматься. И пришлось мне самому программировать форматы. Понятно, что команда #pr не имеет параметров, но ее аргумент может быть сколь угодно сложным. И в нем как бы есть свои команды. Они начинаются с символа \ и их имена имеют одну букву, но могут иметь аргументы.
. . . Начнем запоминать какие же форматы есть у команды #pr . Самое простое -- целые числа. Им надо просто выделить длину строки и все. Например, \I5 a b; тут символ I указывает на запись целыми числами, 5 указывает, что на число отводится 5 позиций (символов), пробел после I не обязателен, так как все имена форматов имеют длину 1 символ и интерпретатор это знает. А вот потом надо пробел и через пробел можно писать числа или переменные или элементы числовых массивов. Список может быть сколь угодно длинным и все заканчивается символом точки с запятой. Если число имеет меньше разрядов, то слева записываются пробелы чтобы длина числа была 5 позиций. Но можно писать отрицательную длину и тогда вместо пробела записывается 0. Вот примеры \i5 25; дает строку ( 25), а \I-5 25; дает строку (00025).
. . . Для реальных чисел для простоты есть универсальный формат без параметров \G . Он все числа записывает на один манер, а именно, ( -1.2345-67). То есть 11 символов, первый -- пробел, второй -- знак минус или снова пробел, знак плюс не пишется, третий -- число, потом точка, еще 4 числа, потом знак, пишется и плюс и минус, и два числа для степени 10. Такой же общий формат записывает и команда #io . Но есть еще формат \N8 3 a; . У него два аргумента. Первый можно писать без пробела, второй -- после пробела. Он записывает так ( -1.234). То есть указывается общая длина числа и длина дробной части, лишние позиции заменяются пробелами. И второй формат \B10 2 a; записывается так ( 1.23E+00). В отличие от формата N тут показатель степени 10 всегда пишется, даже нули, и пишется буква E. Этот формат сделан для совместимости с программами, написанными на других языках, которые так пишут.
. . . Есть еще один универсальный формат без параметров \S . Его можно использовать всюду, но реально он создавался для показа графиков. Его фокус в том, что он исправляет ошибки расчетов. так числа 2.44999912345 и 24500012345 оба запишутся как ( 2.45 ). На графиках всегда ставится одно число и пробелов спереди и сзади раньше не было. Но потом захотелось писать в таком формате несколько чисел подряд и теперь число пишется с пробелами. Также у этого формата есть ограничение дробной части 4-мя позициями с округлением последнего разряда. И совсем редко нужный формат \O записывает число с машинной точностью. В этом случае появляется возможность делать собственный формат в моем ЛЯПе.
. . . Итак, мы записываем текст и числа. Но и это еще не все. Бывают юникоды, которых нет на клавиатуре. Их невозможно напечатать. А в массиве t() все юникоды. Для этого есть команда \U a b c*n d e; Ее аргументами могут быть числа, переменные и элементы массивов. Конструкция c*n означает повторить n раз число с. Она позволяет вводить в текстовый массив юникоды без проблем. Но для простоты и быстроты работы интерпретатора введена модификация этой команды \u у которой аргументами могут быть только числа. Снова повторяю, что первый пробел не обязателен. Так что конкретный юникод можно вводить как \u125;
. . . Есть еще одна проблема. Некоторые символы используются в ЛЯПе как служебные для самого ЛЯПа. Их надо вводить как команды и тогда проблем нет, то есть \b (назад на один символ, \u8;), \t (табуляция, \u9;), \n (конец строки, \u10;), \r (возврат каретки, \u13;), далее команды означают ввод тех самых символов, которые записываются: \' \" \\ \@ \# \[ \] . И есть еще одна команда \- . Она ничего не вводит. Но фокус в том, что команда #pr пропускает все пробелы после себя до первого символа и все пробелы после каждой ее команды, и не только пробелы, а также и концы строк. И вот команда \- нужна только для того, чтобы пропустить пробелы и концы строк. Вообще говоря, эти команды не очень то и нужны, потому что все можно вводить по юникоду. Но так есть во всех языках т я тоже решил это сделать, так как юникоды не все помнят наизусть, а так нагляднее.
. . . Есть еще команды для удобства записи и для полезной информации, которую знает только интерпретатор. Так команда \D вставляет в текст текущие дату и время, \Pn вставляет в текст значение текстового параметра (n=1,4,5,6), \F вставляет в текст имя программы интерпретатора, \H вставляет в текст имя рабочей папки в данный момент с символом / в конце, но только в том случае, если она была объявлена операцией #f [op=fold; fille=name;], \M вставляет в текст полный путь к папке интерпретатора с символом / в конце. Но возможности форматов можно расширять и дальше.
. . . Наконец, вероятно, самой важной является команда \Ta b . Она вставляет в текстовый массив другой кусок текстового массива, начиная с индекса a и b символов. Эта очень удобная команда является аналогом процедур для кода. Можно один раз определить некий текст и потом много раз вставлять его в разные места. Это не только экономит написание кода, но и является очень важным способом манипулирования текстом. Например так можно передавать текст из одной программы в другую. Достаточно указать два числа и все. Лично я это использую очень широко.
. . . Осталось объяснить как формируется текст. Начало текста задает параметр s(3). Я уже писал об этом. После выполнения команды #pr параметры s(4) и s(5) возвращают параметры строки, то есть начало и конец. Одновременно параметр s(3) автоматически меняет свое значение на s(4)+s(5). То есть каждый раз указывать начало не надо. Если написать #pr txt1 #pr txt2, то тексты txt1 и txy2 встанут второй после первого . Узнать размер строки после нескольких печатей можно так. Запоминаем начальное значение a=s(3); . А после нескольких печатей длина строки будет s(3)-a; . Вот и все. За все время работы мне всего этого хватало. Но если не хватит, то очень просто добавить еще форматов.
. . . Прелесть в том, что весь интерпретатор написан на языке Java одним человеком. А в Питоне это не так. Там разные люди на разных языках писали разные пакеты и исправить что-то не так уж и просто. Пользователи как верующие молятся на то, что есть, и ничего не могут сделать, чтобы изменить в языке хоть что-нибудь. Впрочем я тут могу быть не прав. Возможно что-то и там можно изменить. точнее добавить. Я же написал инструкцию как добавлять процедуры математических расчетов в ЛЯП. На языке Java это самая легкая часть.

14. . . . Работа с текстом позволяет писать программы различных компиляторов, то есть преобразователей одной системы записей в другую систему. В частности, автоматизировать работу по созданию сайтов интернета. Форматирование текста -- это только часть таких возможностей. Так же точно, как вычисления имеют дело с массивами и различными операциями над массивами, многие преобразования больших текстов надо делать одной операцией. И такие операции выполняются сразу с файлами. Для них есть команда #f , которая имеет очень много операций.
. . . С другой стороны, оформление многих сайтов и вообще программ делается с использованием картинок, то есть двумерных изображений, которые представляют собой либо матрицу чисел для монохромных картинок, либо три матрицы -- для цветных картинок. Обработка таких картинок, то есть сжатие матриц в различные форматы, например, jpg и png, или получение матриц из сжатых файлов, а также типовые картинки научной графики -- это тоже часто необходимая техника. Для нее есть команда #w , у которой не так много операций, зато очень много параметров.
. . . Хотя многие картинки интерпретатор делает сразу в готовом виде, но далеко не все. И должна быть возможность рисовать картинки, используя графические примитивы. В ЯП Java первоначально использовалась система графических примитивов компьютеров первого поколения с малым числом пикселей на экранах. А затем была создана более сложная система, копирующая язык Постскрипт. Если в первой системе все было просто, то во второй системе линии имеют толщину, контур -- это отдельный объект и может быть весьма сложным, цвета и заливки области весьма разнообразцы. В ЛЯПе есть команда #g для простой графики, и команда #eg -- для второй системы, аналогичной тому, что есть в постскрипте.
. . . Но начинать использовать графику лучше всего не с команд, а с суперкоманд, то есть готовых процедур, написанных уже на ЛЯПе, которые все делают намного проще. Описание суперкоманд есть в интернете и той информации, которая там содержится, вполне достаточно. Но там нет информации о том, как и для чего это все можно использовать. Я попробую это рассказать. Исторически суперкоманды поначалу писались как просто процедуры. И те их них, которые приходилось часто использовать постепенно меняли свою структуру таким образом, что у них появлялись входные данные (ВД) и универсальность.
. . . Но и эти структуры за много лет моей работы с ЛЯПом все время изменялись. И так получилось, что ВД для разных суперкоманд имеют разные структуры. До сих пор я не привел их в единому стилю, так как пока не знаю какой стиль лучше. Номера суперкоманды получили не сразу, и они не соответствуют хронологии их создания. Я не стремился в этом вопросе наводить красоту, потомучто это по сути не так уж и важно. Поэтому нет особых причин почему суперкоманда номер 1 рисует научный график для серии функций одной переменной. Возможно это мало кому надо но мне надо и часто. Я постоянно рисую такие графики.
. . . Ну, и раз эта суперкоманда уже появилась в программе, написанной в конце мини-главы 12, то я с нее и начну. Итак, она принимает на входе двумерный массив чисел, для которого надо указать его начало, число точек в каждой функции (строку матрицы) и число функций (число строк). Тем самым есть ограничение -- все функции имеют одинаковое число точек. Функции рисуются на перпендикулярных осях и записаны для значений аргумента с постоянным шагом. Достаточно указать первое и последнее значение аргумента, а все остальное программа делает сама. Затем необходимо указать номер цвета, которым рисуется первая кривая. Про это я еще не рассказал, расскажу в следующей мини-главе. И еще один сложный параметр одновременно показывает масштаб картинки и режим записи картинки в файл и показа на экране. Это все можно делать или не делать. Наиболее вероятное значение этого параметра 1100, то есть масштаб 100%, и все показывать и записывать в файл.
. . . Это минимальные числовые параметры. Они записываются в переменные A B C D E F G командой #d 7 A .... Дело в том, что эти переменные образуют массив и команда все делает правильно. Но есть еще текстовые параметры. Вот их надо напечатать командой #pr . Нужны два текста. Первый -- это имя файла без расширения. оно всегда png. И файл появится в рабочей папке. Второй -- это текст, который будет показан над графиком. Эти два текста записываются как один и разделяются символом вертикальной черты. Я очень часто так делаю. Вот и все. Остальное суперкоманда делает стандартно и меня это устраивает. Ну а если не устраивает, то надо копировать текст суперкоманды в процедуру и менять там то, что хотите изменить. И вот тогда уже понадобится знание работы команды #w.
. . . А вот вторая суперкоманда показывает двумерные массивы (матрицы) как картинки. Она еще более сложная, но все равно намного проще, чем тот код на ЛЯПе, который ее исполняет. То есть мой ЛЯП имеет высокий уровень, но суперкоманды-- еще более высокий. Они позволяют очень быстро и просто делать сложные вещи. В описании показан пример вызова, я его скопирую с изменениями вот так
. . . # F=1; #d 15 r(F) x1 x2 x3 x4 nx y1 y2 y3 y4 ny z1 z2 z3 z4 nz #d 5 A J n1 n2 1100 13 #p [pa=3; em=0;] #pr filename|title\E ##2
. . . Здесь строка подлиннее, но все просто. Дело в том, что здесь три оси: X, Y, Z. Две оси для двух аргументов и одна для функции. И их надо размечать вручную. Это делается с помощью 5 чисел. Первые два числа -- это начало и конец оси в тех же единицах, что и первый аргумент функции, которую описывает матрица. Затем идут значения первой длинной риски шаг до следующей риски и число коротких рисок между ними. Остальные две оси размечаются точно также. Это для особенно фасонной картинки. А если надо попроще, то можно использовать суперкоманду 31. Она принимает первые два числа их каждой 5-ки и добавляет остальные. Но ее аргументы другие, вот такие # F=1; #d 6 r(ZZ-30) x1 x2 y1 y2 z1 z2 ##31 . Тут ZZ -- максимальный индекс массива r(). Эта переменная автоматически в самом начале работы программы, а результат получается в r(F).
. . . А вот в массив переменных А надо записать 5 чисел. Начало матрицы, ее размеры, тот же параметр видимости и масштаба и еще один параметр из двух разрядов, каждый из которых показывает сколько пикселей надо делать под каждую точку по осям X (левое число) и Y (правое число). Но дополнительно надо указать еще палитру цветов. Это указывает параметр pa. Он может принимать 4 значения 0, 1, 2, 3. Но наиболее интересными являются 0 и 3. При этом 0 -- черно-белая карта цветов, 3 -- цветная карта с палитрой из внешнего файла. И вот тут есть возможность менять внешний файл при одном и том значении параметра pa. Пока есть только два файла с номерами 1 и 2. Номер 1 -- стандартная карта, номер 2 -- специальная карта. Это сделано относительно недавно. И тут выбор реализуется суперкомандой номер 42. Выглядит это так # NP=2; ##42 .
. . . Но есть еще возможности. Команда #d 5 A определяет 5 переменных A B C D E . При положительных значениях D и E матрица рисуется картинкой и к ней дополнительно есть оси и карта цветов. Функция нормируется на интервал от 0 до 1 и выставляется ось для этих значений. А минимальное и максимальное значения реальной функции показывается над графиком. Если D отрицательно, то рисуется только голая картинка без масштабирования, то есть 100% размер в пикселах. Но режим показа как раньше. Если E меньше нуля, то ось карты цветов ставится как указано во ВД, и функция не нормируется. А в остальном используются модули этих переменных.

15. . . . Я показал как можно вычислять на компьютере, используя мой ЛЯП и как можно показать результаты вычислений векторов (функций одного аргумента) и матриц (функций двух аргументов). Но речь шла о так называемой растровой графике. Она в самом начале имитирует экран компьютера, то есть задает прямоугольную область, которая разделена на пиксели -- точки, которые на самом деле могут быть квадратиками, разного размера. Грубо говоря матрица показывается так, что каждый ее элемент рисуется квадратиком заданного размера и цвета. Соответственно вместо наклонной линии получаем лестницу. Или эскалатор, так как многие молодые люди по лестницам уже не ходят, а эскалатор есть в метро.
. . . Чтобы получить высокое разрешение картинки в этом случае надо очень много точек и маленький размер квадратиков. На экране это невозможно, зато возможно на принтере. Но принтер печатает матрицу точек, а ее надо записать и файлы получаются огромные. По этой причине очень давно придумали векторную графику. Векторная графика вместо картинки записывает программу как эту картинку нарисовать. А принтер или специальная программа на компьютере рисует картинку так сказать на месте. Если на картинке нарисованы 5 линий и 5 кругов, то программа рисования будет очень компактной, и что самое главное с предельно высокой точностью. Ведь все зависит только от прибора, а информация записана очень точно.
. . . Например, линия записывается координатами ее начала и конца и эти координаты можно записать с 7-ю знаками и даже больше. С кругом еще проще -- две координаты и радиус. И вот когда-то самым массовым языком записи такой векторной графики и был постскрипт. Самый первый продукт компании Адоб, которая сейчас больше известна как автор программ pdf формата и фотошопа. Суперкоманды ##1 и ##2 рисуют растровую графику на экран компьютера с малым числом пикселей. Поэтому линии там не имеют толщины, точнее у них толщина 1 пиксель. Для научной публикации это не годится. Многие западные научные журналы до сих пор требуют рисунки в постскрипт формате.
. . . В этих рисунках линии имеют толщину фасоны окончаний, фасоны углов и вообще все прописывается очень детально в расчете на матрицу с очень большим числом пикселей. В моем ЛЯПе суперкоманд, которые рисуют в постскрипт формате нет. Но вот готовые программы, которые это делают, есть. Дело в том, что для повседневной работы это не нужно. А когда надо более красиво и для публикаций, то всегда можно сделать по программе. И снова я хочу объяснить чем интерпретируемый язык отличается в лучшую сторону от компилируемого. Дело в том, что готовые программы тоже написаны на ЛЯПе. Они ничем не отличаются от процедур. Они тоже просто текст. И в любой программе на ЛЯПе очень легко использовать автоматически и готовые программы.
. . . Более того, можно и исполняемые программы использовать. Но для этого уже надо подключать операционную систему и тут есть проблемы, если ваша программа должна ждать результатов выполнения другой программы. Вашу программы придется остановить. Полностью автоматически она работать не сможет. Мне в моей жизни приходилось так работать. Было время в 90-е годы и в начале 00-х когда я работал в Германии Франции. А там были рабочие станции и система Юникс. Эту систему я не знал, но дело не в системе, а в ее программах. В системе все же был фортран и был постскрипт. И вот я делал расчеты на фортране, потом с помощью своей же программы на фортране vkPS я генерировал постскрипт рисунки. А потом приходилось ждать внешнюю программу, которая их показывала. И вот это было не быстро.
. . . Дело в том, что интернета тогда не было, но были локальные сети внутри самой организации. И вот эта внешняя программа была не на компьютере а в этой сети. И тормозила. Интересно, что одна из таких моих программ работает во Франции до сих пор. Именно в такой манере. Сейчас бы я на своем ЛЯПе сделал программу намного более удобную, но меня там больше нет. То есть внешние программы все же не очень удобно. А программы на том же интерпретируемом языке, на котором и та программа их вызывает -- это удобно. Более того. В этом случае сам ЛЯП становится бесконечно большим. И любая программа, написанная на нем, может исполнить все программы, которые были написаны всем человечеством за все время.
. . . Как раз по этой причине я не буду здесь рассказывать как работают эти программы. Для них есть другое описание в интернете. В мини-главе 12 я давал ссылки на справочники по ЛЯПу и суперкомандам. Так вот все три файла находятся в одной папке и имеют названия acl-info, acls-info и aclp-info. Последний файл для готовых программ. Программы создания графики в eps формате я написал очень давно и самые разные. Первое время я их писал для других людей, в основном соавторов по работе, а сам не использовал. Мне проще было сразу писать на постскрипте. Но потом я научился писать их так. что и мне самому стало удобно ими пользоваться.
. . . И это одна из многих областей применения ЛЯПа. Она состоит в том, что можно написать какую-то программу вручную и потратить на это какое-то время. Потом оказывается, что таких программ надо много, и они мало чем отличаются. Можно копировать, но не всегда это удобно. И проще написать программу, которая сама будет генерировать стандартный текст и добавлять туда переменные куски, формируя их из входных данных. Так можно писать не только eps графику, но и сайты интернета, презентации докладов, анимации фото-альбомов и много чего еще. Для всего этого достаточно иметь механизм манипулирования с текстом. Про этот механизм я рассказал в мини-главе 13.
. . . В частности оказалось, что переписать программу на моем ЛЯПе в язык Javascript совсем не трудно. Но в Javascript графика появилась намного позднее, чем в Java, и даже чем в моем ЛЯПе. Язык Javascript мне нравится. Он не совсем такой, как ЛЯП, но соответствие установить можно. Однако он совсем не годится для очень многих задач, так как не имеет возможности работать с файлами. Точнее читать то файлы он может в ограниченных пределах. А вот записывать нет. Если надо что-то показать или исполнить музыку, то все ОК. А вычислять без записи в файлы невозможно.

16. . . . Уметь что-то вычислять на компьютере и показывать свои вычисления на графиках -- это хорошо, но недостаточно. В наше время смартфонов надо еще уметь делать программы, которые общаются с пользователем. И практически все современные языки это умеют, причем в старых языках все это было сделано еще в прошлом веке и частично сохранилось в том же виде. Но тогда число пикселей на экране по каждому направлению было небольшим, а теперь стало больше. И готовые элементы интерфейса стали очень маленькими. Это касается и элементов операционной системы.
. . . По этой причине я все реже их использую, хотя все, что было в языке Java, есть и в моем ЛЯПе, но не в виде конструктора, а в виде готовых объектов, которые как раз выполняют такую работу. Таких элементов много, но самыми главными из них являются текстовые редакторы. Текстовые редакторы существуют и в виде готовых программ и их очень много. Фактически любой программист считает за честь написать свой текстовый редактор. Можно использовать любой текстовый редактор, записать в него текст, сохранить в файл. Потом ваша программа прочитает этот файл, а там все будет написано, что надо делать и как.
. . . Многие так и работали раньше. Наверняка и сейчас кто-то так работает. Но это не очень быстро и зависит от того, что есть на компьютере. На одном может быть редактор, а на другом может и не быть. Все таки хорошо, когда ваша программа имеет свой текстовый редактор, и сама может в него что-то написать, спасти в файл, а потом прочитать из файла. В моем ЛЯПе есть несколько текстовых редакторов и вот как с ними работать полезно рассказать. Дело в том, что текстовый редактор способен показать инструкцию о том, как работает программа, что она делает. И заодно предложить пользователю написать входные данные для расчета.
. . . Потом программа выполнит то, что попросил пользователь, а в конце какие-то результаты покажет на графике, а какие-то покажет текстом. И вот это уже будет вполне достойный диалог компьютера с пользователем. Так как текстовые редакторы имеют дело с файлами, то операции с ним выполняет команда #f . Первая операция называется edit. В справочнике моего ЛЯПа написано, что команда реагирует на параметры c; mo; file; b; le; em; nx; ny; xs; ys; Я не буду копировать то, что там написано, потому что можно открыть описание и прочитать. Я расскажу только то, что там не написано.
. . . Дело в том, что любой редактор -- это отдельное окно на экране, которое имеет размеры, положение, название и режимы работы. Дополнительно редактор имеет свое меню. в котором можно выбрать операции для обработки текста или информацию о тексте. И все это надо описать и там все написано. Что касается внешнего оформления редактора, то для каждого человека они свои. Я лично для себя выбрал значения параметров и записал их определение в суперкоманду ##6 . Остался неопределенным только параметр file, в котором находится текст для редактирования. Поэтому для меня стандартный запуск редактора такой ##6 #f [file=name.txt;] Если кому-то мои значения какого-то параметра не понравятся, то он может записать его в явном виде, изменив это значение. Или переписать суперкоманду.
. . . Этот редактор не совсем похож на внешние редакторы. Во-первых у него неполное меню. Нет возможности открыть файл, спасти в файл, или спасти в другой файл. Он работает только с тем файлом, который указан в команде, которая его открывает. Если файл пустой, нет ни одного символа, то он его не открывает. Так получилось, и я не стал это менять. Текст автоматически спасается в файл при выходе из редактора через меню или по клавише [esc], но только если [mo=1;], а если [mo=0;] то не спасается. Это необходимо для показа некоторых информационных текстов, которые нельзя портить. Но и при [mo=1;] изменения не сохраняются, если закрыть окно крестиком в правом верхнем углу окна.
. . . Также еще один важный момент. Параметр s(1) при входе задает позицию текстового курсора, а при выходе передает в программу позицию тестового курсора. И вот это уже элементы взаимодействия. Первая позиция нужна при поиске слов и ошибок в программе. Вторая -- при получении информации от пользователя о выборе какой то строки или слова. Наконец, можно указать [file=here;]. Тогда редактор показывает часть массива t() с началом по значению параметра b и длиной le. А при выходе параметры s(4) и s(5) сообщают куда записан новый текст. А начинается запись с параметра s(3). В данном случае s(4)=s(3), просто соблюдается стандарт.
. . . Всего этого нет у внешних программ и им это не нужно. Они работают только с файлами. А данный редактор является элементом интерфейса программы. Что касается меню самого редактора, то оно тоже необычное. Во-первых, он умеет исправлять кодировку символов, напечатанных при неправильной раскладке русского и латинского языков. Он также умеет сам устанавливать раскладку. Наконец, он может показывать сайты интернета в собственном браузере (с очень простой разметкой, без JS) и картинки. Как это делать написано в самом редакторе в меню [help]. Все это помогает создавать необычные программы для обработки текста.
. . . Если интерпретатор работает с собственным окном, то окно данного редактора к нему не привязано. Его можно перемещать. И также редактор работает в том случае, если окна интерпретатора нет совсем. Но есть еще другой редактор, который работает точно так же, но его окно открывается только в пределах окна интерпретатора. И перемещается вместе с ним. Он открывается по операции [op=edtf;]. Этот редактор полностью копирует редактор самого интерпретатора с окном, который является элементом среды разработки программ. И, наконец, есть третий редактор. Его история такая. Первоначально я, кроме своего ЛЯПа сделал вторую независимую программу -- редактор тестов, который делал почти все то же, что мой ЛЯП, но через меню.
. . . Этот редактор имеет очень большие возможности. Он не только записывает текст, но может делать вычисления, рисовать графики, выполнять операции операционной системы, показывать сайты интернета в хорошем браузере, и многое другое. У него есть собственное описание и там все написано. Для этой программ я даже делал свой сайт. И программа до сих пор существует как независимая. И с ней можно работать. Но потом я решил просто включить ее код в интерпретатор, и она стала частью ЛЯПа. Но фокус в том, что часть кода у редактора полностью повторяет код интерпретатора, то есть в коде есть классы двойники, записанные в разные папки.
. . . Поэтому компилятор такой код не пропустит. Приходится держать код этого редактора отдельно. И потом добавлять после компиляции. На его работе это никак не сказывается за исключением того, что этот редактор запускается как внешняя программа командами # &=0; #pr Полный путь к файлу\E #e [n=1; em=1; c=1;] _\09 . И у него нет возможности манипулировать курсором. А узнать как он был закрыт можно. Если он закрывается нормальным образом (через меню или по [esc]) то переменная &=1; А если кликом крестика, то переменная & не меняется. Как раз я сейчас пишу этот текст именно в этом редакторе. Так как файл для редактора определяет ЛЯП, то это позволяет кое-что автоматизировать и не на придется искать файл в операционной системе.
. . . И вот хотя в моем ЛЯПе есть очень много самых разных элементов интерфейса я уже почти от всего отказался потому что достаточно редактора текстов. В нем можно сообщить информацию о программе и задать входные данные. И все это автоматически сохраняется до следующего раза. Организовать ввод входных данных можно разными способами. Можно даже просто записывать часть кода на ЛЯПе и потом его выполнять. Так даже намного проще программировать.

17. . . . В ЛЯПе сделан еще один универсальный инструмент общения с пользователем. Это специальная программа показа картинок. Используется способность ЯП Java работать с картинками в форматах jpg, png и gif. Картинки в специальном окне показывает команда #w . Это одна из самых сложных команд. У нее несколько операций и очень много параметров. Самая простая операция получается если [op=im; mo=0; sa=0; c=1; em=0; file=name;]. Операция im указывает, что картинку надо взять из файла с именем name, включая указанные расширения. Параметр mo=0 означает, что картинку надо показать как есть в центре экрана. При этом размеры картинки возвращаются в программу в параметры s(12), то есть tw (ширина) и s(13), то есть th (высота). Параметр sa=0 означает, что картинку нужно только показать на экране и все. Но есть и другие варианты. При sa=-1 она еще записывается в файл, это важно в других вариантах, а при sa=-2 она только записывается в файл и не показывается.
. . . Но параметр sa может иметь и положительные значения от 1 до 100. И вот тут самое интересное. В программе есть специальное хранилище картинок, так сказать обменный пункт. Кроме массивов i(),
r(), t(), s() есть еще один массив картинок. Но у этого массива нет имени. Его индексы определяются разными параметрами. Запоминать картинки нужно по такой же причине, как и другие массивы. То есть для передачи из одной команды в другую и из одной программы в другую. Дело в том, что рассматриваемая операция данной команды прочитывает картинку из файла и декодирует ее в числовые массивы и потом запоминает.А другой команде уже не надо это делать. Она берет картинку из массива по номеру и может сразу с ней работать. Она уже имеет нужный формат raw, то есть без сжатия. То есть, например. если sa=55, то картинка вообще не показывается. Она записывается в память и все. е
. . . Про параметр c я уже говорил ранее. Если он равен 0, то картинка показывается и программа идет дальше. А если 1, то программа стоит и ждет реакции пользователя. Пользователь должен либо кликнуть мышкой, либо нажать клавишу. Параметр em в самом начале равен 0 и его можно не указывать. Но если он был изменен ранее и его забыли обнулить, то надо это сделать. Пока программа стоит на экране в окне, то под картинкой находится текстовая строка, которая показывает размер картинки, координаты курсора и RGB цвет пикселя под курсором. Двигая курсор мы получаем координаты любой точки, которая нас интересует. Это очень удобный инструмент, который позволяет определять размеры различных объектов и нужные компоненты цвета.
. . . Самое интересное происходит когда пользователь кликает мышкой или нажимает клавишу. В этом случае окно с картинкой исчезает, программа продолжает работу и одновременно она получает параметры клика в параметр s(1). Если он простой, то s(1) равен 16, другие варианты: 17 для Shift+Click, 18 для Ctrl+Click, 19 для Shift+Ctrl+Click, 24 для Alt+Click, 25 для Alt+Shift+Click, 26 для Alt+Ctrl+Click, 27 для Alt+Ctrl+Shift+Click. Если нажата клавиша, то ее код возвращается в параметр s(2). Коды для цифр и букв совпадают с ascii кодами клавиш. То есть [0]=48, ..., [9]=57, [A]=65, ..., [Z]=90. Другие клавиши имеют коды, совпадающие с ASCII кодами знаков нижнего регистра: (,)=44, (-)=45, (.)=46, (/)=47, (;)=59, (=)=61, ([)=91, (\)=92, (])=93. Служебные клавиши имеют следующие коды: [Bksp]=8, [Tab]=9 (не работает), [Enter]=10, [Shift]=16 (не работает), [Ctrl]=17 (не работает), [Alt]=18 (не работает), [CapsLock]=20, [Esc]=27, [Space]=32, [PgUp]=33, [PgDn]=34, [End]=35, [Home]=36. Стрелки имеют следующие коды: влево 37, вверх 38, вправо 39, вниз 40. Служебные клавиши [F1]=112, ..., [F12]=123. Наконец другие клавиши имеют специальные коды: [Ins]=155, [Del]=127, (')=222, (`)=192. Если забыли, то это информацию можно получить с помощью специальной небольшой программы.
. . . Но и это еще не все. При клике мышкой координаты курсора возвращаются в параметры s(102) и s(103). А если нажата левая кнопка мыши в каком-то положении, потом курсор был передвинут в другое положение и кнопка отпущена, то возвращаются не только первые координаты, но и вторые в параметры s(104) и s(105). Это позволяет передавать в программу координаты любого размера картинки. И потом можно создать новую картинку как фрагмент старой. Есть готовые программы, которые это делают. Можно посмотреть их код. Имея такой богатый арсенал очень легко создать разного рода меню, фасонные кнопки и выбор любого продолжения программы. И все в красивом графическом виде.
. . . Но у этой операции есть и другие возможности. Так, если mo=1 и параметры tw, th > 0, то картинка перед показом будет промасштабирована на новый размер, равный значениям этих параметров. Если один из параметров отрицателен, то он он будет вычислен таким образом, чтобы аспектное отношение сохранялось. При этом необходимо определить параметр sc, то есть дать ему значение в интервале от 1 до 5. Если дополнительно параметры wid, hei больше нуля, а также xs, ys больше или равны нулю, то после масштабирования будет выделен фрагмент из картинки с размерами wid и hei, сдвинутый из левого нижнего угла на расстояние xs и ys.
. . . Если mo=2, то картинка будет взята из памяти, то есть из массива картинок, с номером, равным параметру n и ее размеры изменятся на tw, th. Если mo=3, то картинка снова будет взята из памяти из нее будет вырезан фрагмент. Условия операции те же, что и выше. Остальные возможные значения параметра mo показывают в виде картинок массивы чисел, записанные в разные форматы. Детали можно посмотреть в справочнике по этой операции. Важно, что данная операция позволяет показать картинки, записанные в самые разные форматы, менять их размеры и вынимать фрагменты, а также делать преобразования для подготовки других операций с картинками.
. . . С точки зрения внешнего оформления программы полезно указать на еще одну команду. Она более простая, но часто очень полезная для презентаций и не только. У нее мало параметров и можно показать их все. Вот она #fr [op=o; mo=; n=; xs=; ys=;] FT . Название -- начало слова frame. [op=o;] означает показать картинку на экране. Картинка берется из памяти с номером n как есть. Координаты xs, ys указывают смещение левого верхнего угла картинки от того же угла экрана. Если mo=0, то картинка показывается в окне и имеет название окна, которое указывается аргументом FT (форматированный текст). Это тот же самый текст, который записывается в команде #pr , которая обсуждалась в мини-главе 13. А если mo = 1, ..., 10 , то картинка показывается без рамки и без названия. И таких картинок можно выставить 10 штук с разными значениями mo. Картинка будет стоять на экране пока не выполнится команда #fr [op=с; mo=; ] FT . Если mo = 0, то картинка определяется по названию, а mo > 0, то по значению.
. . . Одно из применений таких картинок -- дать подсказку пользователю что и как надо делать. И это можно сделать в любом фасонном виде. Но иногда такие картинки могут использоваться как фон для какой-либо операции. Можно даже простую анимацию делать показывая картинки какое-то время а потом убирая. Была бы возможность, а применение найдется. Но тут есть и опасность. Если вдруг в программе ошибка, а картинку закрыть не получилось, то она так и останется на экране. Избавиться от нее получится только перезапустив интерпретатор. Так что пользоваться надо с осторожностью.

18. . . . В предыдущей мини-главе я показал, что можно совместить показ картинки на экране с запросом от пользователя. Но в команде #w [op=im;] эта функция является как бы дополнительной к многим другим функциям, главной из которых является декодирование картинки из сжатой формы, как она записана в файле в матрицы чисел. То есть показ картинки на экране или запись в память. А другие команды могут этим пользоваться. Например, такой командой является #fr .
. . . Но с точки зрения получения запросов от пользователя есть и другая более простая команда #ch [n=; xs-; ys=;] . Название от слова choose. У нее всего три параметра. Если внимательно читать то, что уже написано, то смысл ее параметров очевиден. Эта команда показывает картинку из памяти с номером n и смещением (xs,ys) от левого верхнего угла. Картинка показывается как есть и без рамки. И потом она ждет реакции пользователя, а результат выдает в параметры s(1), s(2), s(102), s(103). Все очень просто. И вот у меня есть готовая программа номер 31, которая показывает Таблицу Менделеева. И клик на любом элементе сразу открывает информацию об этом элементе в редакторе текстов.
. . . И описанная команда является главной в этой программе. Дальше надо просто по полученным координатам клика определить какой элемент был выбран. Это просто математика. Все квадратики элементов имеют свои координаты и найти внутри какого из них был курсор во время клика можно простым перебором. Таким же образом можно нарисовать любой набор кнопок, меню и всех элементов которые делают выбор. Но есть и стандартные команды для реализации выбора. Они тоже удобны.
. . . Есть команда #sel . Название от слова select. Я не буду ее подробно описывать. Информацию можно получить в справочнике по ЛЯПу. Ссылку можно найти поиском по слову acl-info . Я расскажу что она делает. Она выставляет прямоугольную таблицу кнопок и возвращает номер нажатой кнопки. Номера идут слева направо и сверху вниз, как обычно. Число кнопок в ряду и число рядов переменное. Сами кнопки могут быть как картинками, так и текстами. Тексты могут иметь разный размер, цвет и на фоне любого цвета. Я часто использую эту команду в виде суперкоманды ##16. Эта суперкоманда просто выставляет таблицу из 99 кнопок 11*9, на которых написаны номера. И у нее все определено.
. . . Можно выставлять несколько таких таблиц каскадом. И вот чтобы не запутаться вторую и далее таблицы можно сделать другим цветом. Тогда надо писать такой код #d 6 r(1) 0*3 255*3 1 &Z 99 ##16 . тут определяются 2 цвета и переменной &Z присваивается значение 99. В cтандартной ситуации надо следить, чтобы эта переменная не имела такого значения. Но я до сих пор не объяснил как используются цвета. Дело в том, что мы еще не рассматривали графические пакеты. А это там. Но цвета все же отдельно и потому я сейчас расскажу как это делается. Цвет определяется тремя компонентами R (красный) G (зеленый) B (синий). Эти компоненты записываются одним байтом, то есть имею значения от 0 до 255. В указанном коде два цвета берутся из 6-ти первых элементов массива r(). Это черный 0 0 0 и белый 255 255 255.
. . . Но в моем ЛЯПе для удобства писать код снова сделан массив из 256 элементов для цветов. И в некоторых командах цвет задается одним параметром col и имеет значение от 1 до 256. В самом начале работы все элементы массива цветов определены, но это определение не очень полное. Вот оно. (1 до 243) черный (0 0 0), (244) темно-красный (128,0,0), (245) темно-серый (85,85,85), (246) белый (255 255 255), (247) черный (0 0 0), (248) красный (255 0 0), (249) синий (0 0 255), (250) зеленый (0 195 0), (251) серый (128 128 128), (252) коричневый (152 128 0), (253) фиолетовый (152 0 152), (254) голубой (0 255 255), (255) темно-синий blue (0 0 128), (256) светло-коричневый (220 200 180). Если вас такие цвета устраивают, но и можно использовать. А если нет, то таблицу можно переопределить. Делает это команда #col [b= ; le= ; fir= ;]. Ее параметры определяют первый номер цвета (b), сколько цветов определяем (le) и где записаны RGB компоненты цветов (fir).
. . . Номер цвета одним числом нам попадался в суперкомандах ##1 и ##2 в мини-главах 12 и 14. Он есть также в команде #sel и в командах #g и #eg , которые мы еще не рассматривали. Из команд, реализующих интерфейс с пользователем осталось отметить команду #inp . Название от слова input. Было время, когда я много программ написал с ее использованием. Но последнее время я ее не использую. Как она работает написано в справочнике по языку и я не буду подробно об этом рассказывать. Это фактически мини редактор текстов, которых показывает окошки, в которые можно писать текст, а слева от них есть инструкция какой именно текст надо записывать. Такие окошки можно видеть на некоторых сайтах интернета, когда, например, проверяют не робот ли вы. Типичный пример -- показывают число текстом с ошибками и просят ввести это число цифрами.
. . . Так вот команда #inp делает много таких окошек с текстами и кнопками. Сначала надо заполнить все окошки, а потом нажать одну из кнопок. Есть очень красивые и продвинутые варианты. А было время, когда в программах были сотни таких окошек и прежде, чем запустить программу в работу их все надо было определить. Мне это всегда не нравилось, но свою первую онлайн программу на языке JS я тоже сделал в таком стиле. Ей уже более 25 лет, но она все еще есть в интернете, вот ссылка https://kohnvict.ucoz.ru/a/10/crl.htm .
. . . Сейчас я входные данные записываю по возможности в одну строку в редакторе текстов и в этом же редакторе могут быть другие варианты и описание параметров. Даже просто код моего ЛЯПа можно писать. В редакторе текстов можно и окошки организовать. Важно, что не надо прыгать из одного окна в другое. Можно копировать текст, хоть сколько угодно символов сразу. Взрослые люди -- те же дети. Иногда придумывают себе игрушки или сказки и верят в это. Причем все сразу. А потом все бросают и придумывают то-то другое. Вот сейчас поголовное увлечение Питоном -- это не просто удивительно, но признак болезни. Ведь Java и Питон появились почти одновременно. Сначала все увлеклись языком Java, а потом решили, что очень сложно и Питон проще. Стали всех кормить Питоном. Java -- это сложно и не очень удобно. Но можно упрощать. И таких попыток уже много. Мой ЛЯП -- одна из них.

19. . . . Я написал, как вычислять и как показывать вычисления, но тут возможностей больше, я показал не все. И еще я показал как программа может взаимодействовать с пользователем и создавать свой внешний вид. Но стандартные возможности любого языка программирования намного больше. Что осталось ? Первое -- работа с файлами, то есть как создается операционная система. Ведь любая операционная система -- это комплекс программ для работы с файлами на дисках. Система ДОС так и называется -- дисковая операционная система. Частично я про это рассказал при обсуждении команды #io. Но главная команда, которая это делает #f (file).
. . . Далее, нужна работа с текстом и текстовыми файлами. Это очень важно и полезно для писателей и для получения информации. В моем ЛЯПе это делает команда #te (text). Также нужно уметь рисовать рисунки и я уже писал, что в Java есть два пакета, которые полностью перешли в мой ЛЯП, конкретно в команды #g и #eg. И я еще не рассказал об одном простом средстве не взаимодействия с пользователем, а сообщения пользователю каких то текстов, например, об ошибках в программе, о том что делать далее, разные подсказки и так далее. Обычно с этого начинают рассказывать о языке. Но это глупо, и я не попугай, чтобы повторять эту глупость за всеми.
. . . Наконец, очень полезно уметь работать с архивами файлов. Это когда много файлов соединяют вместе в один файл в сжатом виде. Читать такой файл нельзя, но передавать информацию по интернету очень удобно. В Java был выбран за основу zip архиватор. Это делает команда #z . Весьма полезно уметь использовать операционную систему, то есть хотя бы запускать командные файлы системы. Это делает команда #sys . Ну и можно совсем не сложно делать анимации. Это полезно для моделирования некоторых процессов во времени. Я сделал на базе языка Java собственную относительно простую систему, которая выполняется командой #ag от слов animation graphics. И все стандартные средства работы на компьютере на этом заканчиваются.
. . . Но есть нестандартные. Более того, язык можно расширять бесконечно, включая даже чужой код, написанный на Java. И вот таких расширений в моем ЛЯПе два. Это команда #ps для создания постскрипт графики и команда #pd для работы с pdf файлами. Это все очень крупные системы с большим числом операций. И есть еще более мелкие команды, которые упрощают программирование и управление работой с программами. Например команда #stop прекращает выполнение команд в файле даже если они там написаны. Например, надо проверить работу какого-то короткого кода. Создавать новый файл нет смысла. Пишем в начале любого файла этот код, а потом команду #stop и сам файл не будет выполняться.
. . . Можно и покороче писать, но такие команды я пишу полностью. Есть еще команда #exit . Она вообще закрывает программу интерпретатора. И она необходима, когда программа работает без окна с меню. В этом случае закрыть ее средствами ОС не получится. Нужно именно закрывать интерпретатор. У меня есть программа презентации. Когда интерпретатор открывается по иконке сразу с одной готовой программой и в конце закрывается. В этом случае презентация сразу открывается за один клик, а интерпретатора не видно совсем. Программа Power Point, которой все пользуются, так не умеет. И программа Adobe Reader тоже. Там выйти на режим показа слайдов на весь экран многие просто не умеют, и делается это не быстро.
. . . Еcть еще проcтая программа #read . Она часто используется в моих готовых программах, созданных по новому методу. Эта программа читает из текстового массива числа. То есть делает то же самое, что и операция #io [op=rf;] , о которой я рассказывал в 12-й мини-главе. Но там чтение идет из файла, а тут -- из массива t(). Это нужно когда из файла вынимается только одна строка. Есть еще некоторые сложные режимы работы которые оформляются короткими командами, например, #go n, #% . Но про них я еще не скоро буду рассказывать. Но в справочнике они есть и там все написано. Достаточно часто я использую команду #pf . Это как бы готовый элемент оформления программ, который наверняка все видели. кто работает на компьютере. Название от слов progress bar . Она используется когда программа очень долго работает в цикле.
. . . Если программа молчит и ничего не показывает, то всегда есть опасность, что что-то пошло не так и сломалось. Поэтому программа показывает процесс выполнения операции, закрашивая полоску каким-то цветом. И видно сколько сделано и сколько осталось. Вообще говоря, такую штуку можно элементарно сделать на моем ЛЯПе. Но я сделал команду, которая использует стандартный Java код. Но процесс выполнения циклов можно показывать и несколькими другими способами. Просто тут лучше делать как все, это более привычно и понятно. Справочник по командам и всем их операциям имеет чуть более 200 пунктов. И первое время кажется что это очень много.
. . . Мол все не запомнить. Но это и не требуется. Нужно просто понимать что конкретно вам нужно и интересно. И можно вообще не знать о другом. Или помнить что и какие операции выполняет, а конкретные детали всегда можно посмотреть в справочнике. Там же есть примеры записи кода. Я и сам так поступаю, хотя сам все делал и помнил. Но проходит время и все забывается. Точнее, все неважное. Важное не забывается. А неважное всегда можно посмотреть. В программировании очень большое значение имеют примеры кода, выполняющие те или иные операции. Это есть в готовых программах, в суперкомандах, и я еще пытался писать кое какие образцы. Даже просто для копирования кусков кода.
. . . Но вот последнее время я пишу другую статью, где рассматриваются примеры кода для решения некоторых задач с подробным объяснением как это делается. Эта статья пишется в pdf формате и есть в интернете, вот ссылка https://kohnvict.ucoz.ru/vkacl/vkacl-examples.pdf . Все ссылки можно найти по кнопке на программу ЛЯПа на моем сайте. Пока там мало, но зато весьма полезные примеры. В будущем их будет больше. Итак, я описал программу того, что еще предстоит написать. И это совсем не мало. Более того, это только основы. А еще есть комбинации всех операций, то есть приемы программирования. И тут уже бесконечность.

20. . . . У команды #f в справочнике описано 27 операций. Это и много и мало. Мало потому, что с файлами можно делать намного больше операций. Много, потому что основных операций все же меньше. Про две операции -- [edit] и [edtf] я уже рассказал в 16-й мини-главе. Они запускают готовые программы редактора текстов, но этот редактор управляется параметрами и взаимодействует с командами ЛЯПа. Из основных операций с файлами начнем с операции [copy]. Эта операция копирует несколько файлов в один. В частном случае один в один. Я не буду рассказывать как это устроено, в справочнике все написано. Важно, что копирование нескольких файлов в один позволяет автоматически создавать сложные сайты, в которых есть стандартные куски и куски, формируемые программой.
. . . Второй по важности и массовости операцией является [dele]. Она просто уничтожает файл с указанным именем. Это бывает необходимо делать автоматически, когда используется временный файл и потом его надо уничтожить для чистоты каталога винчестера. Эта же операция уничтожает пустые папки. То есть сначала надо уничтожить все файлы в папке, а потом можно уничтожить и саму папку. Ну и понятно, что для этого надо знать все файлы в папке. Такую информацию дает операция [fcat]. Она просто печатает в массив t() все имена файлов, разделенные символом вертикальной черты. Как обычно, начало в s(3) до операции, потом s(3) смещается, а s(4), s(5) дает информацию о сделанной печати. Про операцию [fold] я тоже уже рассказал в 12-й части.
. . . Еще одна из основных операций называется [choo]. Она как раз показывает каталог файлов на компьютере в некотором собственном оформлении и пользователь может выбрать нужный ему файл. Эту программу я не писал, она есть в ЯП Java в готовом виде и я просто оформил ее вызов из ЛЯПа. Там все делается как в ЯП Java. У этой операции есть 2 модификации. Либо все показывать стандартно, либо показывать картинки с предпросмотром в виде небольших иконок. Вообще я должен отметить, что в языке Java есть не только элементы языка, но и вполне готовые объекты, уже написанные авторами на этом языке. Это что-то вроде процедур. И их гораздо больше, чем те. которые я перенес в свой ЛЯП.
. . . Так я много лет работал без следующей операции, но недавно все таки ее сделал. Она называется [modi]. Она показывает дату последнего изменения файла. Это бывает необходимо для написания программы синхронизации файлов на двух носителях. Можно узнать какой из двух вариантов изменялся позднее и скопировать его на второй носитель. Ну и последняя операция этой серии которая очень часто используется -- это [size]. Она показывает размер файла в байтах. Если размер равен нулю, то данного файла не существует. Именно так это и проверяется в ЛЯПе. Это считается серьезной ошибкой и программа интерпретатора дальше не работает. В операционных системах, естественно, есть еще много чего, что делается на уровне программ. И в моем ЛЯПе тоже еще много чего есть. Но указанные программы -- это тот минимум, без чего просто нельзя работать.
. . . А теперь посмотрим что еще есть дополнительно. Начать я хочу с операции [line], которую сам использую очень часто. Эта операция записывает в массив t() строку из текстового файла с указанным номером. То есть если первую строку, то от начала и до первого признака конце строки. Если для второй строки, то он от первого символа после первого конца строки до второго символа. Например, в каждой строке может быть записан один из вариантов входных данных программы и после выбора пользователем этой строки в редакторе, я ее потом и вынимаю из файла.
. . . Из такой же серии есть другая операция [list]. Она использует два символа. Сначала берет из файла весь текст до первого символа, включая и его самого. Потом пропускает весь текст до второго символа, включая и его самого, потом снова берет и так далее. Эта операция нужна для работы с Хэш таблицами. Это такой текст, который состоит из пар имя-значение. Типа как составляются словари. Каждое слово имеет объясняющий его значение текст. И вам сначала нужно оставить таблицу всех имен и показать ее. А потом пользователь выберет какое-то имя и вам надо показать текст из этой пары, то есть значение.
. . . Я сделал такую программу, которая показывает таблицу имен операций. А при выборе нужного имени она делает операцию, которая с этим именем связана. Одна их операций сама редактирует файл с Хэш-таблицей и может добавить или отредактировать операцию. Эта программа имеет номер 28. Но могут быть и другие варианты. У каждого свои потребности. Вообще-то для работы с Хэш-таблицами в ЯП Java есть свой механизм. Но эту операцию я сделал сам скорее всего в более упрощенном виде.
. . . Есть еще операция [find]. Но она не совсем стандартная. Она работает с любыми файлами, не только текстовыми. И определяет сколько раз в данном файле встречается некоторая комбинация байтов, то есть чисел в диапазоне от -128 до 127. Результат выдает в параметр s(2). Не буду объяснять зачем это надо. Была бы возможность, а применение найдется. Более сложную работу делает операция [repl]. Она находит в файле все комбинации байтов и заменяет их на другую систему байтов. Например, может исправит все запятые на точки. Все символы \ на /. И много чего еще.
. . . Но бывает и так, что надо сделать более сложные замены. Есть операция [rep2], которая заменяет одну систему на другую, потом вторую систему на вторую другую, а потом все повторяется. Вот простой пример. Надо все круглые скобки заменить на квадратные. Можно два раза применить [repl]. Но это не всегда будет правильно. Надо именно одни скобки заменить внутри других. А скажем двойные скобки типа (( не менять. Операции такого типа в других ЯП я не знаю. Конечно ее можно сделать, но если делать посимвольно, то в интерпретируемом языке это будет долго работать.
. . . Но есть еще и [rep3]. Эта операция находит первую комбинацию символов, потом вторую, и весь текст, который находится внутри заменяет на другую комбинацию или на пустоту, то есть уничтожает. Такое тоже бывает необходимо. А можно и искусственно сделать. Сначала помечаем все куски текста, которые надо уничтожить или изменить, символами, а потом все делаем за один миг. Я описал не все операции. Остались редкие и более сложные. Это будет в следующий раз.

21. . . . У команды #f всего 27 операций. В прошлый раз я рассказал про 15. Попробую рассказать про остальные уже прямо по их порядку в списке справочника. Некоторые операции я делал в тот самый момент, когда в них была необходимость. Хотя потом они не так уж часто использовались. К таким операциям относится [alph]. Она упорядочивает строки текста по алфавиту, точнее по номерам юникодов. Это бывает полезно при составлении словарей и поиске двойников. Иногда бывает так, что в очень большом тексте есть строки двойники и их надо убрать. И вообще поиск нужных строк удобнее делать если текст упорядочен по алфавиту. Операция [cdpj] была создана в тот момент, когда я изучал ЯП Питон. Дело в том, что Питон в ОС Виндовс записывает числа в компьютерном коде совсем не так, как Java и vkacl. И вот эта операция переписывает такие файлы из формата Питона в формат джавы. Название операции составлено из первых букв слов convert data python java.
. . . С Питоном у меня история была такая, что язык мне не понравился, но кое-что сделать можно. И я начал это делать. Но потом подумал, что это огромный труд заново делать то, что у меня уже сделано и на языке, который мне совсем не нужен. На нем работал аспирант, с которым все равно ничего не получилось. У него свои начальники и загружают его так, что он ничего не успевает. И он так и продолжает работать на Питоне, но кое чему я его все же научил. И, все же операция полезная, если вдруг кто-то мне пришлет свои результаты на Питоне, то я смогу их использовать. Без этой операции это невозможно. Операция [divi] является аналогом выделения из матрицы подматрицы, а из картинки ее фрагмента. Но в данном случае матрицы нет, есть файл как система байтов. И вот операция сначала пропускает некоторое число 1 байтов, потом берет другое число 2 байтов, потом пропускает число 3 байтов и последние две операции повторяются n раз. Число 1 определяется параметром [b], число 2 -- параметром [le], число 3 -- параметром [xsh]. А байты могут содержать текст, числа в разных форматах и так далее.
. . . Операция [html] иногда может быть полезной. Буквально с первой версии язык Java в ней был написан очень простой браузер, который может показывать html файлы. Он очень уступает современным браузерам, но иногда какую-то информацию он способен показывать лучше, чем просто текст в текстовом редакторе, потому что какое-то форматирование в нем есть. И вот эта операция его запускает и показывает файл, который ей указан. Одно время я его широко использовал, но потом стал запускать все-таки внешний Яндекс браузер, который современные компьютеры легко запускают. Но кое какие файлы я продолжаю запускать в нем. Этот браузер как раз пример того, как язык может включать в себя и готовые программы, а не только примитивы.
. . . Операция [mb64] уже помечается компилятором как устаревшая. Возможно они когда-нибудь в будущем от нее откажутся. Но старые версии JRE никуда не денутся и там все есть. Дело в том, что письма электронной почты в самом начале передавались в сжатом виде в формате MIME 64. И когда-то очень давно не было онлайн почтовых машин и серверов для всех. У нас на работе один из компьютеров работал как сервер и у него стояла почта в систем Юникс. И я по телефону связывал свой компьютер с этим сервером (были такие модемы) и получал эту почту по ftp в таком вот закодированном виде. И нужно было раскодировать, прочитать, потом написать ответ и снова закодировать. Я все это дело делал с другой программой. А в Java есть механизм это делать. И как раз эта команда то же самое делает в моем ЛЯПе.
. . . Казалось бы зачем она сейчас. Ведь почту уже можно легко принимать и посылать через онлайн почтовую машину. Но есть еще одно применение этой кодировки. Картинки в формате электронных книг fb2 тоже кодируются этой кодировкой. И это продолжает работать. Формат fb2 электронных книг весьма распространен. Я даже купил себе прибор для их чтения на солнце. Но попользовался а потом перестал. Дело в том, что я дома так много времени сижу перед компьютером, что на улице я перестал этим заниматься. Я не смотрю смартфон и не читаю электронных книг. Просто думаю и все. Но в метро уже на стенах появились экраны с рекламой и все равно можно что-то смотреть. И тем не менее, я написал на своем ЛЯПе программу создания электронных книг в формате fb2, и эта программа использует данную операцию для кодировки картинок.
. . . Операция [ruco] мне тоже понадобилась и пришлось ее сделать. Она перекодирует русский текст в файле из кодировки windows-1251 в кодировку utf-8. У меня очень много файлов было написано в кодировке windows-1251, она более компактная и вполне годится. Но в какой-то момент мой сервер Юкоз перестал ее поддерживать, и все статьи на моем сайте стали показывать нечитабельный текст. Пришлось исправлять несколько сотен файлов. Мой редактор это умеет, но вручную это долго, а операция позволяет автоматизировать процесс.
. . . Операция [tobm] конвертирует картинки из файлов в форматах jpg, png, gif в матрицы байтов. Каждая точка -- один байт. Если картинка цветная, то она превращается в черно белую скалярным произведением цвета пикселя на цвет, заданный параметром col. То есть просто используется декодер и фильтр. Матрица байтов может быть переведена в матрицу ascii кодов, то есть целых чисел от 0 до 255 и с ними можно делать всевозможные математические операции. Обратное преобразование матрицы в картинку делает команда #w [op=im; mo=8;]. Операция [tocm] делает то же самое, но более детально. То есть каждый пиксель записывается тремя байтами, которые определяют R G B компоненты цвета. Обратное преобразование такой матрицы делает команда #w [op=im; mo=24;]. Обе эти операции позволяют делать всевозможные манипуляции с картинками, например, складывать или вычитать две картинки с разными весами, прибавлять или умножать на константу, все зависит от того, у кого сколько фантазии.
. . . Операция [topn] конвертирует картинку из памяти с номером n в png формат и записывает на диск. Дело в том, что команда #w [op=im;] спасает картинку в файл только в jpg формате. Если нужен png формат, то картинку надо записать в память и затем эта операция сделает то, что надо. Сама операция ничего не показывает. Она просто записывает файл. Поэтому она здесь, в этой команде, а не в других. Операция [tops] необходима для работы с графикой в постскрипт формате. Дело в том, что растровые картинки в этом формате записываются достаточно сложным образом и вручную это не сделать. И вот эта операция спасает ситуацию. Она может брать картинку типа jpg, png, gif прямо из файла, но если параметр file=here, то тогда берет из памяти с номером n. Это общий принцип. Результат она записывает в файл, имя которого задает параметр form . Это тоже почти всегда так, когда нужно указать два файла.
. . . Последняя операция [w2jc] составлена из слов windows to java conversion. Я уже писал про проблемы с Питоном. Но есть и другие программы. Она просто переставляет байты у каждой группы из 4-х байтов. Дело в том, что в системе Виндовс числа в компьютерном коде из 4-х байтов записываются так, что младшие байты раньше старших. В этом есть свой резон для маленьких чисел. Если точно знать, что числа маленькие, то можно читать первые байты, а остальные не читать. Но в Юникс не так. Там как в математике, сначала идут старшие разряды, а младшие в конце. И чтобы прочитать в Юникс то, что было записано в Виндовс, надо переставлять байты. Вот именно это данная операция и делает. Повторное ее применение все возвращает обратно.
. . . Вот и все операции на момент написания этого текста. Но очевидно, что таких операций может быть больше. Их отличает то, что написать эти операции непосредственно на ЛЯПе либо невозможно, либо сложно, либо будет неэффективно, потому что медленно. И вот всю эту сложную работу делает интерпретатор, написанный на ЯП Java. Но и в нем кое-какие операции даются в готовом виде. А java код некоторых операций был взят из интернета. И принцип отбора был очень простой. Это мой личный ЯП и в нем есть то, что лично мне интересно и понадобилось.

22. . . . В 19-й части рассказа я перечислил все что осталось не рассказано. Но в рассказе о средствах общения программы с пользователем я не отметил еще одну команду, которая очень часто используется и тоже называется одной буквой #m от слова message. Она просто показывает сообщение (текст) на экране в отдельном окне и имеет одну или несколько кнопок. Эта команда просто использует готовую программу языка Java, хотя ее можно было бы сделать и самостоятельно. Но меня лично в ней все устраивает. У этой команды есть несколько операций (win. yno, gen, oce, txt, rtt, uni). Команда эта существовала в моем ЛЯПе с самого начала, но не все операции.
. . . Я не стану подробно рассказывать про все операции, так как многие из них я уже и сам практически не использую. Вместо них появились другие. Правда им можно найти другое применение, но полная информация о них есть в справочнике. Из всех операций я иногда использую самую первую (win). и самую последнюю (gen). Но самую последнюю не в оригинальном виде, а в виде суперкоманды ##33. Операция gen имеет много параметров и много возможностей иметь разный внешний вид. А в суперкоманде выбран оптимальный внешний вид и есть только самые важные возможности. Вот про них я и расскажу. Команда #m [op=win;] FT показывает форматированный текст, то есть все то, что записывает команда #pr в текстовый массив, но в своем окне стандартного вида и с одной кнопкой [OK].
. . . При этом окно размещается в центре экрана, а программа стоит и ждет когда пользователь кликнет эту кнопку. И дальше программа работает в своем стандартном режиме. А для суперкоманды 33 тот же самый текст печатается командой #pr и потом она вызывается. Но окно показывается не в центре экрана, а в левом верхнем углу. У суперкоманды есть дополнительная возможность. Если команда #pr печатает текст, разделенный вертикальной чертой, то все тексты перед последним являются названиями кнопок, которые все размещаются в один ряд в центре по ширине. Например, если написать #pr Yes|No|Continue ?\E ##33, то в окне будет две кнопки с названиями [Yes] и [Nо] и текстом [Continue ?].
. . . То есть эта суперкоманда тоже позволяет сделать выбор, но из относительно небольшого числа вариантов, зато с любым сколь угодно сложным текстом. Она хороша для записи начального меню в программе, которая делает несколько разных операций. И эта суперкоманда очень легко заменяет операции yno, oce, uni . Ну а если значения параметров не устраивают , то текст суперкоманды можно просто переписать. Лично меня все устраивает и я уже перестал использовать указанные операции, но убирать их из ЛЯПа тоже не стал.
. . . Еще стоит упомянуть, что иногда вместо команды #sel или суперкоманды ##16 я использую суперкоманды ##14 (ssel) ##32 (ssel2), которые показывают длинные кнопки меню большого размера с текстом на них. Первая вертикально в один столбец. Вторая -- в два столбца. И вот эти суперкоманды являются примером того, как можно сделать внешний вид программы на моем ЛЯПе, используя графику. С другой стороны, команда #sel может делать таблицу кнопок с картинками. Раньше я так делал и было красиво. Но с картинками больше мороки. Их надо искать или делать, куда-то закачивать. И последнее время я все реже пользуюсь этой возможностью.
. . . В 21-й части я рассказывал об операциях [tobm] и [tocm]. Они создают картинки в виде матрицы байтов или матрицы цветов. И вот для работы с этими матрицами я сделал команду #bi от слов (byte image). Так как матрицы байтов могут иметь большие размеры, то манипулировать ими в ЛЯПе будет не быстро. А копировать их в 4х-байтовые числа тоже не хотелось. У этой команды много операций но они достаточно простые. Вот они (add, mul, inc, dec, cha, pow, log, exp, sup, pro, div). В переводе на русский язык это означает (прибавить, умножить, увеличить уменьшить, изменить, степень, логарифм, экспонента, сумма, произведение, деление). Все эти операции делают математические преобразования над байтами с целью изменить картинку. Некоторые из них просто вычисляют математические функции, другие делают более сложные преобразования, используя значения параметров, с целью изменить контраст, яркость и другие свойства.
. . . Нет смысла рассказывать об этом подробно, потому что это не всем интересно, и даже если интересно, то не часто нужно. В справочнике все подробно об этом написано. Моя задача -- просто указать что это есть, и этим можно пользоваться. Такая же ситуация с программой #ma . Я немного рассказал о ней в 12-й части. Но у нее 47 операций. И снова не все операции всем интересны. Но в справочнике все можно посмотреть. Для использования всех операций математики надо знать математику. А программисты, вообще говоря, вовсе не обязаны ее знать. Это дело ученых. Например некоторые операции математики работают с комплексными числами, выполняют интегральные преобразования над матрицами и делают другие не менее сложные преобразования. Но есть и простые. Например, операция vba преобразует массив из байтов в аscii коды. При этом ascii коды выходят за пределы байтов, но преобразование делается с массивом r(). Есть также операции масштабирования матриц, вращения матриц, размножения периода.
. . . На самом деле даже 47 операций не покрывает необходимость решить все задачи для всех. И для более редких операций был придуман механизм выполнения некоторых процедур через команду #e [...] \n , где n -- номер процедуры. Фокус в том, что эти процедуры могут быть написаны на языке Java и скомпилированы отдельно от всего остального Java кода, которого очень много. Инструкция как это делать есть на моем сайте. И для кодирования математических вычислений не обязательно знать всю полноту языка Java. Вполне достаточно знать только как записывать вычисления. И все это можно быстро узнать по написанной мной инструкции. Затем откомпилированные классы можно просто записать в jar файл интерпретатора и все будет работать.
. . . Я для себя уже написал 10 таких процедур, причем первые просто решали конкретную задачу, которая после решения уже даже не нужна и ее можно просто вынуть из jar файла. Я пока так не поступаю, но наверно скоро буду это делать. Просто иногда бывает так что математическую часть задачи легче закодировать на Java в виде процедуры. А вот все обслуживание расчетов, то есть входные данные, графики и так далее, делать на ЛЯПе. Но, вообще говоря, на моем сайте есть также моя книга о программировании на Java, где написано как делать и более сложные вещи. Я ее написал очень давно и она была в каталогах программ. Но теперь осталась только на моем сайте.
. . . Расширять мой ЛЯП за счет внешних программ, написанных как мной, так и взятых из интернета можно очень долго и много. Но пока в ЛЯПе есть только то, что интересно лично мне. И вот одну такую весьма большую систему Java классов для работы с pdf файлами, я использовал в своем ЛЯПе. Я сделал команду #pd и часто ей пользуюсь. Причем я даже не все возможности из этого пакета использовал а только то. что мне нужно. Но и этого немало. Более подробно об этом будет позднее.

23. . . . В команде #f есть много операций, которые относятся к тексту в этих файлах. Текста может быть много и потому программировать такие операции на ЛЯПе будет не эффективно. И очень не быстро. Но некоторые из этих операций полезны также и для текста в массиве t(). Первоначально я их тоже все выполнял в команде #f . Для этого использовался такой прием, что объявлялся файл с именем (здесь), то есть [file=here;] и это означало, что файла нет, а есть кусок текстового массива, который определяется параметрами [b] и [le].
. . . И это работает. Но потом я решил что все таки будет удобнее читать код программы, если сделать специальную команду для работы с текстом. И сделал. Это команда #te . У нее меньше операций, чем у команды #f и не все точно ней соответствуют. Я часто ее использую как раз для разбора текста входных данных или сообщений пользователя в процессе работы программы. Итак, строка текста во всех таких операциях определяется параметрами [b] и [le]. А про сами операции я расскажу в этой части. Их всего 8. Первая операция [edit] запускает редактор текстов с текстом из массива t(), а отредактированный текст туда же и возвращает. Для этого используются параметры s(3) -- s(5). Я напомню, что параметр s(4) равен параметру s(3) до начала работы операции. А после s(3)=s(4)+s(5).
. . . Это используется не так часто, но может пригодиться. А вот операция [find] работает иначе, чем в команде #f . Она находит все положения заданного символа и записывает их в целый массив, начиная с указанного индекса. И вот эта операция весьма востребована. Например, вы определили каталог файлов в папке. Он записан в виде имен файлов, разделенных символом вертикальной черты. И зная координаты этого символа в тексте вы можете разделить имена, для использования в цикле. И так можно поступать не только с каталогом файлов. Разделителем текстов может быть символ конца строк и много чего еще.
. . . Операция [repl] тоже работает иначе. Она просто заменяет один юникод на другой. Не слово, а только один символ. И это тоже бывает нужно. Например, заменить запятую на точку символ \ на / и много чего еще. Есть еще операция [show]. В команде #te операция [edit] всегда записывает текст, а вот [show] его только показывает для чтения, но не делает изменений. Очень важная для меня лично операция [trim]. Она выделяет из текста куски, разделенные пробелами, причем неважно сколько их. Может быть 1, а может 11. Такие куски можно записывать во входных данных программ. То есть эта операция разделяет строку текста на несколько строк, не содержащих пробелы. Она возвращает сразу параметры этих кусков в целый массив, начиная с указанного индекса.
. . . Операция [find] тоже разделяет, но там начала и длину строк надо вычислять, а в операции [trim] они сразу даются в готовом виде. Операция [tail] тоже убирает пробелы из строки, но только в самом конце. При этом она просто меняет значение параметра s(10) [le]. А вот операция [fitt] уже ищет в тексте строку символов, причем строка тоже задается параметрами [c] начало и [tw] длина. Результат в виде индексов массива t() записывается в целый массив, начиная с параметра [n]. И последняя операция [emls], вероятно, никому не нужна. Она определяется только аргументом и ее задача -- отправить письмо по электронной почте. Эта операция нужна для написания единственной программы почтовой машины. и я ее уже написал. Так что если кому интересно, что можно почитать описание в справочнике и посмотреть код этой почтовой машины.
. . . Но сложность в том, что если у вас нет своего почтового сервера, то пользоваться другими в принципе можно, но сделать рассылку они вам не дадут. А отдельное письмо можно написать и без этой программы. Лично я пишу все письма в собственном редакторе и потом просто копирую в онлайн почтовую машину. Или наоборот, из онлайн машины копирую в свой редактор. В каком то смысле программа удобна для рассылки в ограниченных пределах тем, что в каждом письме всего один адрес. Например через сервер Яндекса можно послать 50 писем за один раз. И там будет 50 адресов. А почтовая машина может 50 раз отправить письмо с одним адресом. Но это делается очень не быстро.
. . . Еще одна очень полезная команда -- это зип архиватор. Она сделана в ЯП Java в готовом виде, но не так просто как хотелось бы. Через команду это выглядит проще. Команда называется #z . У нее всего 5 операций. Первая операция [cat] показывает список файлов в архиве. Это полезно для информации и для визуальных программ. Но я сам ее почти не использую. Остальные 4 разделены на две пары. Одна пара для папок вторая -- для файлов. Файлы в архив можно вставить и можно вынуть. Если их много, то лучше вставлять или вынимать папку. Это делается сразу по указанию имени папки. Операции [sfo] или [gfo] от слов set folder или get folder. Первая вставляет, вторая вынимает. Параметр указывает только число папок, а их имена указываются аргументами в виде форматированного текста. Адреса отсчитываются от папки интерпретатора и рабочая папка не используется.
. . . Есть интересная особенность. Если папки образуют каскад, то сначала надо вставлять и вынимать внешние папки и только потом можно вставлять и вынимать внутренние. Другая пара операций [sfi] или [gfi] работает с отдельными файлами. Названия от слов set file или get file. Тут все то же самое, только вставляются и вынимаются отдельные файлы. Если их много, то придется писать очень длинный список адресов относительно папки интерпретатора. Я сам чаще всего использую операции [sfo] или [gfo].
. . . Архивы используются повсеместно, и, вообще говоря, это делает операционная система. И есть много специальных программ. Но иногда необходимо работать с архивами автоматически. Например, программа презентации может держать в архиве все свои слайды в какой-то папке. И перед началом работы она должна вынуть слайды из архива, а потом уничтожить, если нельзя оставлять их на чужом компьютере. Пользоваться внешними программами тоже можно, но это будет медленно и не эффективно..

24. . . . Стоит немного подробнее рассказать про команду #sys . У нее не так много операций, хотя возможно в ЯП Java возможностей и больше. Но фокус этой команды в том, что она использует операционную систему (ОС) того компьютера на котором работает. А ЯП Java изначально проектировался как независимый от операционной системы и даже был проект создания ОС и процессора специально под байт-код Java. Но это не получилось. Не получилось даже продавать ЯП и он раздается бесплатно. Только вариант для работы на смартфонах не бесплатный.
. . . Я сам долгое время работал в Виндовс и постепенно привык использовать эту команду для запуска внешних программ, например, браузера. У этой команды есть операция [rp] от слов run program. То есть можно запустить любой исполняемый файл ОС. В системе Виндовс такими файлами являются exe и bat файлы. Но в этой команде рабочая папка не работает и exe файлы должны быть внутри папки интерпретатора, что очень неудобно. Удобнее запускать bat файлы, в которых можно сделать переход в другую папку или запуск программы по полному адресу. И все это замечательно в ОС Виндовс, но не работает в ОС Линукс и других системах.
. . . В последнее время я добавил в эту команду запись [file=arg;] при которой адрес программы становится аргументом и может быть любым. Более того, в этом случае вообще нет проверки на наличие файла и можно записывать любую команду ОС. То есть теперь в системе Линукс можно просто выполнять одну команду ОС за другой так, как в Виндовс это записывается в bat файлах. На самом деле в Линукс тоже есть командные файлы, но их надо объявлять специальной командой chmod и проще просто выполнять команды ОС не используя командные файлы. То есть во всяком случае есть выбор.
. . . В справочнике очень подробно описано как можно использовать эту команду в разных системах. Я просто недавно переписал статью. По этой причине я не буду тут повторять подробности. Кому интересно, может посмотреть там. Я только скажу, что кроме запуска внешних программ эта команда может сообщить время работы любого кода. У нее есть две операции [st] set time и [gt] get time. Первая запускает секундомер, вторая показывает результат. То есть всегда можно точно узнать сколько работает тот или иной кусок программы.
. . . Следующая команда называется #ag от слов animation graphics. Анимации -- наиболее привлекательная часть программирования для тех, кто ничего не знает и кому ничего не надо, в том числе и для детей. И все ЯП для детей как раз только с этого и начинают. Они появились даже на самых первых персональных компьютерах с 8-мибитным процессором. У нас дома тоже был такой. Сын учился в физ-мат школе, и знал об этом от своих товарищей. И мне пришлось купить ему эту прелесть, причем он все организовал сам. Нашел продавца, привез меня к нему на квартиру и мне оставалось только отдать деньги.
. . . Такие компьютеры в то время были и российские, но очень мало и в магазинах их купить было невозможно. Только по записи и ждать годами как квартиру. А кое-кто привозил их из Европы и продавал в квартире. Компьютер назывался Шнайдер, у меня в сети ВК есть его фотография. Он был в клавиатуре, а показывал на экране цветного ТВ. Подключение компьютера к ТВ делали другие мастера. В 80-х годах еще был социализм, но уже очень разбавленный частным бизнесом. И за такие операции уже практически не наказывали. Началась перестройка.
. . . В ЯП Java есть средства делать анимацию, но каких-то готовых и простых вариантов нет. В команде #ag я как раз сам придумал некоторую простую систему, которая позволяет кое-что делать. У этой команды 6 операций, по первые 5 образуют комплекс, а 6-я просто запускает готовую программу, написанную очень давно полностью на ЯП Java. Все операции записываются одной буквой. Операция o (open) открывает анимацию. Она открывает окно анимации, размеры окна и положение на экране определяют значения параметров. И она же запускает общий звуковой файл. Но проигрыватель звука в Java работает только с файлами без сжатия, то есть wav, au, aif и еще может проигрывать мелодию на синтезаторе по нотам. Такие файлы имеют тип mid. Наиболее разумно использовать последний тип, так как такие файлы имеют малый размер, а качество для фоновой музыки вполне достаточное.
. . . Раньше окно заполнялось цветом, но в последних версиях JRE оно прозрачное. По этой причине надо сразу же делать вторую операцию. Она называется m (move), причем первая операция делается до цикла, в вторая в бесконечном цикле. Эта операция ставит в окно картинку, причем ее центр может быть смещен из центра окна. Картинку она берет из памяти с номером, равным значению параметра [n]. И снова можно указать файл музыки. Но на этот раз разумно записывать файл с микрофона в формат wav. Это может быть короткий комментарий по поводу картинки. А если это игра, то какие-то звуки в игре. Как первая операция. так и вторая записывают заголовок окна анимации. И после этого предполагается, что картинка в памяти перерисовывается. И делается задержка по времени, если это происходит очень быстро.
. . . На новом витке цикла показывается новая картинка, хотя номер ее другой. И так все это может крутиться до бесконечности. Но рисование картинки может занять какое-то время и если нужна быстрая смена кадра, то разумно все картинки нарисовать заранее, записать в память и потом показывать одну за другой. Так можно показать не более 100 кадров. Но потом можно все повторять, либо делать большую паузу и все перерисовывать снова. Показ кадров по очереди похож на кино, только там кадров очень много и каждую секунду показывают 24. То есть запаса хватит на 4 секунды. Но есть другой вариант. Можно делать много кадров в одной картинке и просто смещать ее так, чтобы в окно анимации попадал каждый раз новый кадр. Так можно сделать картинку на 100 кадров.
. . . Вопрос лишь в том, что картинки не сжимаются и может не хватить памяти, отведенной под программу. Но есть и комбинированные варианты. Можно использовать картинку как фон и дорисовывать на ней кое какие объекты. Тогда картинок надо меньше, а рисовать можно быстро. Впрочем компьютер довольно быстро рисует, если не надо что-то очень много считать. И вот так процесс идет бесконечно, но как-то надо его закончить. Есть несколько вариантов.
. . . Первый вариант такой. Закрываем окно кликом крестика в правом верхнем углу окна анимации. Программа сделана таким образом,, что при этом она блокирует все циклы и они заканчиваются. Анимация выходит из цикла в любом состоянии, даже если внутри были еще циклы. И сразу после цикла анимации надо поставить команду #ini . Назначение этой команды -- отменить блокировку всех циклов. И программа начнет работать в штатном режиме. Но иногда необходимо, чтобы пользователь участвовал в анимации. Это тоже возможно.
. . . Дело в том, что каждый кадр анимации сообщает о действиях пользователя точно так же, как команда #w [op=im;]. Об этом написано в 17-й мини-главе. То есть код клавиши в s(2), модификатор клика -- в s(1), координаты клика в s(102), s(103) и даже можно указать область. И цикл можно сделать так, что из него будет выход по требованию клавишей или мышкой. Но картинки в анимации могут меняться не часто или их вообще может не быть. Есть операция [p] parameters, которая тоже возвращает эту же самую информацию. Еее можно поставить во внутренний цикл и она во время паузы будет периодически запрашивать информацию о действиях пользователя. Операция [c] закрывает окно анимации, если выход из цикла был сделан без клика крестика. А операция [i] init обнуляет информацию о проведенных действиях пользователя, после чего все возвращается в начало. как будто он ничего не делал.
. . . И еще раз про музыку. Если написать [file=nomusic;], то музыки не будет. Музыка в операции [o] может зацикливаться, а в операции [m] исполняться однократно. Анимацию можно использовать просто для прослушивания музыки и ничего не показывать, если это кому-то нужно. Среди готовых программ есть программы с номерами 41, 42 и 99, которые как раз используют анимацию. Можно посмотреть как они работают и можно посмотреть их код. Программы 41 и 42 достаточно сложные, а 99 -- относительно простая.
. . . Наконец, операция [s] запускает готовую программу на языке Java, которая показывает анимацию фотографий под музыку, то есть фото-шоу. Ее описание существует в отдельной статье на моем сайт, вот ссылка https://kohnvict.ucoz.ru/acl/vkss.htm. Для нее надо приготовить специальный файл входных данных (протокол) и она по нему выполняет свою работу. Программа была сделана давно, а потом ее код был добавлен к коду интерпретатора.

25. . . . Кто знает объектно ориентированные языки наверно увидели некоторое сходство между командами и их операциями, с одной стороны, и классами объектов и их методами, с другой стороны. Да, так устроен ЯП Java. Но нужно отметить, что я свой язык создавал в 1992 году, за 3 года до того, как появилась Java. И в то время я ничего не знал про язык C++. Просто так совпало, с одной стороны, а с другой стороны, все же разница есть, моя структура намного проще. Нет никакого наследования и никто ни от кого не зависит.
. . . Возможно это не так эффектно, но зато проще. С другой стороны, в моем языке есть сходство и с ЯП Постскрипт, хотя и про него я ничего не знал, когда проектировал свой ЛЯП. Но потом, по крайней мере для меня, они соединились. Я рассказал практически о всех командах, кроме команды графики. Это сделано сознательно в том смысле, что на первых порах без графики можно обойтись. Но и потом, даже через много лет работы с ней я фактически перестал пользоваться командами #g и #eg . Тем не менее, знать их необходимо, но это совсем не сложно.
. . . Более того, эти команды -- единственные, которые переписаны из Java без всяких изменений, один в один. Но для новичка эти слова ни о чем не говорят. И надо все же рассказать как это делается. Я начну с более простого пакета графики, которую выполняет команда #g. Здесь операции имеют из трех букв. Первая операция [open] слово короткое и можно писать полностью. Она задает размеры бумаги для рисования. Но я добавил еще возможность масштабировать координаты рисованных объектов кроме других картинок. Размеры задаются параметрами tw (total width) и th (total height).
. . . Про масштабирование я расскажу позднее, а сейчас самое простое. Итак указали область рисования. Эта область сразу заполняется цветом, номер которого задает параметр col. Это всегда так. Если вам больше ничего не нужно, например, черный квадрат, то следующей операцией будет [clo] close. Надо закрыть процесс рисования и спасти результат. Тут работают параметры [c], [sa], [form]. Все как в операции #w [op=im;]. Если [sa=0 или -1], то картинка показывается на экране и при [c=1] ждет реакции пользователя. Если [sa=-2 или -1], то картинка спасается в файл, имя которого без расширения задает параметр [form]. А если sa > 0, то картинка спасается в память с указанным номером.
. . . Следующая операция [cont] continue позволяет продолжить рисование картинки спасенной в память с заданным номером. Номер определяет параметр [n]. Некоторые параметры имеют определенные функции и во всех командах эти функции одни и те же. А другие операции позволяют нарисовать на заданной области графические примитивы. Операции такие [text] комбинация любых символов, [line] линия, [area] область, [rect] прямоугольник, [oval] эллипс, [arc] дуга и часть круга, [imag] картинка, [axis] оси координат, [rfun] чтение функций, [dfun] рисование функций на графике. последних трех операций в Java нет, они используются в суперкоманде номер 1. Более подробно про все эти операции написано в справочнике. Нет смысла тут повторять этот текст, потому что это исключительно справочная информация.
. . . Теперь про масштабирование. В самом начале и каждый раз перед рисованием объектов по координатам, можно задать параметры параметры [trx], [try], [sca]. Первые два определяют вектор смещения всех координат рисования последующих объектов. В процессе рисования эти параметры можно менять и тогда разные объекты будут смещаться на разные расстояния. А параметр [sca] задает масштабирование в процентах. Если знак плюс меняется все, то есть и размеры и координаты. Если знак минус, то меняются только размеры. Такое дополнение к простой графике хорошо расширяет ее возможности.
. . . Что касается команды #eg (enhanced graphics), то она более продвинута и целиком списана с ЯП Постскрипт. Там есть 15 операций и часть операций выделена в отдельную команду, которая рисует объект под названием контур. Там тоже есть операции open, clos, cont с тем же смыслом. Дополнительно есть операции draw и fill рисования контура или закрашивания области внутри него. Сам контур создается командой #pat . У нее тоже есть операции open, clos, cont и дополнительно операции рисования элементов контура. Также у нее уже на уровне операций есть задание перемещения всех объектов [tran] и масштабирование [scal]. При рисовании текстов, можно задать шрифт и его параметры [chfo], а при закрашивании области можно указать способ [pain]. Это может быть цвет, градиент цвета и обои (матрица из картинки).
. . . Также объекты можно подвергать более сложным преобразованиям типа вращения [rota] и сдвигов разных частей [shea]. Наконец, можно выделять часть области рисунка внутри контура [clip]. Есть и дополнительные возможности, которыми лучше не пользоваться. То есть можно все, что только существует в рисовании. Но это все надо программировать более сложным образом. И тут снова удобно делать суперкоманды или программы, которые делают самое важное и не делают остальное.
. . . Я в самом начале программирования на своем языке весьма часто использовал графические пакеты, и простой, и сложный. Но последнее время использую их крайне редко. Дело в том, что я написал готовую программу номер 8, которая называется Слайд Мейкер (Slide Maker). В ней просто числами задаются размеры картинки, а также сколько картинок и текстов поставить на картину. Для картинок указывается их положение и масштабирование, для текстов то же самое и еще шрифт. Картинки берутся из файлов, а тексты пишутся тут же. И этого хватает чтобы сделать все как надо.
. . . И все потому, что фрагменты из файлов можно приготовить разными способами, вырезать из любого документа, нарисовать в любой технике, хоть в постскрипте Из маленького квадратика любого цвета можно приготовить горизонтальные и вертикальные линии простым масштабированием. Постепенно накапливается целый арсенал готовых объектов и рисовать что-то с нуля уже не требуется. Но графика все же нужна для анимации. И тут я первоначально создавал целую серию суперкоманд, которые упрощают запись команд. Однако для анимации это было не очень хорошо. Но возможности более компактно записать графику с помощью процедур все равно существуют.
. . . У профессиональных сайто писателей существует практика делать макеты в программе Фотошоп и только потом писать код. Не знаю насколько это правильно, ведь фотошоп сделан для глупых людей, которые не умеют программировать. Эти люди учат только только языки сайтостроения и другие им как бы не обязательно знать. Точнее у них разделение на фронт и бэк энды. То есть одни делают внешний вид, другие все остальное, то есть расчеты, базы данных и так далее. И каждый знает только свое. Как робот или токарный станок. Потому так и получается. А еще есть заказчик, который совсем ничего не умеет и потому не может толком объяснить что ему надо. Вероятно поэтому и нужен фотошоп. Вместе с тем программирование графики -- очень мощный инструмент.
. . . Ведь программу Фотошоп сделала та же фирма Adobe, которая придумала постскрипт, и она широко его использует. Мне достаточно использовать бесплатную программу FastStone Image Viewer. Правда последние версии уже просят донаты, но платить не обязательно. Все наиболее часто используемые процедуры показа и преобразования картинок там есть.
. . . Говоря о команде #g я пропустил еще одну операцию. Она называется axon (axonometric). Это рисование аксонометрической проекции трехмерной поверхности. Поверхность задается функцией двух аргументов z(x,y) и рисуется таким образом, как будто она проектируется на некую плоскость, перпендикулярную линии между глазом наблюдателя и центром этой поверхности. При этом учитываются искажения, если расстояние до наблюдателя невелико и не рисуются части линий, которые невидимы. Фокус в том, что исходно линии аргумента на плоскости z=0 в точках пересечения образуют двумерную матрицу.
. . . Эта двумерная матрица поточечно преобразуется в другую двумерную матрицу, когда z > 0 и переменное. И возможно перед рисованием просто вычислить эту матрицу. И затем просто остается соединить новые точки линиями. так в данной операции программа и поступает. Просто у нее есть еще один набор параметров --видимость. Не все отрезки видимы. Те, которые не видимы, как бы есть, но не рисуются. Интересно, что такая техника позволяет рисовать не только растровые но и постскрипт рисунки. Об этом будет далее.

26. . . . Я рассказал о всех особенностях ЛЯПа, которые так или иначе связаны с ЯП Java, на котором написан интерпретатор. Точнее, это та часть, которую я использовал из общего описания языка 4-й версии, которая была в момент активного использования моего ЛЯПа. На самом деле я начинал с 2-й версии, но просидел на ней недолго, потом была 4-я версия. А однажды я использовал чужой код из каталога программ, и для него нужна была 5-я версия. Я скачал 6-ю версию компилятора, которая была на тот момент последней и на этом остановился до настоящего времени. То есть я с ней компилирую свой интерпретатор.
. . . А время шло и новые версии все появлялись. В какой-то момент я решил посмотреть одну чужую программу на Java и для нее нужна была какая-то высокая версия. Я скачал 22-ю версию. Фокус в том, что мне нужна была только виртуальная машина, но последние годы Java развивается как-то странно. Новые версии виртуальной машины продолжают номер 8 и только меняется дополнительный номер. Он уже больше, чем 440. А виртуальные машины с номером выше 8-го даются вместе с компилятором, как это делается и в Линукс. Надо скачать компилятор и оттуда можно вынуть виртуальную машину для работы Java программ.
. . . Хотя у меня есть компилятор 22-й версии, но я его так и не освоил. Мне пока всего хватает и с 6-й версией. Но я вовсе не обязан ограничиваться только базовым составом языка. Я могу использовать и готовые программы, написанные на языка Java. И вот теперь я хочу рассказать об этом. Первой командой такого типа является команда #ps. Она способна создать файл постскрипт графики для пользователя, который этого ЯП не знает. На самом деле Постскрипт -- тоже интерпретируемый язык, причем у него есть интерпретаторы, но нет компилятора. Текст на языке Постскрипт можно написать в любом текстовом редакторе.
. . . Но на моем ЛЯПе можно создать только eps файл, то есть рисунок на одну страницу. Вообще говоря, постскрипт файлы создаются многими программами, из которых для ученых более всего известен Латех. Латех может создавать многостраничные постскрипт файлы документов, но основная цель этой программы -- писать форматированный текст и формулы. Что касается рисунков, то их просто можно добавить в виде готовых eps файлов постскрипт графики. Но в данной системе есть еще дополнительная кодировка Метапост, которая может создавать графику. Лично я ей не пользовался, так как довольно рано выучил постскрипт и мог писать eps файлы сразу. В системе Метапост надо снова много писать, а я это не люблю.
. . . У команды #ps есть несколько операций, которые позволяют что-то сделать, но не все. Первая операция [of] open file заказывает размер рисунка. Параметры tw и th указывают размер, но не в точках, а единицах pt. Хотя это сокращение от слова point, но единица имеет реальную длину. Так для размера бумаги формата А4 нужно задавать 596*843 pt. А почему интересует бумага тоже понятно. Этот язык создавался для управлением работой принтеров в локальной сети операционной системы Юникс. Принтер прочитывал текст, компилировал его в свой растр и печатал растровую картинку. А сам код никак не зависел от того, какое у принтера разрешение. Так же точно программы показывают постскрипт рисунки и на экране любого прибора от ноутбука до смартфона.
. . . А параметр form указывает имя создаваемого файла, но без расширения. Оно всегда eps. Вторая операция [cf] close file без параметров просто говорит о том, что рисование закончено и файл можно записывать на диск. Самой важной операцией операцией является [ps]. Она позволяет включить в новый рисунок готовый постскрипт код, который можно взять из какого либо источника. Его можно взять из файла, а если [file=here;], то из массива t() и его часть определяется параметрами [b] и [le]. Важно, что картинку можно перенести в любое место их начала и поменять размер. Детали лучше смотреть в справочнике по ЛЯПу. Также есть операция [pf] plain figure. Она имеет очень много параметров и рисует рисунок такого же типа, как и аналогичная операция команды [pf]. Ноя про нее не рассказывал. Вместо нее я рассказывал про суперкоманду ##1. Вот она как раз и использует эту операцию. Детали снова можно узнать в справочнике.
. . . И еще есть одна операция [ax], которая рисует аксонометрическую проекцию трехмерной поверхности. Я про нее рассказывал при описании команды простой графики #g . Рисунок получается точно такой же, но записанный в векторной графике. Я уже рассказывал как это делается. Просто вычисляются искажения двумерной сетки и определяется видимость отдельных узлов этой сетки. А потом записывается серия команд рисования линейных отрезков.
. . . Вот и все, чем можно манипулировать на уровне команд. Но я также сделал готовые программы на своем ЛЯПе, которые могут рисовать рисунки любой степени сложности. Кстати напомню, что операция #f [op=tops;] конвертирует растровые картинки в постскрипт формат. И потом этот код можно использовать для вставки в eps файл. А готовые программы имеют номера 49 и 50 и есть еще программы, которые работают в старых версиях интерпретатора, но до сих пор не включены в новую систему просто потому, что я сам уже давно их не использую.
. . . У меня на сайте есть книга с описанием ЯП Постскрипт, где все просто и подробно описано и есть примеры готовых программ, так что проще выучить язык, чем писать кучу параметров, которые потом переписываются в еще более сжатый код. Но возможно в будущем я их все же включу в список готовых программ. Я уже писал выше, что лично я даже перестал пользоваться командами графики моего ЛЯПа. Проще написать рисунок на языке постскрипт и потом перезаписать в растровом виде. В западные журналы я посылал рисунки только в постскрипте. К сожалению, это уже почти невозможно. За публикацию в западном журнале сейчас надо платить деньги, да еще санкции. А в российских журналах принимают только jpg рисунки и потом перерисовывают. Так делали в прошлом веке, так и осталось. Но я все равно делаю постскрипт и потом конвертирую в jpg. Причем иногда цепочка такая eps >> pdf >> png >> jpg. Первый этап через Миктех, второй онлайн, третий -- с помощью программы FastStone Image Viewer.

27. . . . Последняя команда, о которой еще не говорилось в этом рассказе называется #pd , но можно писать и #pdf если кому-то так нравится. Это пока единственный пример включения в ЛЯП полностью внешнего кода, который расширяет возможности ЯП Java. Очень много лет назад, точно не помню сколько, я узнал из интернета о существовании пакета iText для разных ЯП. Цель пакета -- дать инструмент для работы с pdf файлами. Я нашел этот пакет для ЯП Java в каталоге программ SourceForge. Он и сейчас там есть, вот ссылка https://sourceforge.net/projects/itext/. Я его скачал, немного изучил описание и сделал команду, которая его использует в работе.
. . . Это библиотека уже откомпилированных классов размером 2 Мб, что даже немного больше всех классов, которые я сам сделал. Но в масштабах возможностей компьютера, то есть его оперативной памяти, например, это не так много. Я не стал очень подробно изучать документацию, а просто выбрал то, что лично мне нужно в первую очередь, и сделал набор операций для работы с pdf файлами. Эта команда не создает pdf файлы. Это можно делать разными способами, в том числе конвертировать из других форматов. Она просто позволяет редактировать уже существующие файлы.
. . . Но в процессе редактирования новые файлы все же получаются. То есть они создаются, но не программируются. В этой части я расскажу как это работает, но без подробностей, которые можно узнать в справочнике по ЛЯПу. Снова первая операция [open]. Она сообщает программе параметры создаваемого файла. Это полный размер, размер рабочей области, сдвиг ее из начала, то есть поля, снова все в единицах pt. Говорят, что pdf -- это тот же постскрипт, только по другому записывается, более компактно. Читать его можно, только не понятно. Наверно можно даже научиться понимать, но я не пробовал. Также есть очень сложный способ задания модификаций.
. . . То есть документ может иметь надписи над рабочей частью сверху (header) и снизу (footer), может быть с паролем, с мета данными и еще кое-что. В справочнике все написано, но многое из того, что можно делать я сам лично никогда не делал. Но, возможно кому-то захочется это делать. Снова напоминаю, что размеры бумаги формата А4 равны 596*843 pt. Также есть операция [clos] , которая заканчивает формирование pdf документа и записывает pdf файл. Остальные операции наполняют текст содержанием. Так можно писать текст. Для этого есть операция [para], которая начинает новый параграф текста и сообщает как его делать, отступы и так далее. И есть операция [text], которая записывает сам текст и сообщает кк это делать (шрифт, размер, цвет, . . .). Текст я никогда не писал.
. . . А вот для записи в pdf файл картинки есть операция [imag]. И вот это я часто использовал. Эта команда очень хороша для распечатки картинок на принтере. На бумагу размером А4 можно разместить картинки в произвольном порядке и после преобразований, таких как вращение, масштабирование и еще кое-что. И потом принтер все это аккуратно распечатает. Но можно также легко делать презентации. Программа Adobe Reader умеет показывать презентации из pdf файлов. Причем в этом случае совсем не обязательно заказывать размеры бумаги. Они могут быть любые и с любым аспектным отношением.
. . . Важной операцией является также [page]. Она переводит курсор записи pdf файла на следующую страницу. Это важно для принтера, но и не только. Для презентации тоже важно. И вообще текст не должен вылезать за пределы. Иногда переход на следующую страницу делается автоматически, но иногда необходимо делать его и вручную. Еть еще операция [smar] set margin array. Она устанавливает поля на следующей странице, если они изменились. Для печатания книг есть операция [smmi]. set margin mirrow inversion. Она устанавливает режим зеркального отражения полей от страницы к странице. Еще есть операция [spgn] set page numbers. Она вводит режим нумерации страниц, если он ранее отсутствовал.
. . . Многими из указанных выше операций я ни разу не пользовался. Но есть и еще более крутые операции. Так [opeg] вводит режим графики. После нее можно использовать все операции команды #eg , а операция [cleg] закрывает этот режим. То есть любую готовую программу рисования картинки можно рисовать не только в растровом формате, но и сразу в векторном. Однако часто проще нарисовать в растровом и потом вставить картинку. Но могут быть случаи, когда лучше делать растр из pdf файла.
. . . Наконец есть еще две очень важные операции, которыми я тоже часто пользуюсь. Первая [rpdf] прочитывает внешний pdf документ и узнает параметры его страниц. А вторая [wpdf] записывает в новый документ страницу с заданным номером из внешнего документа. Так из книги тезисов докладов можно выделить страницу именно с вашим докладом в отдельный pdf файл. Но для этого надо знать размеры страниц внешнего файла. Эту информацию сообщает первая операция [rpdf].
. . . Вот и все операции. Но рассказ не окончен. Дело в том, что формат pdf часто используют для записи документов. У этого формата есть секретность, его можно читать по паролю. С другой стороны, даже того минимума средств, какие я описал достаточно для подделки документов мошенниками. В частности, среди готовых программ есть номера 13 и 14. Они позволяют записывать в уже существующий файл pdf документа текст и рисунки. То есть из любого сколь угодно большого psf файла можно выделить страницу и кое что в ней переписать. Например, имя автора книги, или картинку с чужой подписью. А потом вставить страницу обратно.
. . . И ничего не поделаешь. Запретить нельзя. Ведь даже кухонным ножом можно убить, и были такие случаи. Но не запрещать же после этого кухонные ножи. Люди уже очень давно привыкли есть не пачкая руки. А есть еще спички, от которых может быть пожар. И есть дети, которые ничего не понимают и не знают. Но без спичек тоже неудобно жить, хотя и возможно получать огонь трением. И даже есть такие приборы. И газовые зажигалки как раз из таких. Сейчас идет цифровизация и придумывают способы как обезопасить и упростить электронные подписи. Даже постоянные пароли уже не годятся. Нужны временные по смс. Жизнь быстро меняется. Посмотрим что еще придумают.

28. . . . В этом месте я бы хотел сделать остановку. Не закончить, так как можно еще много о чем рассказать. Но подвести первые итоги. При написании книг есть два подхода. Раньше любили писать содержание частей в конце. Потом стали это делать в начале. Мол, так читателю будет сразу понятно что есть, а чего нет. Но в этом рассказе я исходил из того, что любой читатель может начать читать и потом бросить это делать. Потому что часто даже не важно ЧТО написано, а важно КАК написано. И если написано хорошо, то и не важно о чем. Оглавление не имеет значения.
. . . И уже только после прочтения текста для тех, кто дошел до конца, становится важным содержание. Просто для того. чтобы еще раз пересмотреть какие-то куски. И при таком подходе содержание лучше давать в конце. А у меня все не так, как у всех. И содержание будет в середине, которая пока является концом. То есть уже пора показать содержание. А потом оно будет отодвигаться все дальше и становиться все длиннее. Итак, я показываю содержание, оно ниже
. . .
. . . . . . 01. Введение
. . . . . . 02. Личный язык программирования (ЛЯП) и команды операционной системы ОС
. . . . . . 03. Зачем нужен новый язык. Об этом и немного истории создания ЛЯПа
. . . . . . 04. Основные принципы ЛЯПа, интерпретатор и глобальная память
. . . . . . 05. Структура ЛЯПа, команды и их операции, а также параметры
. . . . . . 06. Массивы, циклы и условия, все проще и все иначе
. . . . . . 07. Про условия подробнее и про ЯП Питон
. . . . . . 08. Организация процедур, снова просто, но со вкусом
. . . . . . 09. Выполнение процедур, много разных способов
. . . . . . 10. Суперкоманды, как специальные процедуры, и их устройство
. . . . . . 11. Математические вычисления и команды для них
. . . . . . 12. Команда #ma и пример первой программы
. . . . . . 13. Команда #pr и форматированный текст, снова не как у всех
. . . . . . 14. Суперкоманды 1 и 2 более подробно, важно для показа вычислений
. . . . . . 15. Графика и постскрипт, размышления об этом
. . . . . . 16. Файлы, команда #f и работа с текстовым редактором
. . . . . . 17. Картинки, команда #w и коллекция картинок в памяти
. . . . . . 18. Команды #ch, #sel, #col, #inp, как общаться с пользователем
. . . . . . 19. Обзор других коротких команд ЛЯПа, это скелет программы
. . . . . . 20. Команда работы с файлами #f более подробно 1-я часть
. . . . . . 21. Команда работы с файлами #f более подробно, 2-я часть
. . . . . . 22. Команды #m, #bi и внешние процедуры, еще больше возможностей
. . . . . . 23. Команды #te и #z, то есть работа с текстом и зип архивы
. . . . . . 24. Команды #sys и #ag, то есть команды ОС, время и анимации
. . . . . . 25. Команды #g и #eg, то еть простая и сложная графики
. . . . . . 26. Версии ЯП Java и команда #ps, для создания постскрипт файлов
. . . . . . 27. Команда #pd для создания pdf файлов и манипуляций с ними
. . . . . . 28. Заключение
. . .
. . . А сейчас несколько слов о том, что с этим делать. Интерпретатор моего ЛЯПа уже много лет бесплатно доступен в интернете. На моем сайте есть статья о том, как скачать файлы и как запускать программу. В этой статье также кратко описаны готовые программы и как с ними работать. А если учиться программировать, то это как раз примеры кода готовых программ. Есть и другие статьи с примерами кода. Вообще говоря, число статей, в которых описывается ЛЯП уже довольно много. Некоторые их них с общей информацией, но менее удобные, чем три справочника. Некоторые подробно описывают конкретные готовые программы. Но есть и просто примеры. Код готовых программ и суперкоманд лучше всего смотреть с помощью готовой программы номер 26. Готовые программы в файле pro00.txt, а суперкоманды -- в файле proc00.txt. Если вдруг обнаружится непонятная ошибка, то можно писать мне на адрес электронной почты. Адрес сайта и почты указан под заголовком.
. . . По своей работе я на своем ЛЯПе написал много программ, я последнее время взялся писать очень большую программу которая решает много задач. На любом другом ЯП я бы не взялся это делать, так как пришлось очень много всего писать. Много букв. Считается, что ЯП с глобальной памятью и не объектные не годятся для написания больших программ. И вот я своим примером как раз опровергаю такое мнение. А вот что касается работы в коллективе, то тут я ничего не могу сказать, так ка не пробовал. Проблема в том, что в любом коллективе есть дураки и что с ними делать не очень понятно. У нас ведь либерализм и демократия. Но ракеты взрываются на старте, корабли тонут, попав в воду, мосты ломаются от ветра.
. . . Так что это личный ЯП и для личного использования. Так его и надо понимать.

.


.