Форум программистов, компьютерный форум, киберфорум
Lisp
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
5 / 5 / 0
Регистрация: 15.05.2020
Сообщений: 10
1

Запилил свой Lisp под броузер с OOP и нормальным дебагером

15.05.2020, 17:03. Показов 1039. Ответов 35
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!

Сделал интерпретатор Лиспа на JS со своей IDE (минимальной), дебагером (как в Smalltalk-e), ООП (простым) и другими удобными удобствами.
Сразу скажу: заточен для работы в броузере и на классический Lisp мало похож. Больше похож на JavaScript по логике и операторам.

Собственно репозиторий: https://github.com/SaemonZixel/littlelisp.js

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

Что скажете?
2
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.05.2020, 17:03
Ответы с готовыми решениями:

Создаем свой инет броузер...
Замучился, выбирать.... Ближайший по духу Фаерфокс... Но новые версии всяко неправильно конектcя,...

"OOP.Hospital.Adress" не содержит конструктор, который принимает аргументы "4" E:\OOP\OOP\Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

JEditorPane или как создать свой броузер
Привет. Столкнулся с проблемой.. Короче надо сделать хелп для проги. Но так как нету мастера...

Переделать под Common Lisp
1)Реализовать алгоритм поиска в глубину для решения задачи о кув- шинах с водой. Имеются два...

35
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
15.05.2020, 17:59 2
Saemon Zixel, чтобы оценить язык, приведите примеры кода.
0
Заблокирован
16.05.2020, 00:25 3
Saemon Zixel, это всегда интересно. Но поддержу уважаемого Catstail: хочется, увидеть код в простых примерах.
1
5 / 5 / 0
Регистрация: 15.05.2020
Сообщений: 10
16.05.2020, 23:02  [ТС] 4
Да. Вот наиболее интересные на мой взгляд примеры.

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
;; синтаксический сахар для арифметических и логических операторов (выглядят как в JavaScript).
 
(x < 2)                ;; -> (< x 2)
((x < 2) && (x > -1))  ;; -> (&& (< x 2) (> x -1))
((x < 2) || (x > -1))  ;; -> (|| (< x 2) (> x -1))
(x + 1 2 3)            ;; -> (+ x 1 2 3) => x+1+2+3
(x ++)                 ;; -> (++ x) 
(++ x y z)             ;; -> increments variables x, y, z separately
 
 
;; тело while/if не надо оборачивать в свой список
 
(setq i 0)
(while (i < 10)
    (console.log i)
    (++ i)
)
 
(setq x (window.prompt "Value of X:")) ;; enter any value
(if (x = null)
    (setq x "(none)")
    (alert (+ "x = " x))
:else
    (alert (+ "x = " x))
)
 
 
;; к полям объектов можно обращаться напрямую через точку
 
(alert document.location.href)
 
;; к элементам массивов
 
(setq i 0 list (1 2 3 4 5))
(while (i < list.length)
    (console.log list.@i) ;; @ - разыменовывает
    (++ i)
)
 
;; создание и заполнение JS-объекта
 
(setq obj1 (new Object))
(setq obj1.a 123 obj1.b "abc") ;; можно за один вызов
 
(setq name "c")
(setq obj1.@name ())
(setq obj1.@name.0 111)
(setq obj1.@name.1 222)
(setq obj1.@name.2 333) 
 
(alert (obj1.c.join " ")) ;; show "111 222 333"
 
 
;; классы пока-что сделаны по простому
 
(defclass Трамвай
    :extends Object
    :instvars "из_чего номер"
    :classvars "всего"
    :constructor init
)
 
(setq Трамвай.всего 0)
 
(defmeth Трамвай.init (номер основа) (
    (setq this.номер номер)
    (setq this.из_чего основа)
    (Трамвай.всего ++)
))
 
(defmeth Трамвай.поехали () (
    (window.alert (+ " Трамвай №" this.номер " из " this.из_чего " за вами выехал!"))
))
 
