Search
Write a publication
Pull to refresh

Comments 64

UFO landed and left these words here

и Python тоже периодически бесит, без слэша никак:

myobj.getSomething()\
    .getOther()


Это скорее вопрос синтаксического анализатора, чем самого факта отказа от точек с запятой.
У меня в языке, например, точка с запятой не является обязательным элементом (фактически она почти всегда игнорируется), а перенос строки влияет только на принадлежность декремента или инкремента, а также на `return`/`throw`/`break`/`continue`
Например, в следующем коде инкремент будет принадлежать к переменной `x` как постфиксный:

val y = x++
f()

Но если перенести инкремент на следующую строку, то он уже будет префиксным и относится к объекту, который будет возвращать функция `f()`:

val y = x
++f()

Отвечая на вопрос "кого же бесила точка с запятой?" никого. Данный элемент в синтаксисе на данный момент является больше "наследием" и излишком прошлого, чем действительно необходимым терминалом.

Но при этом точка с запятой, как мне кажется, обязана присутствовать как необязательный элемент. В качестве примера можно привести случай, когда метод изменяет объект так, что при неизвестном заранее количестве итераций он вернет одно необходимое значение, из-за чего в циклах не будет необходимости прописывать тело:

while (analyzer.boolEat(TokenType.COMMA));

Не знаю, можно ли учитывать все это в генерируемых парсерах, так как не использую их. У меня в профиле присутствует пара статей на тему написания синтаксического анализатора (абстрактная теория и отдельно практика), если интересно

Спасибо, хорошие статьи. Ну а меня раздражает злоупотребление скобочками и ключевыми словами на каждый чих, var и func особенно. В порядке эксперимента даже написал парсер, где мат. выражения типа cos n arccos x вместо cos(n*arccos(x)) распознаются вполне корректно. Для этого пришлось добавить операторы "неявное умножение" с приоритетом выше обычного умножения, умножение с приоритетом ниже сложения/вычитания, и с делением аналогично. Прочих идей тоже хватает, но общей картины миллиард первого самого лучшего ЯП пока ещё не сложилось, и самого главного - нет ещё крутого названия для него)

Вот почему, если вопрос про смысл формулы. А если про парсинг - то из-за расстановки приоритетов, математики часто опускают скобки при записи подобного рода выражений. Для вашего случая надо так и писать - cos n * arccos x.

Мало того, что парсер должен понимать, что есть функция, а что аргумент, чтобы правильно парсить

x y => x*y
sin x => sin(x)

Так ещё и выражения (x y) и (x * y) - разные выражения, хоть и обозначают произведение. Потому что

cos x y => cos(x*y)
cos x * y => cos(x) * y

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

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

UFO landed and left these words here

а вот нафига пробелом заменять умножение?

Если задача - набивать формулы из учебника, типа
2x^2 + 10x = 7
или
sin 2x = 2 sin x cos x
И это прям надо делать много, по 100500 формул каждый день, то каждая звёздочка и скобочка на счету. Логично себе облегчить жизнь и создать DSL под задачу.

UFO landed and left these words here

Конкретно в моих задачах программирование практически полностью состоит из математики.

UFO landed and left these words here

Ну, зарплату мне платят за автоматизацию металлургического производства. C, C#, SQL, HTML/CSS/JS и даже ассемблер иногда. Понимаю, конечно, что настоящее программирование - это жсоны перекладывать и кнопочки на формы лепить. Ну чтош...

UFO landed and left these words here

Ну например, есть сайт с температурами. Для наглядности надо значение каждой температуры в в цветовой градиент перевести. Или непрерывные показания датчика разложить в спектр, что вибрации подшипников отслеживать и аварии предотвращать. Да даже любая, самая банальная статистика по сумме вываленного металлолома в ковш и то математика.

UFO landed and left these words here

Математика в интерполирующей проекции шкалы значений в шкалу тона и последующим преобразованием цветового пространства из HSV в RGB, которую нужно запрограммировать самостоятельно.

UFO landed and left these words here

Необязательно пробелом, можно и без, например 2(1+x)(1-x). В Wolfram Mathematica так уже давно можно, равно как и использовать горизонтальное деление, знаки корня, индексы и прочее. Julia частично тоже.

UFO landed and left these words here

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

UFO landed and left these words here

У меня они обязательны, но удалены там, где они не нужны. то есть, условно, после определения структуры они парсеру вообще не сдались, там нет неодноначности, а вот после операции в коде функции они вполне себе нужны и обязательны.

Вы, возможно, неправильно меня поняли. Так то запяточки в языке есть, но моё упоминание бесящих подразумевало точки с запятыми после классов или структур в С/++.для определения функции в конце ";" не требуется, а для структуры зачем-то надо. это меня и бесило.

UFO landed and left these words here

Косвенно, но я упоминал это в статье. Цель Honey - позволить программисту писать высококачественный код, меньше задумываясь об этом - за него подумает компилятор, ведь правила языка сами по себе способствуют хорошему коду. Хотя я не отрицаю тот факт, что насвинячить можно где угодно и как угодно.

UFO landed and left these words here

