Просмотр полной версии : Кое-что о Лиспе на Атари-8
Здравствуйте, дорогие друзья.
Для 8-битной Атари существует единственная версия интерпретатора Лиспа
- Интерлисп/65.
Я заинтересовался Лиспом давно, но всё это было - чисто академический интерес,
так как я вообще не мог представить как его можно использовать на Атари.
Всё же, у меня для сравнения было три версии Интерлиспа и так или иначе, я засел за изучение языка.
Сначала об истории.
В 30-е годы прошлого века жил-был могучий математик Дэвид Гилберт.
После смерти Пуанкаре, его стали считать первым математиком планеты.
Он был вполне непоседлив и изъездил всю математику вдоль и поперёк.
Каждый вздрогнет, вспомнив теорему Коши-Буняковского и Гильбертовы пространства.
Вот с него-то всё и пошло...
Так вот, именно он внезапно перед своими сотрудниками залепил жуткую задачку:
Энтшайдунгс-проблЕм. Задачка эта касалась анализа и формализации вычислимости.
Спросил он следующее: Существует ли формальный аппарат, внутри которого можно
написать произвольное утверждение, которое можно будет доказать за конечное число шагов средствами самого этого аппарата?
Собственно он спросил: "Существуют ли алгоритмы?!!"
Все забегали и озаботились...
Там была ещё парочка шикарных математиков которые вкурили эту проблемку аж на
20-лет и в конце концов оба доказали, что в арифметической формализации - НЕ СУЩЕСТВУЕТ! В общем же случае - Существует.
Благодаря этим исследованиям, один из них с помощью АНАЛИЗА глобальной задачи придумал формализацию "Решающей машины" имени самого себя любимого...
- это был Алан Тюринг и придумал он машину Тюринга.
Второй же, с помощью СИНТЕЗА малых подзадач придумал формальный язык способов вычислений, а именно - теорию "Лямбда исчисления" и это был - Алонзо Чёрч.
В конце концов в 1957 году небезызвестные Джон Бэкус и Петер Наур реализовали язык Фортран,
а небезызвестный Джон Маккарти в 1958 году реализовал язык Лисп.
Разумеется, первый язык был воплощением аналитической тюриговской машины, а второй синтетического Лямбда исчисления.
Сам по себе Наур интересен фамилией, моральный ИНДУС, знаете, ли...
Он Бэкусу сказал, что на Санскрите вообще всё определено, Как, Что и Когда говорить ...
И озаботил Джона !!! И ВОТ Вам факт!
Ну, в общем, я родился в 1959 году и однажды тоже озаботился задачкой вычисления "Счастливого билета" на разных языках.
В случае Фортраноподобных языков, алгоритм будет следующим:
1. Так как на билете шестизнак, то следует построить убывающий цикл,
в котором надо будет делить сам шестизнак, а потом и его остатки на степень десятки (5->0), получая правильные частные значения.
2. Сложить три первых значения, затем три вторых.
Вычесть одну сумму от другой и если 0, то вуаля, вы слопали билет. :)
В случае Лиспоподобных языков, алгоритм выглядит по другому:
1. Распаковать шестизнак в список десятичных чисел.
2. Взять (Счёт ведётся от НУЛЯ) третий хвост списка
3. Найти сумму всех чисел в шестизнаке и вычесть из этой суммы сумму чисел третьего хвоста.
4. При нуле питаться! :)
Вам не показалось, что второй способ - это именно то, как мы-люди интуитивно подсчитываем съедобность билета?
Вот вычислимость билета на ЛИСПЕ:
;;;; Проверка на счастливый билет
;;;; Интерлисп/65 Для Атари 8-бит
;;; Добавим предикат пустоты списка.
(DEFUN NULL (L) ; Зададим имя и параметр функции
(EQ L NIL)) ; Проверка на равенство NIL(Пуст по определению) списка L
;;; Добавим суммирование элементов списка L
(DEFUN SUM (L)
;; NIL это терминатор хвоста любого списка !
;; Используем наш предикат для проверки на исчерпание списка
;; COND проверяет СПИСОК предикатов останавливаясь при первом T !!!
(COND ((NULL L) ; При пустоте или исчерпании списка
0) ; Сумма = 0
(T ; В противном случае, (T - терминатор для COND)
;; рекурсивно, начиная от хвоста прибавляем все частные головы списка ...
;; (CAR L) - предыдущая голова
;; (SUM (CDR L)) - уже найденая сумма хвоста
(+ (CAR L) (SUM (CDR L))))))
;;; Вывод промпта и получение шестизнака
(DEFUN PROMPT NIL
;; PROGN задаёт итеративное исполнение форм
(PROGN (POKE 128 0) ; Отключение промпта Лиспа
(PRIN1 (QUOTE "Enter 6-digits ticket number> ")) ; Печать промпта
(SETQ NUM (READ)))) ; Присвоение переменной данных ввода с клавы
(DEFUN HAPPY-P NUM
(PROGN (SETQ LIS (UNPACK NUM)) ; Присваиваем распакованное число списку
(SETQ S (SUM LIS)) ; Вычисляем полную сумму списка
(SETQ R (SUM (@ LIS 3))) ; Вычисляем сумму элементов 3 хвоста
(SETQ L (SUB S R)))) ; Вычитаем из полной суммы
(DEFUN LUCKY NIL
(COND ((EQ L R) ; Если левая и правая суммы равны
(PROGN (POKE 128 0)
(PRINT (QUOTE "Eat me, Honey !"))))
(T ; В противном случае
(PROGN (POKE 128 0)
(PRINT (QUOTE "Bad-luck poor Yorick !"))))))
(DEFUN TICKET NIL
(PROGN (SETQ NUM 0) ; Инициализация переменных ...
(SETQ LIS NIL) ; ...
(SETQ L 0) ; ...
(SETQ R 0) ; ...
(PROMPT) ; Вывод промпта и ввод шестизнака
(HAPPY-P NUM) ; Проверка на счастливость
(LUCKY))) ; вывод результата
Вообще говоря, история Лиспа - это просто фантасмагория какая-то.
Ну, не зря говорят, что Лисп - язык Искуственного Интеллекта.
Дело в том, что когда программируешь на Лиспе, всё время ощущаешь,
что ГОВОРИШЬ с машиной. Именно на её языке!
Все начинают обучение Лиспа с Факториала. Для начала и нам он подойдёт.
Факториал - это произведение всех неотрицательных целых чисел включая заданное.
Обратите внимание, что НОЛЬ тоже включён, только на него умножать не надо! :)
Математически, рекурсивное определение факториала следующее:
/N=0, N! = 1
\N>0, N! = N * (N-1)!
А вот - запись на Лиспе:
;;; Факториал
(DEFUN ! (N)
(COND ((EQ N 0) ; При равенстве N нулю
1) ; будет единица
;; В противном случае N умножается на факториал от (N-1)
(T (* N (! (SUB N 1))))))
Как говорится, ищите 10 отличий...
Вот трассировка:
(! 4)
-->!/ARGS: (4)
-->!/ARGS: (3)
-->!/ARGS: (2)
-->!/ARGS: (1)
-->!/ARGS: (0)
<--!/VALUE: 1
<--!/VALUE: 1
<--!/VALUE: 2
<--!/VALUE: 6
<--!/VALUE: 24
24
Стоит заметить, что на каждом этапе рекурсии происходит не только умножение на N, но и вызывается САМ факториал, подразумевающий, в свою очередь ещё одно умножение на N. Из-за того, что ВСЯ функция Факториала вычисляется на каждом этапе рекурсии при помощи ленивых(отложенных) вычислений, всё идёт медленно (Квадратичное замедление!).
Очевидно, что здесь лучшим был бы рекурсивный подход c накопительным аргументом.
Пусть наше N будет нумератором. Введём ещё один аргумент A - Аккумулятор, тогда, введя новую функцию !AUX, где счёт рекурсий будет от N до 1, и на каждой будет только умножение N-1 на A, а не рекурсивный вызов Факториала, получим быстрый алгоритм (Линейное замедление).
;;;Враппер - Вызывающая функция факториала для включения нуля в определение.
(DEFUN ! (N)
(COND ((EQ N 0) ; Если N=0
1) ; То !=1
;;; При ненулевом аргументе вызов вычисляющей функции с аргументами N и 1.
(T (!AUX N 1))))
;;; Быстрая рекурсия факториала. Изначально в Нумераторе - N, в Аккумуляторе - 1.
(DEFUN !AUX (N A)
(COND ((EQ N 1) ; Терминатор вычислений. Когда N станет 1,
A) ; Выводится накопленное содержимое Аккумулятора.
;;; В противном случае функция пошагово декрементирует Нумератор и
;;; умножает его на Аккумулятор. Результат помещается в Аккумулятор.
(T (!AUX (SUB N 1) (* N A)))))
;;; НУМЕРАТОР АККУМУЛЯТОР
Вот трассировка:
(! 4)
-->!/ARGS: (4)
-->!AUX/ARGS: (4 1)
-->!AUX/ARGS: (3 4)
-->!AUX/ARGS: (2 12)
-->!AUX/ARGS: (1 24)
<--!AUX/VALUE: 24
<--!AUX/VALUE: 24
<--!AUX/VALUE: 24
<--!AUX/VALUE: 24
<--!/VALUE: 24
24
Атарька говорит, что (! 40) = 8.159152512E+47 :)
Без трассировки вычисляет за 1 секунду.
Чтобы показать мощь языка давайте напишем решение одной задачки, которая не поддалась Алонзо Чёрчу, но была решена его учеником Стивеном Клини через 12 лет.
Вот математическое рекурсивное определение:
(X=1 + (-1)) = 0
((X + 1) + (-1)) = X
А вот вычислитель на Лиспе:
(DEFUN DCR1 (X Y Z)
(COND ((EQ X 1) 0) ; По определению, если x=1 То DCR1=0
(T ; При другом X ...
(COND ((EQ (+ Y 1) X) ; Y - Инкрементный терминатор числа проходов
Z) ; Z - Накопительный аргумент
(T ; В противном случае рекурсия
(DCR1 X (+ Y 1) (+ Z 1)))))))
LISP
(DCR1 5 0 0)
4
То есть в своём Декременте мы
свели вычитание единицы из натурального числа к прибавлению единицы !!!
Ни одного (SUB N 1) в программе НЕТ!
Вообще говоря, математика - это нерадостное *****!
Которое, ещё ВРЁТ!
LISP
(А в смысле Физики, так ГУСТО !!!)
Но, - НАДО!
Булькать!
Для флуктуирования я всё время употребляю программу КОВРИК, которая на разных языках выводит ... КОВРИК.
Прямо на экране.
Вот Коврик на Лиспе:
(DEFUN PRAND NIL
(COND ((> (PEEK 53770) 127) ; Если содержимое RANDOM-регистра больше 127...
(PROGN (POKE 128 0) ; Запрещаем вывод значения функции
(PRIN1 '"/"))) ; Печатаем Слэш
(T (PROGN (POKE 128 0) ; Иначе
(PRIN1 '"\"))))) ; Печатаем обратного СлэшА
(DEFUN KOVRIK NIL
;; PROG is Iterator
(PROG NIL
(POKE 752 1) ; Запрет курсора
(POKE 82 0) ; Установка левой границы
LOOP ; Просто метка
(PRAND) ; Случайная печать
(GO LOOP) ; Переход
(POKE 752 0))) ; Восстановим курсор
Может, кого и порадует ... :)74156
Добавил Видео https://youtu.be/giohCD0fGD4 :)
редактирования демо-программки.
zen
на прологе все комбинации счастливого билета много проще
in(X,[X|_]).
in(X,[_|L]):-in(X,L).
is_happy(A,B,C,D,E,F):-L is A+B+C,R is D+E+F, L = R.
?-Z=[0,1,2,3,4,5,6,7,8,9],in(A,Z),in(B,Z),in(C,Z),in(D,Z),in(E,Z),in(F,Z),i s_happy(A,B,C,D,E,F),write([A,B,C,D,E,F]),nl,fail.
Raydac
Есть чо сказать?
Я как раз ищу способ написать интерпердатор Пролога.
Пока не нашел.
А так, благодарю за сообщение ЧЕССНО!
дак а чего искать способ, штука несложная, я когда пролог изучал то сел да написал (https://github.com/raydac/jprol), лет 11 чтоль назад, японец один потом на айпад переделал версию
Есть ли код?
Вроде паскаля или си.
Я бы попробовал тогда на PL65 затуганить...
Только я ни разу не программист... Укротитель я... :)
У меня сейчас на нём пара наработочек: доступ ко всей расширенной памяти и библиотека списков. :)
zen
Есть ли код?
Вроде паскаля или си.
у меня только на Java, это уже гуглить надо, вроде исходники движков есть от JavaScript (TauProlog) до версий на clojure (считай на лиспе)
Есть какие-то хрени, гуглящиеся на Java2pas, но приблизят ли они топикастера к его цели неизвестно. Надо пробовать. Был бы интересен Prolog и для всего, где реализован консольный uLisp (http://www.ulisp.com/).
Есть какие-то хрени, гуглящиеся на Java2pas, но приблизят ли они топикастера к его цели неизвестно.
Пролог предельно простая штука, если не пытаться сделать "самый быстрый" и "самый меньше всего жрущий ресурсов", поэтому он и для Спектрума был и даже для БКшки
Ну не у всех Прологов одни и те же возможности. Имея реализацию Lisp-а было бы естественно реализовать Пролог на Lisp-е (https://qastack.ru/cs/6618/how-to-implement-a-prolog-interpreter-in-a-purely-functional-language).
И такие реализации с ненулевой вероятностью существуют. На uLisp-е uProlog мне не попадался. Хотя для него-то по крайней мере с поддержкой графики( не говорю о распознавании графических образов) не надо париться.
Насчет предельно простая штука не уверен( Не на всяком сделаешь базу знаний и обнаружение неполноты знаний. Там где аксиомы прописаны вместе с фактами и весь фокус-покус в логических выводах наверное да) Конечно какой-нибудь Турбо Пролог от Borland не слишком сложная штука, но так как стандартов на него не существует, тут уж кто во что горазд. Впрочем с Lisp-ом примерно та же ситуация.
- - - Добавлено - - -
поэтому он и для Спектрума был и даже для БКшки
опять же как память тратить...понятно для двоичной логики битов достаточно, но только у этих процессоров побитово адресуемой памяти кажись не было, а сдвигами если, то экономия в одном и расточительство в другом. Поэтому и пытались и Lisp, и Prolog на уровне железа поддерживать в 80-е. Как себя нынешние ARM M0,M3, M4 себя с этим ведут пока не вникал.
Ну, вообще говоря реализация Пролога для меня пока - просто туман и маниловщина.
Просто в последнее время я много и успешно работал с PL65 и пользуясь тем,
что в нём есть встроенный ассемблер и нормальная документация полагаю там справится и с битовыми масками и пр. можно.
Беда в том, что современный Лисп и Пролог, просто обязаны использовать расширенную память, а это уже прямая зависимость от HW.
Схем раздачи фреймов памяти - просто тыща. Эмуляторы отрабатывают с трудом и глючно.
Сами схемы не всегда достаточно обоснованы, что ведёт к жуткой путанице в определении причин сбоев и пр.
Ну, просто представьте, что в Интерлиспе/65 нет способа получить ATASCII код буквы.
Что же для этого ассоциативный список, что ли строить? Нет интерфейса к Ассемблерным программам.
Из-за того, что ввод данных с диска - поток атомов, где пробелы игнорируются как разделители, даже через XIO
невозможно по человечески вывести директорию.
Ничто не задокументировано, так как ремарок нет.
Лисп компилятора тоже нет.
Но я всё же пытаюсь сделать что-то весёлое...
zen
Видимо авторы делали не удобный и полезный инструмент для себя, а для каких-то других целей. Или не успели довести до ума.
uLisp распространяется без исходников, но для кучи платформ и есть интерфейс к ассемблерам. К сожалению для 6502 версии нет, так что остается или прикрутить его ассемблер самостоятельно или искать в исходниках, или конвертить из одних исходников в другие.
Совсем экзотика найти или разработать Atari-8 на чипах(по сути эмулировать в железе), поддержанных uLisp, и с учетом имеющихся графических и иных библиотек. uLisp поддерживает SD card interface (http://www.ulisp.com/show?207M)
Ну а после этого Prolog, написанный на Lisp будет доступен в исходниках.
по прологу есть книга неплохая, называется "the implementation of Prolog"
Сделать пролог на лиспе даётся как лабораторная работа :)
Вот например: http://ds.knu.edu.ua/jspui/bitstream/123456789/1023/1/labsbook.pdf (последняя лабораторка в самом конце документа)
Он, конечно, совсем простой, факты и правила записываются списками на лиспе. Но, судя по всему, это должно работать.
Реализацию в студию пожалуйста!
Ну, насчёт реализации -я пессимист.
Всё правильно. Хотели сделать нормальный ЛИСП, но ...
Просто забросили!!!
В доказательство - код из библиотеки LDUMP:
;; Распечатка Форм из "Директории файла" (Properties)
(DEFUN LDUMP (PROPS)
(PROGN (OPEN 1 8 (QUOTE P:)) ; Открыть 1 IOCB на вывод
(PR# 1) ; Перенаправить вывод с терминала на 1 IOCB
(MAPCAR PROPS ; Для каждой формы в директории ...
(LAMBDA (X) ; X - это директория файла
(PROGN (TERPRI) ; Исполнять последовательно ...
(TERPRI) ; CR
(PRIN1 (QUOTE "**** ")) ; Звёздочки без CR
(PRINT X) ; Имя формы + CR
(PPRINT (GETD X))))) ; Печатать определение
(PR# 0) ; Вернуть вывод на Терминал
(CLOSE 1))) ; Закрыть 1 IOCB
;; Установка отступа в Печатуемой строке на N позицию пробелами!!!
(DEFUN TABX (N)
(PROG (COUNT) ; Исполнять последовательно с циклом ...
(SETQ COUNT N) ; Инициализировать обратный счётчик
LOOP ; Метка
(SETQ COUNT (SUB COUNT 1)) ; Декрементировать
(COND ((> COUNT 0) ; Пока не ноль
(PRIN1 (QUOTE " ")) (GO LOOP))) ; Печать пробела и на метку
(RETURN))) ; По исполнении выйти.
Оба кода рабочие, но в LDUMP нигде не входит TABX.
В результате, никакой PP печати. Хоть формы-то разделены.
(EDIT при PP пользуется встроеной TAB, которая просто устанавливает позицию в строке терминала, следовательно нет пробелов.
Кроме этого, LDUMP пользуется формой PPRINT в составе EDIT, а значит без загрузки D:EDIT бесполезна.
Пока же я пробую выкорчевать из EDIT PP и заставить её печатать так как надо.
zen
Вообще-то сделал.
Вот результат печати:
(DEFINEQ PP
(LAMBDA NIL
(PPRINT S-EXP 2))
)
(DEFINEQ P
(LAMBDA NIL
(PPRINT (CAR CURR) 2))
)
(DEFINEQ PPRINT
(LAMBDA (X IND)
(PROG (TFLG)
(PPAUX X IND)
(TERPRI)))
)
(DEFINEQ PPAUX
(LAMBDA (X INDTN)
(COND ((ATOM X)
(PRIN2 X) (SETQ TFLG))
((ATOM (CAR X))
((LAMBDA (Y)
(COND (Y (MULTARGS X INDTN (CDR Y)))
((PROGN (PRIN1 LPAR)
(PRIN2 (CAR X))
(PPARGS (CDR X) INDTN)
(PRIN1 RPAR)
(SETQ TFLG))
)))
(ASSOC (CAR X) *FORMATS*)))
(((LAMBDA (IND1)
(PROGN (PRIN1 LPAR)
(SETQ TFLG T)
(PPAUX (CAR X) IND1)
(TABRET INDTN)
(PPARGS (CDR X) IND1)
(PRIN1 RPAR)
(SETQ TFLG)))
(+ INDTN 1))
)))
)
(DEFINEQ MULTARGS
(LAMBDA (X INDTN L)
((LAMBDA (INDTN2)
(PROGN (TABRET INDTN)
(PRIN1 LPAR)
(PRIN2 (CAR X))
(PRIN1 BLANK)
(PPAUX (CAR (CDR X)) INDTN2)
(COND ((CDR (CDR X))
(MAPCAR (CDR (CDR X))
(QUOTE (LAMBDA (Y)
(PROG NIL
(TABRET INDTN2)
(PPAUX Y INDTN2)))))))
(PRIN1 RPAR)
(SETQ TFLG)))
(+ INDTN (CAR L))))
)
(DEFINEQ PPARGS
(LAMBDA (X INDTN)
(PROG NIL
LOOP
(COND ((EQ X)
(RETURN))
((ATOM X)
(PRIN1 (QUOTE " . ")) (PRIN1 X) (RETURN)))
(PRIN1 BLANK)
(PPAUX (CAR X) INDTN)
(SETQ X (CDR X))
(GO LOOP)))
)
(DEFINEQ TABRET
(LAMBDA (N)
(PROG NIL
(COND (TFLG (RETURN))
((TERPRI)
))
(SETQ TFLG T)
(COND ((> N LINE-WIDTH)
(TERPRI) (TABX (SUB N LINE-WIDTH)))
((TABX N)
))))
)
(DEFINEQ *FORMATS*(NIL)
)
(DEFINEQ LPAR(NIL)
)
(DEFINEQ BLANK(NIL)
)
(DEFINEQ RPAR(NIL)
)
(DEFINEQ LINE-WIDTH(NIL)
)
(DEFINEQ TABX
(LAMBDA (N)
(PROG (COUNT)
(SETQ COUNT N)
LOOP
(SETQ COUNT (SUB COUNT 1))
(COND ((> COUNT 0)
(PRIN1 (QUOTE " ")) (GO LOOP)))
(RETURN)))
)
(DEFINEQ LDUMP
(LAMBDA (PROPS)
(PROGN (OPEN 1 8 (QUOTE P:))
(PR# 1)
(MAPCAR PROPS
(LAMBDA (X)
(PROGN (TERPRI)
(PRIN1 (QUOTE "(DEFINEQ "))
(PRIN1 X)
(PPRINT (GETD X))
(PRINT RPAR))))
(PR# 0)
(CLOSE 1)))
)
А вот файлик с программами. (нужно учесть что в текстовом редакторе формы не напечатать!)
74250
Это не zip, Надо убрать расширение.
zen
Поскольку нативного железа у меня нет, подскажите пожалуйста, в каком эмуляторе это можно запустить?
Здравствуйте Андрюс!
Ну, если у Вас есть Интерлисп, то - в любом.
Я, ведь просто код в пустом диске прислал ...
Полные диски с документацией Здесь!
74252
А файлик с программкой у Вас уже есть :)
zen
Chewbacca
18.12.2020, 17:27
LISP - Lost In Stupid Parentheses ;)
О, дорогой Chewbacca?
Лисп - это не школа!
Лисп - это ЖИЗНЬ!
Проблема в Японском в том, что сначала надо выучить японский!
Утверждаю, что моя дочка сказала, что ЛИСП проще, чем алголоподобные и далее Си-продукты.
Понять и простить НАДО!
А Скобки ... Ну что Скобки
Цитата: От него жена уходит, а он: " Так-так-так,.. Так-так-так, "...
Скобки - для Структуризации и более Ни-Ни!
zen
- - - Добавлено - - -
Вот список всех доступных функций (с ошибками) при загрузке Inter-LISP/65
(OBLIST)
(AND OR READC PAGE MEM GO PROG TERPRI OBLIST
NEW BREAK SETQ DEFINEQ PROGN NCONC SQRT SIN COS
ATAN LENGTH LAST MEMBER ASSOC PR# IN# SAVE DIR
LOAD OPEN CLOSE LIST @ LOG EXP > INT
/ * SUB + # ATOM %OBJ %ADR LITATOM
POKE PEEK TAB SOUND SETCOL DRAW COL GR PLOT
MOVE PACK UNPACK RPLACD RPLACA POINT NOTE XIO READA
CDAR CDDR CADR CAAR *CDR APPLY* BAKTRACE COND
READ STRIG STICK EQ DEFINE SET APPEND CONS PRIN2
PRIN1 PRINT CDR CAR GETD EVAL D:INIT.LSP MACRO
RETURN RESET NSUBR SUBR NLAMBDA LAMBDA QUOTE ' .
) ( T NIL)
Вот содержимое INIT.lsp:
(MAPCAN MAPCAN-AUX MAPCAR MAPCAR-AUX DELETE DELETE-AUX DEFUN
GET REMPROP PUTPROP *PMEMBER)
Это Всё!
Вот способ запустить программку:
Так как это печать в псевдопринтер, то сначала он устанавливается в эмуляторе.
В Atari800WinPlus - это Notepad.
1. Запустить Лисп без картриджей
2. На промпт о необходимости размещения графики в верхней памяти
а) если нужен 80кол режим то подключаю картридж SDX с драйвером CON 80 Режим памяти BANKED
- то есть вся расширенная память отдана SDX, кроме памяти 130XE, чтобы LISP не ругался.
б) если не нужен, то просто запускаю LISP без картриджей, oн сам подгрузит D:INIT.LSP. Bставляю в D2: pp.atr
Вот ещё полезнейшая вещь:
Печать на псевдо-принтер списка...
(DEFUN PRINL (L)
(PROGN (OPEN 1 8 (QUOTE P:))
(PR# 1)
(PPRINT L)
(PR# 0)
(CLOSE 1)))
То есть, для нашего D2:UTS
1. (LOAD 'D2:UTS)
2. (PRINL D2:UTS)
Распечатается список Properties (Директория файла)
(PP P PPRINT PPAUX MULTARGS PPARGS TABRET *FORMATS* LPAR BLANK RPAR LINE-WIDTH TABX LDUMP PRINL)
- - - Добавлено - - -
Я тут подумал и понял, что всё же как-то надо оптимизировать систему распечаток.
(TABX LDUMP PRINL) - Это всё же только принтерные утилиты...
На досуге сделаю так:
Оставлю PP библиотеку в EDIT в покое, а эти функции (ЖУТКО МЕДЛЕННЫЕ из-за добавления пробелов в начало строк),
к тому же редко употребляемые, переименую и вынесу в библиотечный файл D2:PRINT, который Вам пришлю. :)
zen
Ну, что же ...
Deal Done!
Вот файлик:
74268
Это не zip файл. Удалите лишнее расширение.
В библиотеку входят функции:
(TABX *FORMATS* TABRET PRLIST PRDUMP PRPROP PRFORM)
Инструкция:
Сначала запускаем LISP
Подгружаем (LOAD 'D:EDIT)
При необходимости распечаток подгружаем (LOAD 'D2:PRN)
(DEFINEQ TABX
(LAMBDA (N)
(PROG (COUNT)
(SETQ COUNT N)
LOOP
(SETQ COUNT (SUB COUNT 1))
(COND ((> COUNT 0)
(PRIN1 (QUOTE " ")) (GO LOOP)))
(RETURN)))
)
(DEFINEQ *FORMATS*(NIL)
)
(DEFINEQ TABRET
(LAMBDA (N)
(PROG NIL
(COND (TFLG (RETURN))
((TERPRI)
))
(SETQ TFLG T)
(COND ((> N LINE-WIDTH)
(TERPRI) (TABX (SUB N LINE-WIDTH)))
((TABX N)
))))
)
(DEFINEQ PRLIST
(LAMBDA (L)
(PROGN (OPEN 7 8 (QUOTE P:))
(PR# 7)
(PRINT L)
(TERPRI)
(PR# 0)
(CLOSE 7)))
)
(DEFINEQ PRDUMP
(LAMBDA (PROPS)
(PROGN (OPEN 7 8 (QUOTE P:))
(PR# 7)
(MAPCAR PROPS
(LAMBDA (X)
(PROGN (TERPRI)
(PRIN1 (QUOTE "(DEFINEQ "))
(PRIN1 X)
(PPRINT (GETD X))
(PRINT RPAR))))
(PR# 0)
(CLOSE 7)))
)
(DEFINEQ PRPROP
(LAMBDA (FNAM)
(PROGN (OPEN 7 8 (QUOTE P:))
(PR# 7)
(PRINT FNAM)
(TERPRI)
(PR# 0)
(CLOSE 7)))
)
(DEFINEQ PRFORM
(LAMBDA (X)
(PROGN (OPEN 7 8 (QUOTE P:))
(PR# 7)
(PROGN (TERPRI)
(PRIN1 (QUOTE "(DEFINEQ "))
(PRIN1 X)
(PPRINT (GETD X))
(PRINT RPAR))
(PR# 0)
(CLOSE 7)))
)
ПРИ ЗАГРУЗКЕ ПЕРЕПИСЫВАЮТСЯ ВСТРОЕННЫЕ !!! :
Список *FORMATS*
Форма TABRET
Пользуемся так:
0. Для печати директории(PROPERTIES) файла (PRPROP D2:PRN)
1. Для печати Дампа файла (PRDUMP D2:PRN)
2. Для печати любого списка (PRLIST *FORMATS*)
3. Для печати любой формы (PRFORM 'PRLIST)
Примечание: К сожалению, название формы приходится квотировать, так как форма печати пользуется внутренними переменными Лиспа, а отследить несвязанные переменные можно лишь исследовав ВЕСЬ код EDIT.
С НОВЫМ ГОДОМ! ДОЛОЙ КОРОВАВИРУС!
zen
А вот и Новоггодние чудеса:
Вот этот файлик назывался PROLOG.LGO
TO . :TRUEORFALSE
IF LISTP :TRUEORFALSE [PRINT :TRUEORFALSE STOP]
IF :TRUEORFALSE = TRUE [PRINT "YES.] [PRINT "NO.]
END
TO DEFINIOWANA :OBIEKT :CECHA
IF ( FIRST BF BF THING :CECHA ) = "AND [OP AND IS :OBIEKT FIRST BF THING :CECHA IS :OBIEKT FIRST BF BF BF THING :CECHA]
IF ( FIRST BF BF THING :CECHA ) = "OR [OP OR IS :OBIEKT FIRST BF THING :CECHA IS :OBIEKT FIRST BF BF BF THING :CECHA]
IF ( FIRST BF THING :CECHA ) = "NOT [OP NOT IS :OBIEKT FIRST BF BF THING :CECHA]
END
TO DEF :CECHA :LISTA
MAKE :CECHA FPUT "@ :LISTA
END
TO ADD :OBIEKT :CECHA
IF NOT NAMEP :CECHA [MAKE :CECHA []]
IF NOT NAMEP "OBIEKTY [MAKE "OBIEKTY []]
IF NOT MEMBERP :OBIEKT :OBIEKTY [MAKE "OBIEKTY LPUT :OBIEKT :OBIEKTY]
IF MEMBERP :OBIEKT THING :CECHA [STOP]
IF NOT ( FIRST THING :CECHA ) = "@ [MAKE :CECHA LPUT :OBIEKT THING :CECHA]
END
TO DO :N :LISTA
IF :N > COUNT :LISTA [OP :LISTA]
IF :N = COUNT :LISTA [OP :LISTA]
OP DO :N BL :LISTA
END
TO OD :N :LISTA
IF :N > COUNT :LISTA [OP []]
IF :N = 1 [OP :LISTA]
OP OD :N - 1 BF :LISTA
END
TO ELEMENT :N :LISTA
IF :N > COUNT :LISTA [OP []]
IF :N = 1 [OP FIRST :LISTA]
OP ELEMENT :N - 1 BF :LISTA
END
TO WICH :CECHA
IF OR NOT NAMEP "OBIEKTY NOT NAMEP :CECHA [OP []]
OP W :CECHA :OBIEKTY
END
TO IS :OBIEKT :CECHA
IF NOT NAMEP :CECHA [OP FALSE]
IF ( FIRST THING :CECHA ) = "@ [OP DEFINIOWANA :OBIEKT :CECHA]
IF MEMBERP :OBIEKT THING :CECHA [OP TRUE] [OP FALSE]
END
TO W :CECHA :OB
IF EMPTYP :OB [OP []]
IF IS FIRST :OB :CECHA [OP FPUT FIRST :OB W :CECHA BF :OB] [OP W :CECHA BF :OB]
END
MAKE "BRZYTKI [@ NOT LADNY]
MAKE "LADNY [EWA MAGDA ANKA]
MAKE "MADRY [SOBIECH SZYMON KAMIL EWA KUCIAP TIBOR]
MAKE "BRZYDKI [@ NOT LADNY]
MAKE "GLUPI [@ NOT MADRY KOBZA KOBZA]
MAKE "GLUPIBRZYDKI [@ GLUPI AND BRZYDKI]
MAKE "NIEPRZYDATNY [@ GLUPIBRZYDKI OR SZALONY]
MAKE "PRZYDATNY [@ NOT NIEPRZYDATNY]
MAKE "OBIEKTY [SOBIECH SZYMON KAMIL EWA MAGDA ANKA KUCIAP KOBZA TIBOR]
Но в ЛОГО я - не кумекаю ...
zen
Сэр, Вы правы!
Не приблизило!
zen
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot