Pull to refresh

Comments 38

UFO just landed and posted this here
UFO just landed and posted this here
согласно статье
+ 2 * 2 2 == 8
* 2 + 2 2 == 6

очевидно, опечатка?

Скорее закономерный результат неудобной записи

Если я правильно понял идею, то нет.

+ 2 * 2 2 == (2 + 2) * 2 == 8
* 2 + 2 2 == (2 * 2) + 2 == 6

Т. е. приоритетов операций вообще нет, они выполняются в порядке записи.
Если это прямая префиксная запись, то нет:
+2*22 => + (2, ( * (2, 2))) => 2*2 + 2 = 6
*2 +22 => (2+2)*2 = 8
Сначала идет операция, потом два операнда, выполняется через стек (встретили вместо операнда операцию — начинаем выполнять ее).
Чем-то напоминает обратную польскую запись.
2 2 + 2 * => (2+2) * 2
2 2 * 2 + => 2 * 2 + 2
Потому что это префиксная запись — все то же, с точностью до наоборот.
Потому что обратная польская запись — обратная для прямой польской записи?

Вы неверно скобки расставили, а должно быть так


  • 2 2 2 == +(2,(2,2)) == +(2,4) == 8
  • 2 + 2 2 == (2,+(2,2)) == (2,4) == 6
    Что неверно, поэтому в статье действительно должно быть опечатка

Да, вы правы, это опечатка. Большое спасибо! Исправил в статье.

Крутая идея использовать «классы идентификаторов». В целом, если ещё заменить ";" на "!", язык станет совсем похож на GNU Smalltalk :)

По поводу «неудачи» — вы взялись «вручную» тягаться с зарекомендовавшим себя профессиональным инструментом. Не удивительно, что с первого раза не удалось завалить мамонта. Уверен, в этом языке ещё есть места для оптимизаций.

Про байт-код благородный дон, очевидно, не читал?


А что касается ваших проблем, которые привели к необходимости введения типизации — вспомните про каррирование (currying). Или вообще почитайте про такой язык, как forth (тут всё наоборот, используется не прямая польская запись, как у вас, а обратная) — тоже для разбора аргументов функций не требуется знать количество аргументов.

Напомнило Perl, там есть краткая форма описания, а есть полная.
И Perl тоже скриптовый язык, и весьма продуманный. Его изучение может быть полезным для создания таких минималистичных языков.
UFO just landed and posted this here
А результат оказался даже больше.

И вы даже не стали разбраться почему?

Вот-вот. Мне кажется, можно его допилить, и выйдет меньше JS. А может, автор даже слишком развёрнуто написал на Micro? Тогда всё ещё хуже, ведь автор не знает своего собственного языка.
1 — как вам уже неоднократно сказали — почитайте про Форт. Напишите свой интерпретатор (по хорошему и компилятор в байткод). Много моментов подтянете
2 — у вас изначальный код на вашем ассемблере больше места занимает чем жаваскрипт. Напрашивается вывод, что сказывается бедность «стандартной библиотеки», что есть вещи которые в жс занимают мало, а у вас надо расписывать. Без внятного анализа того почему этот ассемблер проиграл языку высокого уровня бенчмарк выглядит неполным.
Это интересная задача для академического проекта: попробовать разработать язык, в котором энтропия будет минимальной.

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

Причём видны пути как для лингвистической оптимизации (более выразительные языковые конструкции), так и для семантической (новые языковые конструкции, позволяющие описывать что-то «неизведанное»), так и для микрооптимизации (например, очевидно, что встроенная поддержка base64 для чисел и значений позволит нам экономить на строках), явно нужно больше локальных неявных переменных, например, с результатами предыдущего вычисления. Больше неявного поведения, которое можно использовать.
например, очевидно, что встроенная поддержка base64 для чисел и значений позволит нам экономить на строках

В идеале base85 или версия с еще большим алфавитом.

Для получения минимальных исходников есть специальные языки из категории Code Golf. Более практично было бы написать транслятор из обычного языка (того же питона) в один из «гольфовых» языков: и разрабатывать удобно, и результат получится сильно меньше.
«Минификация» — это костыль для случая, когда интерпретатору обязательно нужен текст, а мы хотим выкинуть всё что интерпретатору ненужно. Если же язык делаете вы сами, то очевидным образом выкидывается требование текстового представления кода и используется двоичное представление, называемое байткодом. А текст предназчначен, всё же, для людей и должен быть максимально понятным.
А что, если разработать язык, специально рассчитанный на минификацию?

*шепотом* байт-кооооод.
Вы немножко не первый. Человеку нужен велосипед. Это нормально.
Тут ближе Форт по идеологии. Читаемый и сжимаемый, простой.
Это нормально что тут велосипед с треугольными колесами. Ненормально что обрывается на середине. Результат бенчмарка вообще не разобран.
Вы немножко не первый.

И это замечательно.

