Comments 99
Как на счёт Дженериков? Или допустили ту же ошибку, что и авторы Го?
Смотрел, и очень пристально. Потом понял, что мне просто врут. И про управление памятью, и про быстроту компиляции, и про портирование Doom. Ещё в январе я обнаружил, что управление памятью попросту отсутствует — с катастрофическими последствиями. Никакого прогресса или хотя бы внятной реакции разработчиков я с тех пор не наблюдал.
Ну и в конце концов, V претендует на нишу Go и Rust, так что у него нет никаких пересечений с Umka, кроме как в синтаксисе, да и то лишь потому, что и Медведников, и я черпали вдохновение в Go.
По моим убеждениям что новый ЯП всегда должен внести в себе абстракцию которая помогает упросить разработку, а не быть штукатуркой под текущий язык.
Just for fun?
Во первых не статически типизированный, а strong типизированный.
А во вторых, чем вам lua не угодил? Синтаксисом?
This checking can happen statically (at compile time), dynamically (at run time)Так что Umka именно статически типизированный язык, в отличие от Lua. Именно этим Lua мне и не угодил: он откладывает проверку типов до начала исполнения программы.
А чем тогда не угодил python + mypy + обязательное указание типов на уровне pylint?
А во-вторых, Umka всё же претендует скорее на нишу Lua и Wren, нежели Python. В качестве встраиваемого языка Python слишком тяжёл.
Для тех, кто знает питон, думаю выбор очевиден
Ну и затем (как я тоже уже говорил) Umka скорее относится к нише Lua, нежели Python.
Кажется, что вашему языку очень подойдет https://github.com/vnmakarov/mir
Учитывая степень типизированности байткода
LuaJIT… is much faster than all of the other languages benchmarked, including Wren, because Mike Pall is a robot from the future.
А то просто еще один мелкий скриптовый язык, только теперь со статикой.
Кстати, о логах. Удивительно, как люди мирятся с неудобством чтения двоичных логов в языках без статической типизации и классических структур в стиле C. В Umka структуры введены в основном именно ради двоичных логов.
Я как‐то парсил двоичные журналы размером порядка 100—10 000 МБ, используя не сильно оптимизированный код на Python (struct
использовал, но на этом всё). Получил времена исполнения порядка 10 минут на запуск и костыли вида «распарсить журнал, сериализовать результат pickle (чтобы при изменении следующего шага не парсить журнал ещё раз), потом уже что‐то сделать с журналом (со сбросом промежуточных данных на диск, чтобы опять же не повторять шаги)». В итоге плюнул и переписал на так же не особо оптимизированный Rust, время исполнения уменьшилось где‐то на два порядка.
Я, правда, сейчас думаю, что если бы я сначала попытался на Python применить некоторые вещи, которые я использовал с самого начала на Rust*, то, возможно, я выиграл бы порядок и на нём, но вряд ли два. Кроме того, я эти вещи использовал с самого начала, потому что попытка на Rust сделать «как на Python» выглядело бы неестественно. Дополнительно, Rust не позволяет мне забывать обработать варианты enum, а это была частая причина перезапуска, когда я писал на Python.
Я это к чему: имеющаяся типизация в Rust для меня не только сократила количество перезапусков обработчика журналов, но и сделала более оптимальный код более естественным. Я думаю, подобный результат получился бы на любом языке, на котором есть ADT и классические структуры, просто именно Rust был на слуху, и я на нём уже что‐то для пробы писал.
* А именно, не пытаться загнать все журналы в память, чтобы их вместе отсортировать по временной метке, а читать из журналов в правильном порядке, храня в памяти только одну запись из одного журнала и состояние.
Та часть, которая собственно занимается разбором одной записи из одного журнала, в Python и Rust по сути не сильно отличается — придумать какой‐то особенный способ разбора бинарных журналов сложно. Статическая типизация сильно помогала с разбором записей вида «время, тип, данные», где данные зависят от типа — скриптом на LabVIEW я делал из LabVIEW’шного enum Rust’овый enum (до этого — Python’овский), потом Rust не давал мне забыть обработать какой‐то вариант. Данные запихивались в другой enum (который уже ADT, а не просто набор именованных целых чисел) и при создании функции для отладочной печати оного Rust опять не давал мне забыть о том, что в этом enum есть какой‐то вариант, или о том, что этот вариант содержит какое‐то значение.
Ну и плюс в том, что вариант «загнать все данные из всех журналов в один большой список и отсортировать» мне почему‐то показался неестественным. Я не помню точно, о чём именно я думал в то время, но мне либо не пришли в голову варианты реализации на Rust, либо я уже подумывал о таком решении для Python, но решил не заморачиваться, т.к. при использовании CPython в случае отсутствия большого списка я выиграл бы на выделении памяти под него и на его сортировке. А проблемы вида «доступ к любым данным осуществляется только через несколько прыжков по указателям» и «для создания записи нужно выделить память под каждое из полей записи» никуда бы не делись. И эти проблемы в языке с динамической типизацией решить сложно. Возможно, помог бы PyPy с его JIT, но PyPy всё равно не стал бы давать по рукам за забытый вариант enum.
С того времени как он создавался очень уж много в нём чего поменялось. Никаких метатаблиц изначально и близко не было.
И у математиков-то индексация как раз с 1 идет: Wolfram, R, MATLAB, Julia,…
Это только из-за использования массивов как указателей и арифметики с ними. Когда нет указателей к которым можно напрямую привести массивы — 0-индексация не нужна, точнее ничем не лучше и не хуже чем индексация с 1.
Настало время собирать камни отзывы и думать, чем его расширятьЕсли вы захотели делать типобезопасный скриптовый ЯП, то может стоит усилить его и с других сторон? Например: добавить элементы ФП, паттерн-матчинг, метапрограммирование и т.д. Но при этом, чтобы он был прост в освоении, быстр и продуктивен.
map
/filter
/reduce
) в Umka 0.3 всё же появились:import "../import/fnc.um"
fn sqr(x: fnc.Any): fnc.Any {p := ^int(x); return p^ * p^}
fn odd(x: fnc.Any): bool {p := ^int(x); return p^ % 2 == 1}
fn sum(x, y: fnc.Any): fnc.Any {p := ^int(x); q := ^int(y); return p^ + q^}
fn main() {
var data: fnc.AnyArray = [6]fnc.Any{3, 7, 1, -4, 2, 5}
printf("Array = %s\n", repr(data))
result := data.map(sqr).filter(odd).reduce(sum)
printf("Sum of all odd squares = %s\n", repr(result))
}
Для полного счастья не хватает замыканий, но это дело трудоёмкое. Да и так ли они нужны?
Удивительно, как люди мирятся с неудобством чтения двоичных логов в языках без статической типизации
Согласен, в этой задачи без явной типизации результат не очевиден, но немного спасает ctypes
docs.python.org/3/library/ctypes.html#bit-fields-in-structures-and-unions
github.com/cdiggins/cat-language
Медведников, перелогиньтесь.
Ну и в конце концов, V претендует на нишу Go и Rust, так что у него нет никаких пересечений с Umka, кроме как в синтаксисе, да и то лишь потому, что и Медведников, и я черпали вдохновение в Go.
> про быстроту компиляции
time v -o v cmd/v 0.9s
time v -x64 1mil.v 1.2s
> Никакого прогресса
vlib теперь leak free, a в самом компиляторе на 25% меньше. в этом месяце будет 100%.
> про портирование Doom
github.com/vlang/doom/blob/master/p_enemy.v
компилится в p_enemy.o, который можно заменить в си проекте, и всё будет работать
зачем врать?
Про управление памятью: пока локальные массивы выделяются в куче и вообще никак и никогда не освобождаются — я не могу говорить о прогрессе.
Про портирование Doom: насколько я вижу, из всех файлов исходников Doom выбирается ровно один (где 3/4 занимают объявления структур и перечислений), конвертируется из C в V, а затем, при компиляции — из V в C. Этим портирование исчерпывается.
vlib теперь leak free, a в самом компиляторе на 25% меньше. в этом месяце будет 100%.Это глубокая альфа. Про сторонние программы тут ни слова.
if fiberalive(child) { fibercall(child) }
А что произойдёт, если волокно уже померло?
Очень хочется встраиваемый скриптовый язык, который гарантирует что все чистые функции выполнятся в нём абсолютно одинаково на всех машинах.
Пока только пытался начать хотя бы с малого: взял движок Javascript, немного разобрался в его коде, и попытался выпилить оттуда полностью вычисления на float и заменить их на fixed-point. А что дальше потребуется для достижения такой цели, даже пока не представляю.
Не уверен что применений у такого языка найдется очень много, но для deterministic lockstep стратегий очень хорошо зашло бы.
Для меня утрата плавающей точки лишает язык половины его ценности. В моём первом игрушечном компиляторе была фиксированная точка, и я с ней намучился. Фильтр Калмана написать так и не смог (хотя суровые инженеры из 60-х и такое, наверное, могли). Точно ли нужна такая жертва? Нельзя ли и тут просто зафиксировать базовые математические алгоритмы? (Не знаю, фиксирует ли их стандарт IEEE; видимо, нет).
А вот зафиксировать количество бит в целых числах придётся точно.
Отдельное спасибо за двоеточие в определениях типов. Такая вроде бы мелочь, а решительно улучшает читаемость по сравнению с Го.
Существуют и другие (Terra) статически типизированные, встраиваемые, интерпретируемые языки. Возможно кто-то приведёт ещё несколько. Тот же Groovy, можно встраивать в jvm языки.
Кроме вопросов производительности ещё важным вопросом является наличие пакетов для выполнения распространённых задач, таких как работа с базами данных и так далее, иначе использовать его как независимый язык будет проблематично, кроме основной задачи придётся постоянно переизобретать колесо.
Что с системой типов, она так же уныла как в go? Например АДТ есть?
И пожалуй главный вопрос, зачем нужен столь низкоуровневый язык с указателями и размером массивов при инициализации, в то время как уже существует tcc?
Все равно компилятор придется с нуля писать.Компилятор чего? Автор terra уже что-то написал и это что-то работает. Автор umka(нужно ли это склонять?) в любом случае будет писать код для тех же целей.
Основные проблемы у всех новых языков, какими бы они хорошими ни были бы — это:
- Отсутствие библиотек
- Отсутствие тулинга и инфраструктуры
- Миллионы строк legacy на других языках и инертность разработчиков
Конечно, все эти проблемы были есть и будут, кто-то их преодолевает, а кто-то остаётся на задворках индустрии и маргинализуется.
Взять хоть тот же Rust. Имеет огромный потенциал, и его популярность действительно растёт, но язык до сих пор используется гораздо менее широко чем мог бы. Основные разработчики и сообщество вкладывают огромное количество ресурсов в развитие языка, крейтов, экосистемы, инфраструктуры и тулинга и всё равно, количество вакансий на Rust мизерное по сравнению с другими языками.
С golang вышло иначе, изначально довольно спорный язык прочно занял свою нишу и выбить его оттуда теперь сложно. Вероятно, тут сложились несколько факторов: простота языка, массированный пиар со стороны Google и усилия по его продвижению, и изначально довольно качественная стандартная библиотека.