(setq Трамвай1 (new Трамвай 9 "буханки хлеба"))
(Трамвай1.поехали)
(alert (+ "Трамваев всего: " Трамвай.всего))
1
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
17.05.2020, 15:40 5
Гм, инфиксная запись - может, приоритеты ещё? А как отличается вызвов функции < от передачи этой функции в качестве аргумента? Зачем такое усложнение?
0
5 / 5 / 0
Регистрация: 15.05.2020
Сообщений: 10
17.05.2020, 22:04  [ТС] 6
Ну в приоритетах серьёзный нет нужды мне кажется. А && и || вычисляют свои аргументы по мере необходимости.

А что "<" - это функция и её можно передавать в виде параметра?)
Я как-то не думал о таком. Я сделал её как оператор, который прикидываться функцией.

Эти "усложнения" я сделал для удобства людей знающий JavaScript (или другие Си-подобные языки) и плохо знающие Lisp.

Также, огромный минус Lisp-а, на мой взгляд, - это очень много скобочек, очень много скобочек... хотелось бы поменьше)
Вот я постарался убрать часть скобок усложнив немного язык.
0
Заблокирован
18.05.2020, 12:26 7
Saemon Zixel, да, это функция. И префиксная ноиация играет большую роль в концепции языка.
Но все равно вы молодец)

Добавлено через 3 минуты
Saemon Zixel, скобки в Lisp - это не недостаток, а достоинство языка, как ни странно: они чётко разграничивают области видимости, хорошо форматируют код. На Lisp вообще самый красивый код получается. Тем более где-где, а в JS скобок не меньше)
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
18.05.2020, 12:45 8
А ещё круто было бы что-нибудь вместо точек сделать. Свести точки к скобкам. Даже если их сами оставить в виде сахара. Потому что точки в JS часто используются, и в этом лиспе, получается, сосуществуют два способа построения составных конструкций: скобки и точки. Так сказать, к общему знаменателю. А то как макросы писать? Как, кстати, насчёт макросов?
1
5 / 5 / 0
Регистрация: 15.05.2020
Сообщений: 10
18.05.2020, 20:19  [ТС] 9
helter, точки как раз работают также как в JS. T.e. что в JS "document.location.href" выдаст адрес страницы, что в LittleLisp выдаст так-же адрес страницы. И это очень удобно.

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

Макросов нет. Потому, что я не знаю что такое макросы в Lisp-e))

Добавлено через 3 минуты
sodda, ясно)

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

Не уверен, что арифметические/логические операторы я буду делать функциями, чтоб можно было передавать как аргумент или сохранять в переменную. Как-то это сложно мне кажется в плане внутренней реализации. Я даже сейчас не могу представить как это сделать)
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
18.05.2020, 20:41 10
К слову, точки не устарели.

Цитата Сообщение от Saemon Zixel Посмотреть сообщение
T.e. что в JS "document.location.href" выдаст адрес страницы, что в LittleLisp выдаст так-же адрес страницы. И это очень удобно.
Я понимаю, что так же. Но сомневаюсь, что удобно. Рушится единообразие.

Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Макросов нет. Потому, что я не знаю что такое макросы в Lisp-e))
Мне казалось, макросы - главная возможная причина такого проекта. Макросы - это функции, которые порождают код. Куча людей знает JS, зачем им новый синтаксис? Можно было бы сказать: макросами, дескать, вы можете столько кода нагенерить, что любой браузер зависнет. Но в лиспе легко порождать код, потому что сам лисповый код устроен просто. Выражения представляют собой атомы или списки, и голова списка задаёт правило вычисления выражения. Если голова списка - функция, то правило состоит в вычислении остальных элементов и применении к ним функции. Если голова - не функция, то с ней ассоциировано индивидуальное правило вычисления. (И макросы как раз дают возможность программисту создавать такие правила). А у вас сложнее. Во-первых, document.location.href - не атом, так как это выражение явно делится на три части. Получается, у вас два основных способа составления выражений: скобками и точками. Два - сложнее, чем один (только скобками). Ну и правило вычисления усложняется за счёт инфиксности. Видимо, правило вычисления данного выражения определяется не первым элементом выражения, а первым и вторым, если второй имеется. Более сложный код сложнее порождать.

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

Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Я так понял, если при вызове функции аргумент - это список, то он не сразу эволютится, а эволютится внутри функции когда значение аргумента действительно нужно?
Обычно лиспы неленивые, вычисляется всё сразу.