Тут ближе Форт по идеологии. Читаемый и сжимаемый, простой.

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

Несколько лет назад по работе пришлось писать транслятор нашего скриптового языка в язык стековой виртуальной машины (на основе польской записи, я не знал про Форт — обошел он меня стороной как-то), чтобы ускорить исполнение и уменьшить объем хранимого кода. Реализовал и выражения с разными типами данных, и вызов процедур/функций, и модульную компоновку с поздним связыванием.

Написать статью руки не дошли, да и не уверен, что это интересно.
Ну лично мне любые «системные» велосипеды интересны. Особенно когда «не знал про Форт, обошел стороной» — в таких случаях люди делают много чего кривее чем у всех, но что-то да интересное изобретут по незнанию. Как другим — не знаю.
Нет, по итогам ничего кривого в самой ВМ не получилось. Просто если бы я знал, то изначально говорил о том, что реализую виртуальную машину, частично чем-то похожую на Фортовскую, а не просто «виртуальную машину на основе стека».
Вся имевшаяся кривость системы заключалась в том, что проект изначально не предполагал файлового хранения, это должна была быть on the fly компиляция для ускорения проблемных участков. А вот когда потребовалось сохранять в файл, поскольку это был proof of concept для проверки возможного ускорения скриптов, а не система для реального использования, получилось достичь только ускорения, но не размера. Но лишь потому, что сохранение было достатчоно примитивным, а дальше проект не пошел.
Далеко не всегда байткод отождествляется с минификацией. Есть примеры языков, скромные тексты которых разворачиваются в довольно жирный байткод. За примерами далеко ходить не надо: тот же Python в процессе constant folding может сделать такой unfold выражению
'a' * 100
, что в байткоде окажется константа длинною в сотню букв 'a'.
Это смотря что именно понимать под байт-кодом. Гипотетически, мы можем сделать умножение а на 100 отдельной операцией и уложить ее в одну ячейку.
А как же всеми забытый J который и минификцировать не нужно?
текст сжимается намного лучше бинарного кода

И это легко объяснить: текст даже в однобайтовых кодировках состоит из достаточно маленькой части доступных символов (навскидку, русскоязычный текст состоит из 90-100 различных символов из 256 доступных). Поэтому текстовая запись может быть сжата с сравнительно большим коэффициентом сжатия. А байт-коды, по идее, создаются так, чтобы иметь минимальную избыточность, и потому сжимаются плохо.
А по сути вопроса: писать на скриптовом языке и пытаться на уровне языка это сжать — то ещё извращение. Нечитаемое. Как по мне, лучше всё же разнести: синтаксический сахар для удобства программиста оставить на уровне языка, а сжатие возложить на компилятор, преобразующий нормальный язык в байт-код. Таким образом, и писать удобно, и сжимается всё хорошо.


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

*зануда*
Вы как-то совсем по верхам текст затронули.
У символов есть своя частотность, что позволяет еще снизить разрядность, особенно частотность комбинаций (начиная от комбинаций читаемых символов, и заканчивая большими буквами которые редко бывают в середине слова).
Если мы говорим о программе а не Война и мир, то у нас есть относительно короткий набор слов (включая символьные, не текстовые) самого языка, который является константой, плюс тоже не очень большой словарик идентификаторов и прочих литералов специфичных самой программе. Словарик этот можно уже кодировать алгоритмом Хаффмана, чем еще чуть сократить размер.
У символов есть своя частотность, что позволяет еще снизить разрядность, особенно частотность комбинаций (начиная от комбинаций читаемых символов, и заканчивая большими буквами которые редко бывают в середине слова).


Всё равно есть нижний предел сжатого размера (посмотрите вики избыточность информации), который ни байт-код, ни сжатый текст преодолеть не могут, иначе будет потеря полезной для задачи информации. И сжатый идеальный байт-код к нему близок.
Кстати, этого нельзя сказать про сжатый текст. Все эти большие буквы и идентификаторы — лишние элементы, не несущие полезной для задачи информации. Следовательно, собственная информация в идеальном байт-коде меньше или равна собственной информации в некомпилированном тексте. Следовательно, и предельный сжатый идеальный байткод будет меньше, чем предельный сжатый текст. Осталось только выяснить, насколько избыточен байт-код. Если этот байт-код делается более-менее под подобные задачи, то, полагаю, почти наверное мы не сможем сжать текст и получить размер меньший, чем у сжатого байт-кода. В связи с чем идея сжимать исходник ценой читаемости ЯП вместо сжатия байт-кода мне представляется бесперспективной.
Почитайте про язык программирования Форт, там будет ещё несколько идей для ваших целей.

Я что-т не понял зачем битовые операции если из чисел — только с плавающей точкой

Перед выполнением данных операций числа приводятся к целым, а результат — обратно к числу с плавающей точкой. Аналогичный подход присутствует и в JavaScript.

Sign up to leave a comment.

Articles