Pull to refresh
29
0

Пользователь

Send message

Лично мне стало как то легче - меньше шума.

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

В VS был интерфейс 2010х годов, и теперь, судя по скринам они добрались до 2015

Райдер, на пару с Intelij прям в 2020 впрыгнули, по той же, абсолютно объективной моей оценке

Есть мнение что все строго наоборот.

Проекты - десктопные. Так же есть опыт embedded кода и там и там.

В линуксе/макоси, пожалуй лучше чем на винде (ибо консоль нормальная). Крутили C# код на контроллерах с 2017, кажется года - полет оказался прекрасный

Так как я работаю и там и сям одинаковое кол-во времени, и занимаюсь отчасти их тулингом, то могу позволить их сравнить.

Про котлин отдельный разговор. Пока речь про java.

Value types не поддержаны в Jvm - соответственно постоянные мемори трафик и oom, и соответственно перфоманс. Это точно неспорое утверждение - Jvm действительно медленная в большинстве сценариев. CLR же может быть очень быстрой. Вы можете посмотреть ежегодные отчеты по ускорению CLR, но боже, как мы ждем хоть один такой отчет про JVM.

Про идейку: Очевидно, что если сравнивать с идеей то это Rider/Resharper. Это все теже фишки идеи но с много более сильным набором quickfix, typing assists tooling итд. Помимо этого SWEA, unit testing и профайлинг абсолютно другого уровня. Но тут более важна первопричина - в C# есть внутренняя конкуренция VisualStudio vs Rider. И это действительно ровная по фанатам конкуренция (в отличите от java мира) где бой идет не на жизнь а на смерть

Скорость компиляции - в C# вообще никто не знает про скорость компиляции, так как все уверены что она близка к нулю. Серьезно - это сделано очень быстро. Вообщем из пруфов - у меня постоянно открыто пара проектов на java и C#. Когда у меня рябилд java - я ухожу за кофе.

По итогу разница есть, и она велика.

Про котлин: Если бы он был бы на CLR это был бы лучший язык в мире (или один из лучших), но по факту у него:

  • слабоконтролируемый перфоманс

  • плохая поддержка со стороны IDE (очень низкая скорость completion, низкая скорость даже банальной подсветки синтаксиса на большом проекте, кривые typing assists, да даже гаттер марки саспенд функций приехать могут через 15 секунд после открытия)

  • постоянные kotlin compiler error

  • ужасный опыт отладки suspend функций

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

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

Откуда это все взялось - как обычно, из за того, что .net был догоняющим. Он посмотрел на java и сразу начал добавлять сахара. Изначально добавил Value type, затем, когда он выходил на линукс он был полностью переписан. Ну и конкуренция JetBrains vs Microsoft очень много добавляет.

value types, async await, общая производительность, еще раз общая производительность, ide тулинг, скорость компиляции, простота архитектуры базовых фреймворков, тулинг (cli, nuget etc) . а если сравнивать c# с явкой - то это просто лет 10 разрыва между ними

Но тогда и цель жизни - поесть. Ведь если ты не поешь - то умрешь

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

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

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

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

Если быть еще точнее, есть одна

Можно бахнуть отдельный парсер (создать отдельный диалект), например в синтаксисе gherkin если это имеет смысл. Тут нужно изучать, но это любопытно