Как раз противоположность TMTOWTDI. Конечно, при некоторых условиях Тим Тоуди проявляется, но всё же. Насвинячить можно где угодно и как угодно.

UFO landed and left these words here

Не синоним. На моей практике, которая, возможно, не так разнообразна, как ваша, Тим Тоуди приводит к дестандартизации и захламлению кода.

  1. А что с указателями?

  2. Кроме исследования проблем программистов, Вы рассматривали похожие языки Odin, Hare, etc. ?

  1. Указателей в языке нет. вообще. для библиотек С используются isize либо cffi.voidp типы.

  2. Пытался искать подобные языки, но что-то не ищется. Каждая моя статья заканчивается тем, что я узнаю о существовании как минимум двух языков программирования, забавно.

У меня в моей системе требовалась разработка программ для системы тестирования интеллектуальных приборов. Пришлось разработать свой простой язык для интерпретатора, работающего на компьютере тестовой станции. Так как станций десяток, то программа хранится и корректируется в таблице sql. Линейный алгоритм с поддержкой циклов, косвенной адресацией в циклах и т п. Все крутится в sql.. Это конечно нишевые решения, но мой первый опыт в создании скиптового языка с обработкой на sql.

При стремлении к лаконичному синтаксису и бесящих запяточках странно выглядит двоеточие между именем и типом.
А так - ничего революционного не увидел, очередной недо-с++. Про управление памятью вообще ничего не написано, кроме того, что оно автоматическое. Как реализуется? Сборщик мусора, перемещения/заимствования, счётчики ссылок, возможен ли прямой доступ к памяти?
Мне язык точно не подойдёт - нет шаблонов и метапрограммирования - не люблю повторятся.

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

Независимость кода от среды. Где бы код на Honey не запустился, результат всегда будет ожидаемый.

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

А какие у вас будут заложены возможности для написания кроссплатформенного кода в таком случае? Макросов нет, значит будет что-то вроде атрибутов в Rust? Или как?

На счет исключений. Зачем они нужны? В плане эта магическая штука которая как-то обязательно должна аллоцироваться в куче которая влечет за собой трудоемкий процесс разворачивания функций до try..catch'а которая при этом ни как не диагностируется компилятором ( нельзя же все в исходниках хранить ) те это метаинфа со стороны программиста ( + программист тоже может не знать об этом и в какой-то момент на определенной архитектуре допустим все будет падать хотя для ошибки можно было бы заранее придумать решение ). В таком сценарии даже растовские ошибки выглядят солиднее.

На счет перегрузки операторов. Тоже неоднозначное решение. Это хорошо когда это касается каких-то математических структур это прям сказка а не жизнь, но очень часто операторы перегружают по чем зря. Мне кажется лучше предоставить операции над массивами как в fortran'е или в odin'е ( там микро мануал но много всяких интересных идей посмотрите обязательно ) чисто для математики.

На счет точек с запятыми. На сколько я понял они типо фифти фифти можно ставить можно нет. Я никогда не понимал такого решения. У одного программиста стоят точки с запятой у другого нет. Те непостоянность.

На счет мета программирования зря вы так. Просто это нужно сделать максимально непривлекательным чтобы только тем кому оно было нужно оно было доступно. Хз. Просто очень хорошо иметь какой-нибудь контейнер сразу для всех типов со всеми возможными оптимизациями.

UFO landed and left these words here

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

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

Исключения ( в большинстве случаев простая паника ) и динамическая типизация очень сильно ускоряют прототипирование но языки системного программирования это все-таки больше про надежность и устойчивый код ( по крайней мере мне так кажется )

UFO landed and left these words here

Вы правы. Наверное мне просто не нравится их реализация в c++ ( вся эта неявная динамика в якобы системном языке ). Как концепт это хорошая идея, но нужно наладить механизм отслеживания исключений и либо заставить записывать их в аннотацию либо генерить эту аннотацию внутри компилятора, как-нить сохранять в виде каких-нибудь модулей, и прикрутить к этому lsp чтобы всю эту инфу выводил. Сделать чтобы исключения были видны в compile time'е.

  1. А зачем? Нет, серьёзно, какой практический/прикладной смысл?

  2. Как отследить исключения, если метод вызывает метод интерфейса или абстрактного класса? А если метод, из сторонней библиотеки, которая существует только в виде бинарника? А если метод плаг-ина?

Насколько я осознал

  1. Тот же механизм с ошибками в типах но с дефолтным поведением.

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

  1. Не понял, честно говоря.

  2. Классический пример: скомпилировали с одной версией сторонней библиотеки, на машине пользователя установлена библиотека с секьюрити/хот фиксом, новая версия, список исключений отличается.

  3. Ну и плагины, да - пользователь может написать свою логику и бросить дллку в фолдер приложения. Что приложение может знать об исключениях плагина?

Зачем "просить компилятор"? Знаешь как восстановиться после любого исключения - ловишь все, знаешь, как восстановиться после конкретных - ловишь их, не можешь восстановиться - не ловишь ничего. Чего сложного-то?

  1. Ну типа все тоже самое но тип придумывает компилятор и его записывают в какой-то вспомогательный файл кэша или модуль или что-то вроде этого

  2. Ну если взять сишный хедер старой версии и либо новой все так же может пойти не так. Для решения тут есть два варианта. Хеш какой-нибудь в модуле и либе чтобы проверку делать, или вшить модуль в бинарник.

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

  1. Да при чём тут хедер - скомпилировали с хедером версии 1.1, в рантайме доступна версия 1.2, на уровне сигнатур функций полностью совместимы, а список исключений изменился.

  2. Никто ничего не факапит. Усложним: Программа предоставляет плагину некоторое окружение, в том числе функции/проперти, есть списки исключений. Система скомпилирована, версия 1.1. Третья контора написала под эту версию плагин, плагин свободно продаётся. У пользователя система версии 1.2, плагин скомпилированный под версию 1.1. АПИ бинарно совместимы, список исключений системы версии 1.2 отличается.

    Что скомпилированный плагин может знать об исключениях рантайма новой версии?

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

Я понимаю, компилятор/ИДЕ/анализатор может находить некоторое подмножество возможных исключений и показывать это программисту/помогать обрабатывать.

В этом был бы смысл, если бы было возможно найти ВСЕ везможные исключения метода/функции. Но это невозможно, см. примеры Интерфейса/Абстрактного класса/Рантайма новой версии/Плагина.

Значит либо программисту всё равно придётся лезть в документацию сторонних библиотек/свой код - и даже это не поможет в случае обновления рантайма/сторонних библиотек на исполняющей машине, либо он будет оперировать неполной (==ложной) информацией.
Что в итоге даёт нам одинаковый результат.

Вывод: "нинада". Перефразируя: лови, что можешь исправить и будь, что будет.

Примерно такой у меня ход мысли на этот счёт.

Крч в итоге мы просто говорим про разные реализации.

Зачем "просить компилятор"? Знаешь как восстановиться после любого исключения - ловишь все, знаешь, как восстановиться после конкретных - ловишь их, не можешь восстановиться - не ловишь ничего. Чего сложного-то?

Ну дак, я про то же. Когда программу пишешь ты просишь чтоб компилятор тебе это в машинный код перевел. Я об этом

для этого ничего, кроме документации АПИ не нужно.

Мне кажется мы думаем про разные вещи

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

А я, необразованный, назвал исключением возможность ошибки. Мы буквально запекаем все возможные ошибки в анионе в скрытом типе ошибки котоый выводит сам компилятор. Я имел в виду что программист не видит этот скрытый тип ошибки и пишет код как код основанный на рантайм исключениях ( с разворачиванием стека ) а по факту внутри просто парсится результат функции.

Не хочу занудствовать, но теперь уже реально хочется понять.

Т.е. иными словами, неявно каждый метод, в дополнении к результату возвращает и некий код результата/ошибки, который вывел и назначил компилятор, а каждый вызов оборачивается анализом с передачей результата в продолжение если код Ок, либо переходом в соответствующий обработчик/немедленным возвращением этого же кода вверх по стеку?

Теперь я правильно понял?

Если речь об этом, то концептуально это одно и то же.

И проблема остаётся той же: мы не можем с уверенностью собрать все возможные типы ошибок так, чтобы ко всему прочему оно оставалось верным и во время исполнения. А значит в реальной жизни одним из самых частых кодов ошибки будет что-то вроде АНЭКСПЕКТЕД_РЕТУРН_КОД.

Ну и отдельный большой вопрос - почему нужно делать именно так, чем оно лучше?

Да вы правильно поняли. Это на самом деле почти ничем не отличается, единственное на сколько я понимаю исключения в c++ буквально сохраняют стек и прыгают прямо в обработчик откатывая исполнение, а здесь мы разворачиваем каждую функцию через результат и пробрасываем вверх просто неявно.

Каждая функция будет наследовать тип ошибки при необходимости дополняя этот тип. Те например функция A возвращает сгеннрированную компилятором ошибку A_exception функция B соотвественно B_exception функция C вызывает эти функции и не обрабатывает эти ошибки. Компилятор определит что функция C никак не хендлит ошибки, и сделает тип ошибки конкретно для функции C который будет показывать это ошибка A или B и аллоцировать на стеке достаточно места для них обоих. Те для каждой функции мы будем отслеживать все ошибки, просто на стороне компилятора а не пользователя.

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

Я кажись понял что вы имели ввиду. Абстрактные методы же не описываются пользователем, те да. Я дурак. Ну для этого можно придумать воркэраунд ввиде пользовательских ошибок. Я потратил очень много вашего времени, прошу прощения

UFO landed and left these words here
UFO landed and left these words here

Пропустил слово: одним из самых частых ОБРАБАТЫВАЕМЫХ кодов ошибки будет что-то вроде АНЭКСПЕКТЕД_РЕТУРН_КОД.

Имелось ввиду "любой".

Не, любопытно было чем этот подход кажется лучше исключений. В сравнении с го [мне] понятно в чём смысл.

UFO landed and left these words here

Собственно, к чему я и вёл.

Sign up to leave a comment.

Articles