Цитата Сообщение от Saemon Zixel Посмотреть сообщение
в этом и фишка функциональных языков - более 100% производительности?
Скорее это причина тормозов.

Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Не уверен, что арифметические/логические операторы я буду делать функциями
Ого. Насчёт логических - понятно, у них может быть short-circuit evaluation. Но арифметические тоже?
1
Заблокирован
18.05.2020, 23:38 11
Saemon Zixel, есть два подхода. Я не знаю как в CL, но в Scheme значения вычисляются сразу, а не по мере необходимости.
Если передать функции несколько аргументов и один из них будет, например, функция с бесконечной рекурсией, то принимающая функция тоже уйдёт в бесконечную рекурсии, так как она будет пытаться вычислить аргументы и подставить их, но ничего не выйдет.
Не понятно, как в вашем языке будут работать функции вроде apply, reduce и тд, которые принимают в качест аргумента функцию в том числе. Про стой пример вычисления факторипла:


Lisp
1
(defn  fact [num] (apply * (range 1 (inc num))))
Умножение - это функция, которая применяется к списку функцией apply.

Добавлено через 6 минут
Saemon Zixel, по макросы.
Есть такая штука, как гомоиконность: это когда представление данных в реализации языка совпадает с представлением данных на уровне пользователя. Иными словами, если у нас есть вектор [1 2 3], то внутри языка, на более низком уровне, он будет выглядит так же.
Код как данные. Эта одна из причин почему макросы в Lisp такие мощные и в тоже время простые в реализации.
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
19.05.2020, 00:29 12
Не, гомоиконность - это не про представление данных. "hello world" - вот данные, и где тут видна гомоиконность? Гомоиконность - это что сама программа представлена так же, как данные. Лисповая программа состоит из символов, списков - это те же самые символы и списки, которые обрабатываются как данные.
1
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,640
Записей в блоге: 13
19.05.2020, 06:52 13
Мне кажется, что стоит показать ситуации, в которых язык оказывается мощнее, чем его "родители" (JavaSrcipt и Lisp)
0
Заблокирован
19.05.2020, 08:50 14
helter, я это и написал. "hello world" - это строка, а я привёл пример с вектором и сказал, что в пользовательского коде и на уровне языка эти данные будут представлены одинаковоб
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
19.05.2020, 12:27 15
Тогда я ничего не понял. Учитывая, что в CL строка - это вектор.
0
Заблокирован
19.05.2020, 13:28 16
helter, по крайней мере так написано в учебнике по Clojure. Там ещё говор лось, что при парсинге кода не нужны никакие дополнительные конструкции, как в других языках, так как на уровне пользователя, который пишет код, данные представлены точно так же. Ну а же после парсинге уже данные передаются дальше и строка становится вектором символов, вектор становится массивом и тд.

Добавлено через 32 минуты
helter, в общем код, который вы пишете, потом преобразует я в синиаксические деревья и в языках с присутствием гомоиконностьи данные а этих деревья представлены так же, как и в пользовательского коде программиста.
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
19.05.2020, 13:29 17
Не, строки и векторы - это неважно. Представление литеральных объектов неважно. Важно - что сам код состоит из списков. (let ((x 1) (y 2)) (+ x y)) - это список, голова у него - символ let, на втором месте - список ((x 1) (y 2)) и т. п. Однако этот конкретный список имеет смысл с точки зрения программирования на лиспе - он представляет собой выражение, определяющее две локальные переменные и вычисляющее выражение.
0
Заблокирован
19.05.2020, 13:39 18
Saemon Zixel, расскажу, как операторы представлены в Rust.
Там суффиксная нотация, но все же.
Например оператор сложения (+) - это синиаксические сахар для метода add.
Во время компиляции код парсится и на место этого оператора подставляет я вызов метода.