Соглашусь про подсветку синтаксиса. Для этого достаточно подсветить ключеве слова, операторы и паттерны видаy=... и  f(...,а вот про валидатор интереснее - что именно вы имеете ввиду под этим?

Конкуренты

https://github.com/sklose/NCalc2

https://github.com/codingseb/ExpressionEvaluator

Language server

Не реализован. language server это слишком крутая задача, что бы сделать ее в стол.

Но вероятно стоит накидать подсветку синатксиса, ибо для этого достаточно подсветить ключеве слова, операторы и паттерны видаy=... и f(.... Это кажется разумным реквестом

Настраиваемость фич

Пример

Настраиваются:

  • Запрет if

  • Тип целых чисел по умочанию

  • decimal или float арифметика

  • integer overflow

  • Запрет пользовательских функций

  • Запрет рекурсивных функций

  • Список функций

  • Список констант

Вероятно можно ввести множество других флагов типа

  • запрет функций высших порядков

  • запрет списков

  • запрет строк /интерполяции строк

Тут нужны примеры использования что бы понять что именно и где запрещать/расширять ибо здесь у меня нету строгого ощущения что нужно людям

Ошибки

Я постарался разобрать как можно большее кол-во ошибок, с понятным объяснением "что не так".

Разобрано около 140 различных возможных ошибок

Пример: https://github.com/tmteam/NFun/blob/master/src/NFun/ParseErrors/Errors.3.Syntax.cs

Полный список ошибок : https://github.com/tmteam/NFun/tree/master/src/NFun/ParseErrors

Благодарю за комментарий и вопросы. Многое из того что вы спросили я хотел добавить или сознательно убрал из статьи, что бы не раздувать ее. Потому развернуто отвечу здесь:

Python, JavaScript

Python, JavaScript - рассматривали. Более того - изначально на проекте был именно IronPython. На нем столкнулись с проблемами:

  • Вопросы про песочницу

  • Огромные проблемы вызванные слабой типизацией. Люди писали скрипты которые по просту ломались на объектах

  • Скорость исполнения (в сценариях где было много перезапуском сложных скриптов)

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

  • Плохой inter-op. Из за этого скрипт Python был намного более грамоздкий. Например мы не могли понять какая переменная только для чтения, а какая только для записи

  • Так же мы не могли понять какой тип может быть у переменной что опять таки приводило к ошибкам в рантайме. Еще мы не могли оценить скорость выполнения - и любой while true: мог поставить колом или просадить перфоманс в критически важной части

  • Все вышесказанное еще более справедливо для JavaScript

Скорость и прекомпиляция

Я изучал возможности использования C# и F# с прекомпиляцией. Анализ нашей и схожих проблем показал что самым критичным является именно скорость первичной компиляции или one-time-shot(build+run+get results) perfomance:

Примеры:

  • Cкорость запуска промшленного оборудования (чье железо было очень слабым)

  • На запросе вытащить сущность из бд и выполнить связанный с ней скрипт. Тут не покешируешь:(

  • Сложность интеграции и поддержки такого пакета

.Net interactive

.Net interactive - не смотрел. По результатам поверхностный осмотра - все же это разные звери для разных задач:

  • Есть вопросы про песочницу

  • Есть вопросы про скорость исполнения one-time-shot

  • JavaScript - слаботипизирован. См. ниже про python/javascript ниже

  • F# syntax - не уверен что подходит для начинающих

Но похоже нужно смотреть для кругозора

Rule-syntax для anonymous-hi-order-functions

Это очень интересный вопрос, с многими часами размышлений и различными прототипами. Отвечу на него развернуто.

Корневая проблема

На практике оказалось (сюрприз-сюрприз) что для не-программистов hi-order function это чудовищно сложная абстракция. Как 0 для древних людей. Люди боялись ее, и всячески избегали (не смотря на кажущуюся для нас с вами очевидность).

Почему не classic way. a->b syntax

Начиналось все с классического синтаксиса a->b, но в реальности это привело к тому, что ребята попросту отказались пользовать Nfun увидев стрелки. Это когнитивно пугающий синтаксис и они готовы были писать огромные скрипты python просто испугавшись, как они выразились "высшей математики на ровном месте". Если описывать эмоционально, то кажется что пользователи начали бояться заодно и обычной арифметики в nfun ибо бог знает что за этим скрывается, и бог знает на каком шаге придется открывать учебник высшей математики. То есть сам факт наличия оператора стрелки в выражении превращал "тупо выражение" в "шайтан заклинание"

Хотя поиграться со стрелками и всеми примерами вида

y = a->b->c->a+b+c

было очень приятно. Было очень больно выкорчевывать этот синтаксис, когда он уже был разобран и работал.

Почему не kotlin-way. map {it*it} syntax

Альтернативой был синтаксис котлина, с хвостовыми лямдами вида

map{ it*it }

Этот синтаксис не вызывал вопросов у людей, но встал вопрос о консистентности.

Например назревал конфликт с синтаксисом анонимных структур

a={age=42, name ='vasa'}.

Анонимные структуры для nfun намного важнее лямбд, потому им отдается приоритет. С другой стороны введение блока {} логично для многострочных выражений и так же требует использовать {} для всех блоков кода ради консистентности, а это сразу уход в сторону C-Like языков, чего мне хотелось избежать (так как, опять таки, это разумно для более сложного и профессионального применения, а для бытового языка - может напугать.

Был еще вариант синтаксиса map @{it*it}но тут вставал вопрос консистентности - ибо "откуда тут @ ?"

Почему не python-way. x for y syntax

Другой альтернативой был путь питона, с его x for y оператором. Однако этот оператор решает только небольшое кол-во задач с массивами, да и сам по себе. достаточно своеобразен.

В отсутствии циклов, многострочных statements и изменяемых переменных - ограниченность этого подхода становится критичной. Нужно либо делать из nfun полноценный Яп (что конечно круто, но не понятны трудозатраты/сферы применения) либо придумывать новые синтаксисы для различных linq - задач (встраивать Sql/ C#linq?) что очень усложняет nfun. Все же хочется использовать единый подход для большого скоупа задач

Почему rule

Нужно было найти понятную абстракцию для функций высших порядков. Так и появился rule.

Теперь можно объяснить этот синтаксис примерно так:

# rule - это правило применяемое к каждому элементу в списке. 
# с его помощью, например, мы можем взять только те элементы списка, 
# которые удовлетворяют заданному правилу
           
[1,2,3,4,5].filter(rule it>3) #[4,5]

# в примере выше, мы взяли только те элементы которые больше 3.
# внутри правила, 'it' - это элемент для которого применяется правило
            

Вероятно можно сформулировать это лучшим образом, но думаю идея ясна

Помимо этого начала наклевываться другая консистентность Nfun - после rule следует выражение, и этому выражению не нужны скобки, так как в любом месте nfun мы знаем границы выражения.

В теории, строка

x = rule it-1 y = x(1)

может быть разобрана (но в nfun есть чисто косметический запрет, требующий перенос строки или ; между выражениями), при этом синтаксис аналогичен тому как мы моглибы написать

... else x-1 y = x(1)

То есть мы не вводим нового синтаксиса, а используем старые паттерны. Это сразу наводит на мысль что нужно делать try-catch syntax и так далее. Впрочем консистентность синтаксиса - слишком тонкая и спорная материя, но надеюсь я передал свое "видение"

Почему ключевое слово rule а не fun

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

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

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

f(x) = x**2 - 2*x + 3

result = f(12)

Впрочем эти решения могут быть переиграны, если нужно будет делать из Nfun полноценный ЯП

Крипово или нестандартно?

Я полагаю что в данном случае нестандартно == крипово только для опытного программиста, ибо требует некоторого когнитивного напряга, ведь привычная нам метафора/синтаксис не используется, а вместо него что то незнакомое

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

Что можно переделать

Я мог и могу переделать любой нюанс синтаксиса сделав альтернативный синтаксический "диалект" . Это относительно не сложно - но на данный момент я не уверен что я могу сделать синтаксис лучше в рамках оригинальной задачи. Нужны идеи синтаксиса/семантики и примеры использования. Если таковые есть - я действительно с радостью их выслушаю, так как за время работы, над таким, относительно маленьким синтаксисом я немного влюбился в задачу синтаксисов.

Сегодня как раз на стриме будем обсуждать.

Проверяли на практике (проэктанты Scada-системы Sonica). Там был питон/С# и Nfun. 

По итогу - проектанты:

  • При касании C# - сразу говорили "Нет, мы это делать не будем, лучше на костылях".

  • На питоне плакали кололись и допускали очень много ошибок.

  • На Nfun спокойно пишут, ошибок не допускают (но лямбды не используют).

Более того - многое из синтаксиса Nfun строилось именно по реакция проэктантов. Наверняка можно было сделать лучше, я сделал лучшее что мог. Вы можете предложить синтаксис - и можно его впилить в NFun. И это не троллинг, это действительное предложение. Накидать парсер для синтаксиса не есть сложно.

А по факту - действительно "идеального" решения пока нет. Но сложность например SQL дается большинству. Python уже сложнее. C# это ппц для обычных ребят. Но так как мы идем в мир где минимальное знание ЯП становится таким же естественным как умение решать простые уравнения - то это вселяет в меня оптимизм

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

  • Запись выражений в скада системах и или лоукод решениях (смотрите скриншоты в статье)

  • Хранение выражений вместо констант в конфигах (пример с Settings.json в статье). Можно сказать что это сериализация лямбд.

  • Web UI - например фильтры запросов, правила начисления бонусов и так далее (скриншоты в статье)

  • Тонкая настройка фильтров изображений

  • Верстка, в том числе email. Например если раньше вы писали

Дорого пользователь. Ваш баланс низкий и скоро мы вас заболим

то теперь можно писать:

{if (user.gender==m} 'Дорогой' else 'Дорогая'} {user.name}. Ваш баланс равен {user.balance} $ и скоро мы вас заблочим

Раньше для такого нужно было напрягать программистов. Теперь это можно писать просто в вашей CRM

Это примеры которые были в практике или сходу пришли мне в голову.

Примеры:

Это действительно не сложно - но у этих слов сейчас различные оттенки:

  • Исследования - это что то связаное с формальной наукой. "Делал дома исследования" - звучит кустарно

  • Изучение - это больше про учебу и не смотрится в оригинальном тексте

  • Инвестигации - это именно кустарное, айтишное исследование

А так как слово "Инвестигация" - прекрасно склоняется и встраивается в язык - не вижу проблем. Мы же не боимся слова "инфа" или "комп" чьи корени так же заимствованы.

Процесс обогащения языка заимствованными корнями, при условии склоняемости слов - это не плохо. Даже хорошо

C# и F# не подходят для этих задач:

  1. Пользователям (бугалтерам, редакторам, пусконаладчикам, проектантам) очень сложно (а скорее невозможно) писать код с явной типизацией (пускай даже простой)

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

    Сравните с точки зрения не программиста эти две клинописи:

var i = new[]{1,2,3}.Select(a=>Math.Pow(a,2));
var b = new User(){ Age = 18, Name = "Kate"};
var c = i.First() >0 ? "positive" : "negative";

и

i = [1,2,3].map(rule it**2)
b = {age = 18, name = 'Kate'}
с = if(i[0]>0) 'positive' else 'negative'

  1. Скорость компиляции у C#/F# - отстой. Это критично как для embedded -сценариев,так и для одиночного запуска

  2. Кол-во звездочек у пакета Ncalc

  1. Потому что я могу написать свой мини-ЯП !

Чудовищные риски и уменьшающийся рынок. Ужасная ситуация

Гуглоперевод:

Зима приближается

Information

Rating
Does not participate
Registered
Activity