В общем, я сомневаюсь, что в наш век, новый язык общего назначения сможет быстро стать популярным (и вообще когда-то стать популярным), обрастёт экосистемой, сообществом и спонсорами в лице крупных компаний. Но вам, автор, в любом случае успехов, возможности и желания продолжать!
Считаю Python самым красивым языком из всех что видел. Одно только отсутствие {} в телах циклов, процедур и т.д. уже считаю гениальным достижением и движением на встречу людям более художественного склада ума. Решение делать блоки табуляцией — прекрасное. Ну и много других приятностей. Кстати, именно синтаксический сахар пайтона считаю гравной причиной его популярности и как следствие он оброс кучей годных библиотек.
Но я как дизайнер, всегда хотел пойти дальше на пути к синтаксическому раю и давно мечтал о появлении графического языка, который бы выглядел не как текст а как блок схемы, те самые которые мы изучали на уроках информатики. Еще тогда не понимал, почему если так удобно описывать алгоритм блок схемами не сделать это в самом программировании.
И каково же было мое удивление когда я начал изучать игровой движок Unreal Engine и увидел что там реализована моя давняя мечта (Blueprints) и что можно сделать полноценную игру не написав не единой строчки кода! Считаю это большим достижением Епиков и собственно пользуюсь этими плодами, пытаясь создать свою игру.
Так вот, я приветствую разработку новых языков, хорошо когда есть конкуренция, но мое пожелание делать язык проще и красивее предшественников и тогда у него будут большие шансы обойти тот же Пайтон. Извините, если лезу не в свое дело. Понимаю что моя компетенция в среде программистов низкая, но я думаю будет полезен взгляд со стороны! Успехов! :)
Одно только отсутствие {} в телах циклов, процедур и т.д. уже считаю гениальным достижением и движением на встречу людям более художественного склада ума. Решение делать блоки табуляцией — прекрасное.Как и во всяком вопросе вкуса, здесь много и сторонников, и противников. Мне понятна мысль сторонников: если мы всё равно используем отступы, то почему бы не сделать их синтаксически значимыми? Однако мне этот метод не по душе. Во-первых, не всегда такое форматирование выглядит самым читабельным — иногда удобнее написать как-то иначе, а синтаксис не позволяет. Во-вторых, возникает путаница со способом отступов: табуляция или пробелы? Эквивалентен ли один символ табуляции четырём пробелам? А двум? В-третьих, появляется довольно бессмысленный оператор
pass
.Кстати, именно синтаксический сахар пайтона считаю гравной причиной его популярностиЯ думаю, дело в первую очередь в наличии высокоуровневых конструкций, которых нет в C и т. п. — списков, множеств, словарей и прочего. На одном сахаре далеко не уехать.
Но я как дизайнер, всегда хотел пойти дальше на пути к синтаксическому раю и давно мечтал о появлении графического языка, который бы выглядел не как текст а как блок схемы, те самые которые мы изучали на уроках информатики.Таких попыток предпринималось много, но довольно безуспешно. Из относительно живых языков вспоминается только LabView и Simulink. Одно из самых распространённых нареканий к ним — огромная трудность нахождения различий в файлах, а следовательно, и работа систем контроля версий типа Git. Кстати, вы могли заметить, что сейчас наблюдается повсеместный уход от блок-схем к псевдокоду. Не уверен насчёт школьной информатики, но в публикациях эта тенденция очевидна. Может быть, большинству не-художников в принципе легче писать, чем рисовать.
Вменяемый diff сделать в моём понимании не так уж сложно. В простейшем случае вы просто пишете в текстовом файле в абсолютно разные места сортированные по местонахождению список узлов (буквально ID и тип узла), список логических соединений между узлами, список «логических» расположений (актуально для LabVIEW, где есть вещи вида case structure, внутри которых находится что‐то ещё), список «физических» расположений (т.е. координат), остальные метаданные. При правильно выбранных идентификаторах по простому текстовому diff уже можно будет понять, что поменялось. Не‐текстовое представление немного сложнее, но просто две панели с подсветкой вида «этого узла/проводника нет на другой панели» (плюс «внутри этой структуры есть подсветка») должны сойти в большинстве случаев.
Вот сделать слияние так, чтобы результат не выглядел отвратно — это уже будет намного сложнее. Кроме того, мне совершенно не нравится, как на LabVIEW выглядит кодогенерация, или любой вид рефакторинга, который нельзя сделать стандартными средствами (а тот, что таки можно сделать стандартными средствами, ещё потом часто придётся самому облагораживать). Не думаю, что другие графические языки тут будут сильно отличаться.
И все эти проблемы возникают не столько оттого, что в графических языках в принципе нельзя выполнить сравнение/слияние/рефакторинг/кодогенерацию/…, а в том, что, чтобы пользователь мог нормально пользоваться результатом разработчику нужно потратить слишком много усилий. А сами языки ориентированы не на профессиональных программистов, которые такие усилия оценят больше.
Где я написал про «перевод текста обратно в картинки»? У меня в первом абзаце две идеи «как бы я сделал формат графического файла так, чтобы простой diff можно понять» и «как бы я делал diff в графическом интерфейсе». Картинку, описанную в последнем предложении первого абзаца, из diff’а и двух сравниваемых файлов получить можно, но, действительно, зачем? Я такого не писал.
И, кстати, «непрофессионалы» от такой организации представления данных ничего не потеряют, кроме увеличения объёма файлов.
У меня в первом абзаце две идеи «как бы я сделал формат графического файла так, чтобы простой diff можно понять» и «как бы я делал diff в графическом интерфейсе»
Получается, что картинки(на экране) переводятся в текст(исходный код), который обрабатывается diff. Это и есть перевод туда обратно.
И? Я не писал про перевод diff обратно в картинки.
А с тем, что картинки будут переведены во что‐то ещё вы ничего не сделаете. И лучше чтобы «что‐то ещё» было именно текстом, из которого получается более‐менее понятный diff, иначе работать с любыми VCS к интерфейсу которого вы не приляпали свой графический diff (кстати, из графических языков кто‐то так вообще сделал? Я максимум что видел — возможность вызвать этот графический diff из того же tortoisehg.) попросту неудобно.
Кстати, именно синтаксический сахар пайтона считаю гравной причиной его популярности и как следствие он оброс кучей годных библиотек.В плане выразительности его обгоняет perl или lisp. Другое дело в том, что незнакомому с программированием человеку будет очень сложно читать выразительный код, поскольку любую выразительность нужно понимать, а разбираться в коде, когда половина файла непонятна — невозможно.
Но я как дизайнер, всегда хотел пойти дальше на пути к синтаксическому раю и давно мечтал о появлении графического языка, который бы выглядел не как текст а как блок схемы, те самые которые мы изучали на уроках информатики.Когда программисты берутся за дизайн получается не очень, обратное тоже аналогично. До тех пор, пока программы это текст, к ним применимы все те действия, что можно сделать с текстом, вплоть до простого поиска по файлам. Как только программы станут рисовать, очень многие вещи станут невозможными. Плюс ещё тот факт, что то что можно компактно изложить в виде текста просто не влезет в графическом виде

большой код разбивается на функции и макросы (я кстати и в пайтоне все разбиваю на небольшие функции)Далеко не каждое действие можно на что-то разбить, та же сортировка пузырьком это одна функция, и из этого никуда не деться. И потом, у разбиения есть ещё один минус — для того, чтобы что-то прочитать нужно постоянно скакать между разными местами, а то и файлами.
Самое компактное представление кода, это нечто среднее между записью в всего в одну строку, как это можно сделать например в ruby, когда можно соединить filter, map, reduce, так и в lisp, когда открывающая и закрывающая скобка ставиться на строке с кодом. Python обходится без скобок, так что поставить его можно на это место. K&R тратит кучу строк на закрывающие скобки, другие стили тратят место ещё и на открывающие.
Большая часть этого чертежа это либо пустое место, либо провода, самого текста здесь не видно. Я очень сомневаюсь, что даже после рефакторинга это будет так же компактно, как и обычный код.
и кстати поиск в блюпринтах прекрасно работает
Поиск чего? В обычном исходном коде я могу искать хоть через ide, хоть через grep. Если часто нужно искать что-то специфическое, то можно какой-то скрипт написать.
Я очень сомневаюсь, что даже после рефакторинга это будет так же компактно, как и обычный код.Так цель же не сделать компактно, а сделать удобно для не-программиста.
В плане выразительности его обгоняет perl или lispЧем выразительнее ЯП, тем труднее его освоить.
Umka: новый статически типизированный скриптовый язык