Мы пишем 2+2, а Rust подставляет 2.add(2).
Как сделать операторы вам?
Нужно, наверно, определить функцию, которая будет принимать аргументы и помещать их в динамический массив, потом обходить его с помощью цикла и складывать все значения из массива. Или сразу функции передавать массив, который будет создаваться при парсинге кода. Может быть так.

Добавлено через 2 минуты
helter, я там добавил про синиаксические деревья.
Я сказал про массив, так как это не так очевидно на первый взгляд.
0
5 / 5 / 0
Регистрация: 15.05.2020
Сообщений: 10
19.05.2020, 14:37  [ТС] 19
Цитата Сообщение от helter Посмотреть сообщение
Мне казалось, макросы - главная возможная причина такого проекта.
Главная пречина была - сделать хороший дебаггер как в Smalltalk. Прям в котором можно доводить код до ума без перекомпиляций и перезапусков. Это очень облегчает и ускоряет разработку по моему опыту.

Цитата Сообщение от helter Посмотреть сообщение
document.location.href - не атом, так как это выражение явно делится на три части.
Это как раз один атом. Просто он имеет вот такой вот непривычный вид)
Такое вот сложное имя переменной в данном случае.

Цитата Сообщение от helter Посмотреть сообщение
Обычно лиспы не ленивые, вычисляется всё сразу.
Ну, это радует. Мне тогда можно не делать ленивые вычисления)

&& и || - умеют делать short-circuit evaluation. Без этого как-то неудобно.

Для меня вообще на первом месте было хороший Дебаггер (как я упомянул выше) и максимальное удобство для JavaScript-программиста.
Lisp я взял потому, что синтаксис очень простой (всего 5 правил EBNF). И парсер получился очень простой. Вообще я хотел запилить Smalltalk интерпретатор на JS. Но Lisp тоже весьма неплох оказался. Правда скобок многовато)) А так получился неплохой JavaScript-диалект Lisp-a на мой взгляд.

Арифметические операторы short-circuit evaluation не умеют. Я не представляю зачем им это.

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

Добавлено через 5 минут
Цитата Сообщение от helter Посмотреть сообщение
Макросы - это функции, которые порождают код.
Я плохо понимаю как это. Надо будет заняться изучением этой темы. Посмотреть примеры кода, попробовать самому...
0
4527 / 3521 / 358
Регистрация: 12.03.2013
Сообщений: 6,038
19.05.2020, 14:50 20
Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Правда скобок многовато))
Да ну что вы, много да много. Так ли много мест, где вы экономите на них в JS? Объявления/присваивания, простые арифметические выражения. Всё? Сравните количество скобок:
Lisp
1
2
3
(while (i < 10)
 (console.log i)
 (++ i))
Javascript
1
2
3
4
while (i < 10) {
    console.log(i);
    ++i;
}
Сэкономлена одна пара скобок на ++, при этом добавился пунктуационный мусор в виде двух ;.


Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Посчитал, что не перспективно.
А Рик Хики подумал, что норм.

Добавлено через 5 минут
Цитата Сообщение от Saemon Zixel Посмотреть сообщение
Я плохо понимаю как это. Надо будет заняться изучением этой темы. Посмотреть примеры кода, попробовать самому...
Это само по себе весьма интересно. Правда, некоторое владение лиспом необходимо, чтобы ясно понимать и порождаемый, и порождающий код.
0
19.05.2020, 14:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.05.2020, 14:50
Помогаю со студенческими работами здесь

Спецификации SOAP под Common Lisp
Здравствуйте, существуют ли спецификации SOAP-протокола конкретно под Common Lisp, с учетом его...

Среда разработки на Lisp под DOS
ребят подскажите среду программирования для Lisp под DOS... Добавлено через 2 минуты будет еще...

Программное обеспечение для Windows 7 под Lisp
Подскажите, пожалуйста, программное обеспение для вин 7 для того, чтобы можно было открыть,...

Что-то непонятное с дебагером
Приветствую всех. Я тут что-то не пойму. Программа ни о чём, просто изучаю стек. global _start...

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

stm32f051k8u6 без кварца не обнаруживается дебагером
Вроде бы не обязательно иметь внешний кварц для отладки? Через встроенный будлоадер нормально...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru