Как я устал от JavaScript и создал свой собственный язык программирования

    За свою карьеру я успел поработать со множеством языков программирования. Писал flash-игры на ActionScript 3 и Android-игры на Java, сервера на Java, Scala и NodeJS (JavaScript), скрипты на Python, веб и мобильные приложения на React (JavaScript). И на каком бы языке я ни писал, меня не покидало ощущение, что синтаксис этого языка слишком многословен, полон излишеств, шума и синтаксического бойлерплейта, мешающего пониманию написанного кода.

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

    • Человекочитаемость - идеальный язык должен быть читабельным и легким для понимания человеком

    • Лаконичность - код на идеальном языке программирования должен содержать как можно больше смысла на квадратный сантиметр экрана. Максимум семантики, минимум синтаксиса.

    • Внутренняя непротиворечивость - синтаксические конструкции языка должны быть внутренне согласованы и хорошо сочетаемы

    • Чистота и красота - язык должен выглядеть максимально чисто и эстетически красиво

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

    Единственным параметром, которому не до конца соответствовал Lisp, был параметр чистоты и красоты. Уходящие за горизонт заборы из скобочек не нравились мне с точки зрения эстетики. И я нашел решение: чтобы уменьшить количество скобочек можно сделать значимой индентацию, как это сделано в Python.

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

    Как я перестал бояться и полюбил JavaScript

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

    Незадолго до знакомства с JavaScript моим основным рабочим языком была Scala. Вот он-то мне казался по-настоящему крутым, ибо он был полон сверхсложной эквилибристки типов и даже для написания простейшего http-сервера на Scala требовался высший пилотаж.

    Поэтому когда я открыл для себя NodeJS, я сначала не поверил, что можно писать так просто и лаконично. И чем дольше я знакомился с JavaScript, тем более гениально спроектированным и внутренне согласованным он мне казался. Система объектов и прототипов позволяет легко писать код в объектно-ориентированном стиле, а то, что в основе всего этого лежит функция, делает легким и приятным программирование в привычном мне функциональном стиле. А динамическая природа языка делает его фантастически гибким.

    Кроме того в экосистеме JavaScript меня поразило обилие инструментов и хороших библиотек. В Scala в порядке вещей была ситуация, когда библиотека была написана для работы над PhD и заброшена после защиты диссертации. В Java библиотеки были в основном рабочими, но многие из них были абсолютно не дружелюбными - лежали не пойми где, не имели документации в нормальном виде, имели ужасный API и так далее. У каждого языка была своя ужасающая система сборки и управления зависимостями вроде maven, gradle или sbt.

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

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

    Но есть ли у JS какие-нибудь минусы?

    Что не так с JavaScript

    Я программирую на JavaScript, в основном, в чисто функциональном стиле. Я использую const, не мутирую объекты и массивы, использую чистые функции. Так что мой код выглядит примерно так:

    const incrementNumbers = numbers => numbers.map(number => number + 1)
    const takeNumbersGreaterThan = threshold => numbers => numbers.filter(number => number > threshold)
    
    const func = (numbers, threshold) => {
        const incrementedNumbers = incrementNumbers(numbers)
        const filteredNumbers = takeNumbersGreaterThan(threshold)(incrementedNumbers)
        return filteredNumbers
    }

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

    Собственно, именно эти недостатки и натолкнули меня на возвращение к проекту собственного языка программирования. Ну а из-за описанных мною ранее громадных преимуществ экосистемы именно JavaScript я сделал платформой для своего языка.

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

    Порядок выполнения операций

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

    Поэтому в моем языке выражение:

    a (b c) (d e)

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

    a
      b c
      d e

    Ну а выражение:

    a (b (c d))

    может быть записано так:

    a
      b (c d)

    или так:

    a
      b
        c d

    Присваивание

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

    В Una константа объявляется так:

    = name "John"
    = number 1

    Если мы хотим присвоить константе значение вычислений, то делаем так:

    = z (calculate x y)

    а можно обойтись и без скобок, этот оператор позволяет сделать так:

    = z calculate x y

    или так

    = z calclulate
      x
      y

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

    Арифметика, сравнения и логика

    В Una вы можете пользоваться стандартными JavaScript операторами арифметики, сравнения и логики.

    Арифметические операции выглядят так:

    = a (+ 1 2)
    = b (- 2 1)
    = c (* 3 2)
    = d (/ 4 2)
    = e (% 5 2)

    Все из них могут принимать множество параметров. Например:

    = sum (+ 1 2 3 4 5)

    А минус может принимать и один параметр, что является отрицанием числа:

    = a (- 1)
    = b -1

    Вот пример сложных арифметических расчетов:

    = a +
      * 2 4
      / 9 3
      + (* 3 2) (/ 4 2)
      *
        + 1 2
        / 6 3

    Конечно также вы можете использовать любые функции из стандартной библиотеки JS:

    = randomNumber Math.random ()

    Операторы сравнения имеют некоторые отличия от JavaScript. Давайте посмотрим:

    = a (== 1 1)
    = b (~= 1 '1')
    = c (!= 1 '1')
    = d (!~= 1 '2')
    = e (> 2 1)
    = f (>= 2 1)
    = g (< 1 2)
    = h (<= 1 2)

    Оператор == и != - это точное по типу сравнение, аналог === и !== в JavaScript. Для неточного по типу сравнения нужно применять ~= и !~=.

    Логические операторы тоже немного отличаются:

    = a (& true false)
    = b (| true false)
    = c (! true)
    = d !c

    Как вы видите, вместо && используется &, а вместо || используется |.

    Условные операторы

    Тернарный условный оператор работает также как и в JavaScript:

    = message
      ? (> 2 1) "Greater" "Less"

    А еще существует условный оператор с возвращением значения:

    ?! (== number 1) "One"

    Он используется в функцях и других вычислимых блоках, чтобы вернуть значение по условию и соответствует следующему коду на JavaScript:

    if (number === 1) return "One"

    Коллекции

    В Una есть две базовые коллекции: массивы и объекты.

    Массив задается следующим образом:

    = numbers :: 1 2 3 4 5

    А объект задается так:

    = user :
      name 'John'
      age 13
      passport :
        id 1
        country 'USA'

    В Una работают все трюки JavaScript.

    Можно задать элемент массива или поле объекта готовой константой:

    = a 1
    = numbers :: a 2 3
    
    = name 'John'
    = user :
      name
      age 13

    Работает троеточие:

    = threeNumbers :: 1 2 3
    = fiveNumbers :: ...threeNumbers 45
    
    = userFields :
      name 'John'
      age 13
    = user :
      id 1
      gender 'm'
      isAlive true
      ...userFields

    Работает деконструкция:

    = numbers :: 1 2 3
    = (:: one two three) numbers
    console.log one
    
    = user : (name 'John') (age 12)
    = (: name) user
    console.log name

    А чтобы взять определенный элемент массива или значение определенного поля объекта используется точка:

    = list :: 1 2 3
    = object : (a 1) (b 2)
    
    console.log (. list 0)
    console.log (. object 'a')

    Также точка может быть использована, чтобы взять конкретное поле объекта таким образом:

    = object : (a 1)
    console.log (.a object)

    Этот синтаксис удобен для вызова функций, лежащих внутри объекта.

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

    Стрелочная симметрия синхронных вычислений

    Правая стрелка симметрии синхронных вычислений является функцией:

    = sum -> (x y)
      + x y
    
    = onePlusTwo -> ()
      = one 1
      = two 2
      + one two

    Последняя строчка функции всегда является возвращаемым значением. Данный код на JavaScript будет выглядить так:

    const sum = (x, y) => x + y
    const onePlusTwo = () => {
      const one = 1
      const two = 2
      return one + two
    }

    Для преждевременного прерывания выполнения функции можно использовать вышеупомянутый условный оператор:

    = isSumGreaterThanFiveIfXisNotZero -> (x y)
      ?! (== x 0) "X is zero"
      = sum (+ x y)
      ? (> sum 5)
        "Greater"
        "Less"

    Левая стрелка симметрии синхронных вычислений является мнгновенно выполняемым блоком кода, также называемым Immediately Invoked Function Expression:

    = result <-
      = a 1
      = b 2
      + a b

    Этот оператор можно использовать для чего-то вроде задания константы значением по каким-то условиям:

    = result <-
      ?! (== value 0) "Zero"
      ?! (== value 1) "One"
      ? (< value 10) "Less than ten" "More than ten"

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

    = func -> number
      ? (== number 0)
        <-
          console.log "Number is zero!"
      + number 1

    Стрелочная симметрия асинхронных вычислений

    Правой стрелкой симметрии асинхронных вычислений является асинхронная функция:

    = getUserPosts --> user
      database.loadPosts user.postIds

    Левой стрелкой симметрии асинхронных вычислений является await:

    = checkIfUserIsAdmin --> userId
      = user <-- (database.loadUser userId)
      == user.role 'admin'

    Стрелочная симметрия модулей

    Правой стрелкой модульной симметрии является импорт:

    =-> './index.css'
    =-> 'react' React
    =-> './validation' (: validateEmail)

    Он превращается в import или в require в зависимости от соответствующей настройки компилятора.

    Левой стрелкой модульной симметрии является экспорт.

    Дефолтный - export default в JavaScript:

    <-= a

    Экспорт отдельной константы export const в JavaScript:

    <-= = a 1

    Экспорт нескольких констант - export {a, b} в JavaScript:

    <-= ()
      a
      b

    Вы можете импортировать любые JavaScript-модули в Una, и любые Una-модули в JavaScript. Все модули полностью совместимы друг с другом.

    Стрелочная симметрия ошибок

    Правой стрелкой симметрии ошибок является try-catch:

    |->
      <-
        = getName null
        getName ()
      -> error
        console.log error
        'John'

    В отличие от JavaScript в Una этот оператор является выражением, всегда возвращающим значение, а также этот оператор не имеет блока finally.

    Если нужно исполнить асинхронный код, то соответствующие стрелки симметрии заменяются на асинхронные:

    |->
      <--
        getNameAsync ()
      --> error
        console.log error
        "John"

    Левой стрелкой симметрии ошибок является выброс ошибки:

    = addOneToNumber -> number
      ?! (isNaN number)
        <-| "number is not valid"
      + number 1

    Стрелочная симметрия чейнинга

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

    =-> 'ramda' R
    = electronics ::
      :
        title ' iPhone '
        type 'phone'
    
    = phones |>
      electronics
      R.find
        R.propEq 'type' 'phone'
      R.prop 'title'
      R.toUpper
      R.trim

    Левая стрелка симметрии чейнинга подставляет выражение как первый параметр следующей за ним функции. Это удобно для работу со стандартными методами массивов и lodash:

    = sum <| (:: 1 2 3)
      .map (-> x (+ x 1))
      .filter (-> x (> x 2))
      .reduce (-> (x y) (+ x y)) 0

    Без чейнинга это выражение выглядело бы уродски:

    = sum .reduce
      .filter
        .map (:: 1 2 3) (-> x (+ x 1))
        -> x (> x 2)
      -> (x y) (+ x y)
      0

    Интерполяция строк

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

    = name 'John'
    = count 5
    = fruit 'apples'
    
    = text `
      'Hello, ${0}' name
      'I have ${0} ${1}'
        count
        fruit
    
    console.log text

    Этот пример выведет:

    Hello, John
    I have 5 apples

    Так же вы можете провести интерполяцию строк по какой-либо функции - чтобы сделать это пришлите функцию первым параметром. Это очень часто используется например в styled-components:

    = color 'red'
    = Container `
      styled.div
      'background-color: ${0};' color

    React и React Native

    Для написания веб-приложения на React или мобильного приложения на React Native вы не сможете использовать JSX. Вместо этого вы можете использовать функцию createElement, лежащую в основе React.

    =-> './index.css'
    =-> 'react' React
    =-> 'react-dom' ReactDOM
    =-> './styles' S
    
    = (: (createElement e)) React
    
    = App -> ((: name))
      = (:: count setCount) (React.useState 0)
      e S.Container :
        e S.Hello (: (color 'green')) 'Hello, '
        e S.Name : name
        e S.IncrementCount
          : (onClick (-> () (setCount (+ count 1))))
          'Press me'
        e S.Count : count
    
    ReactDOM.render
      e App (: (name 'John'))
      document.getElementById 'root'

    Первым аргументом функция всегда принимает компонент, вторым объект с параметрами (для пустого объекта в Una вы можете использовать : ), а все последующие параметры - это chilldren.

    Что еще предстоит сделать

    Язык еще не закончен, многое еще предстоит. В скором будущем я постараюсь сделать:

    • регулярные выражения

    • возможность заинстансить класс (оператор new)

    • комментарии в коде

    • плагин для Visual Studio Code с подсветкой синтаксиса

    • и многое другое...

    Заключение

    Язык Una устанавливается в любой JavaScript-проект простейшим babel-плагином, который компилирует все файлы с расширением .una в JavaScript. Вы можете найти инструкции по установке, подробную документацию и примеры в моем репозитории на гитхабе. Я буду жутко рад, если вы поиграетесь с языком, протестируете его и дадите фидбек, что можно было бы улучшить, а что стоит починить. Ну и от звездочек конечно не откажусь.

    Спасибо за внимание!

    Комментарии 115

      +9

      Еще чуть-чуть и будет CoffeeScript.
      В функциональных языках в принципе нет понятия "присвоения".
      От JS усталости помогает https://elm-lang.org/

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

        А Elm конечно шикарный и очень похож на Una. Отличие в том, что у Elm собственная стандартная библиотека, коллекции и синтаксис, а Una все же плотно интегрирована в JavaScript.
        –1

        Идея хороша. Запомню как концепцию для DSL.

          +14

          Получилось действительно лаконично, есть некоторая система (вот эта вот симметрия разных стрелочек довольно прикольная).


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

            0
            Я уже привык к этому ASCII синтаксису, и, по моему опыту, скорости чтения это не мешает. Может даже наоборот. Также я планирую сделать плагин для Visual Studio Code с подсветкой синтаксиса. Тогда это вообще не будет проблемой.
              +7

              У вас, конечно, никаких проблем чтение вашего же собственного языка не вызывает:)

                +2
                Все даже лучше! Если не хватает какого-либо оператора, можно его дописать самому:)
            –1

            Интересная идея с разнонаправленными стрелками, но как-то всё это сложно. Хочется ещё проще язык.
            Подход к синтаксису похож на тот, что я описывал тут: https://habr.com/ru/post/503240/
            Как быть без finally, если он нужен?
            Ну и если вам интересно пообсуждать языковые концепции, то заглядывайте к нам в телеграм: https://t.me/lang_idioms

              0
              Я думаю добавить его позже, но не уверен, что сделаю это. Ведь в Una try-catch является выражением с возвращаемым значением. Возможно, finally просто ничего не будет возвращать.
              +2
              Только куда делась человекочитаемость?
              В этом плане, взятый за основу Lisp далеко не самый лучший пример для подражания.
                0
                LISP довольно просто читать, если привыкнуть и научиться думать рекурсивно как лисп-интерпретатор. Он немного непривычно выглядит, но все же вполне читабелен.

                Например:
                (defun square (x)
                   (* x x))
                


                  +18
                  Все же хочется думать как человек, а не как лисп-интерпретатор ;-)
                    +4
                    Программист все равно думает не как человек, а как компилятор языка, на котором пишет. Сравните как по разному даже в повседневности думают программисты разных языков
                      0
                      О, а можно пример?
                      +2
                      Вот ты и попался, человек!
                      –5

                      Всё же куда наглядней как-то так:


                      function perimeter
                          > @width float64
                          > @height float64
                          > @zoom float64
                          < mult
                                  2
                                  @zoom
                                  sum
                                      @width
                                      @height
                        0

                        Любой перенасыщенный длинными инструкциями язык станет легко читать, если привыкнуть к обилию в нём длинных инструкций ;)

                      +2
                      Очень не понимаю, чем вам так не нравятся скобки в лиспе, без них, лично для меня, теряется всякий смысл, да и в любом случае, при программировании почти никогда на них не смотришь, так как, опять же, отступы в форматировании кода позволяют читать:
                      (defun our-member (obj lst)
                        (if (null lst) 
                            nil
                            (if (eql (car lst) obj)
                                lst
                                (our-member obj (cdr lst)))))

                      вот так:
                      defun our-member (obj lst)
                        if (null lst) 
                           nil
                           if (eql (car lst) obj)
                              lst
                              our-member obj (cdr lst)


                      Ну и меня смущает, что в ваших примерах = z (calculate x y) форматируется как:
                      = z calclulate
                        x
                        y

                      Хотя по всей логике это должно выглядеть как-то так:
                      = z calculate
                                    x
                                    y

                      Потому что в лиспе (= z (calculate x y) как раз бы форматировалось так:
                      (= z (calculate
                                      x
                                      y)

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

                        В Una одна таба или два пробела уже задают вложенный блок, поэтому можно не бояться создавать глубоко вложенные деревья кода. Это вряд ли верно с точки зрения качества и читаемости, но возможность такая есть.
                          +2
                          Просто как по мне, это выглядит как-то так
                          (= z (calculate)
                             x
                             y)

                          В целом согласен, что при очень массивном коде это будет выглядеть не очень, просто привычки дают о себе знать
                            0

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


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

                              0
                              Ну, хорошая среда для лиспа сама будет выравнивать тебе все строчки. Ну и не стоит забывать, что у лиспа в основе функциональное программирование, сильно много перевыравнивать скорее всего не придется, если только это не всратый код, как тут
                                –2
                                хорошая среда для лиспа сама будет выравнивать тебе все строчки

                                Речь про системы контроля версий, а не про автоформатирование.


                                у лиспа в основе функциональное программирование

                                Это не так.

                                  +1
                                  Речь про системы контроля версий, а не про автоформатирование.

                                  Ну тут не разбираюсь, спорить не стану.
                                  Это не так.

                                  В смысле не так? Лисп — мультипарадигмальный язык, но функциональная часть явно преобладает даже в common lisp, не говоря о scheme и других диалектах. Конечно, на макросах можно даже ООП построить, а в CL есть goto, но это не отменяет того, что изначально вообще через лямбды писали
                                      +3
                                      Перед тем, как бросаться ссылками, могли сами немного прочитать
                                      Лисп изначально проектировался как функциональный язык программирования с отдельными императивными чертами, введёнными из соображений удобства практического использования.
                                        –2

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

                                          +3
                                          Ну тут вы загнули, даже в хаскеле можно писать с побочными эффектами, что в ФП, между прочим, недопустимо.

                                          И, опять же, нет, вы возвели все в абсолют, большинство языков императивные с чертами функционального.
                                            –3

                                            Емнип в Хаскеле всю эту императивщину можно запретить и только тогда он становится ФП.

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

                                                  Очень просто: все эффекты видны в типах, и поэтому побочных эффектов просто нет.

                                                +1

                                                Нельзя в хаскеле писать с побочными эффектами (без хаков типа unsafePerformIO).

                            +8

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


                            • перенос кода ломает табуляцию;
                            • выровнять код автоматически невозможно, поскольку табуляция имеет смысл;
                            • дебажить куда труднее, кроме проблем с табуляцией появляются проблемы из-за размытости синтаксиса. Как в том же хаскеле, где забытый аргумент функции = проблема с типами, как и практически любая другая ошибка.
                            • нотация через точку дает возможность легко просмотреть API объектов и классов, в языках без этого приходится каждый раз обращаться к документации;

                            А какие преимущества? Пара сэкономленных символов и некое эстетичное удовлетворение?

                              0
                              В Una тоже можно написать что-то вроде:
                              = numbers :: 1 2 3
                              = incrementedNumbers numbers.map (-> number (+ number 1))


                              Но из-за правил порядка применения операторов следующую функцию через точку мы уже вызвать не сможем. То есть вот так сделать нельзя:
                              (numbers.map (-> number (+ number 1))).filter (-> number (> number 1))

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

                              В целом, главное преимущество в таком синтаксисе действительно эстетическое удовольствие от созерцания кода, не отягощенного лишним синтаксисом.
                                0

                                Возиться с закрывающими скобками, особенно, если их много разного типа ))}}]}})))

                                +4
                                Начал читать, и подумал что это Форт. Потом понял что это не Форт. Посмотрел — это может быть Форт. :)
                                  0

                                  Читать тяжело. Куча видов стрелок только сбивает с толку. И в чем выгода от написания переменной справа от "равно", а не слева? a = 1 гораздо более привычная запись, чем = a 1.


                                  Lisp вы зря взяли за основу, его читать невозможно.


                                  Также, функции в JS надо объявлять словом function, а не const, так читабельнее, чем эта мешанина из стрелок. В function x() уже по первому слову понятно, что перед нами функция.


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

                                    +1
                                    Импорт css — это не часть моего языка, а фича webpack. В обычно JavaScript вы можете написать тоже самое

                                    import './index.css'

                                    и webpack подключит стили.
                                      –3

                                      Это и есть ненормально. Надо писать по стандартам ECMAScript, а не на каком-то придуманном авторами webpack птичьем языке. Абсолютно дурацкая фича. Если уж на то пошло, то CSS и JS файлы должны подключаться из HTML-шаблона, а не из псевдо-яваскрипт файла.

                                        +3
                                        Webpack — это де-факто стандартный сборщик для React-приложений. И когда создаешь приложение через create-react-app, то первой строчкой в основном js-файле будет именно импорт index.css. Я не понимаю, в чем проблема.
                                          0

                                          В том, что реакт не Javascript, а всего лишь его подмножество.

                                            0

                                            Это скорее над множество.

                                    +2

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

                                      –3
                                      Вот поэтому я пока что не доверю javascript серверную работу а оставлю только для клиента эту маза-факу…
                                      +9
                                      Прошу прощения но человекочитаемостью и не пахнет
                                      = a (+ 1 2)
                                      = b (- 2 1)
                                      = c (* 3 2)
                                      = d (/ 4 2)
                                      = e (% 5 2)

                                      Мы все со школы привыкли к записи x = y + z
                                      И такая запись интуитивно понятна всем, даже школникам.
                                      Ваша запись не понятна без пояснений никому.
                                      как я должен интерпретировать = d (/ 4 2) не зная правила вашего языка?
                                      Изучать мануал? Тогда причем тут человекочитаемость?

                                      = user :
                                        name 'John'
                                        age 13
                                        passport :
                                          id 1
                                          country 'USA'

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

                                      =-> './index.css'

                                      Серьезно считаете что эта запись более человечна чем
                                      import  "./index.css"

                                      или
                                      #include  "./index.css"


                                      Вы реально считаете что такой вывод интуитивно понятен и удобен?
                                      = name 'John'
                                      = count 5
                                      = fruit 'apples'
                                      
                                      = text `
                                        'Hello, ${0}' name
                                        'I have ${0} ${1}'
                                          count
                                          fruit
                                      
                                      console.log text


                                      Вот это понятно, читабильно и удобно:
                                      name = 'John'
                                      count = 5
                                      fruit = 'apples'
                                      text = 'Hello, $name \nI have $count $fruit'
                                      console.log text

                                      тут программист видит что I have $count $fruit будет написано с новой строки. В вашем варианте непонятно как будет произведен вывод из-за форматирования в редакторе. Не очевидно от слова 'софсем'. А если надо 10 пустых строк перед I have $count $fruit? В IDE вы будете делать 20 пустых строк в коде скрипта?
                                      = text `
                                        'Hello, ${0}' name
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                      
                                        'I have ${0} ${1}'
                                          count
                                          fruit

                                      Как по мне так это все глупость.
                                        +2
                                          –4
                                          а кто вам сказал что она более интуитивно понятна человеку чем запись x = y + z?

                                          PS прошу прощения но, я С++ програмист с 1999 года, закончил ФизМат но про эту дичь слышу впервые в жизни. Вот про венгерскую нотацию наслышан премного… Извините. Может быть пробел в образовании. Но мельком взглянув на польский стиль записи математиечких операций я как имеющий мат образование без пояснений ничего не понял.
                                          Профит от этого стиля записи для человека-программиста крайне сомнителен.
                                            +3

                                            Нет никакой "интуитивной понятности". Есть только привычки. Не стоит выдавать свои привычки за объективные свойства обсуждаемого предмета. И уж тем более не стоит в приличном обществе выпячивать на всеобщее обозрение свою неспособность эти привычки менять.

                                              0
                                              Я частично с вами соглашусь. Но опять же запись x = y + z, как вы правильно заметили, привычнее нам всем еще со школы.

                                              PS и про человекочитаемость озвученного в статье стиля кода заявил не я а автор статьи. Я лишь указал что человекочитаемости нет и в помине.
                                                +1

                                                Однако это не слишком удобная запись во многих случаях.

                                                  0
                                                  например?
                                                    +3
                                                    1. Когда используется много разных операторов легко напортачить с приоритетами.
                                                    2. Из-за неуверенности в приоритетах и для упрощения чтения приходится расставлять излишнее число скобок.
                                                    3. Парсить инфиксную нотацию существенно сложнее и медленнее.
                                                    4. Неконсистентность синтаксиса между вызовами функций и инфиксными операторами.
                                                    5. Практически невозможно расширять набор стандартных операторов вклиниваясь в иерархию приоритетов.
                                                    6. Когда читаешь сложное выражение приходится запоминать первый операнд и лишь потом узнаёшь для какого действия он предназначен.
                                                    7. Оператор может быть лишь 1 и 2 арным. Префиксная нотация позволяет делать операторы произвольной арности.
                                                      –1
                                                      Когда используется много разных операторов легко напортачить с приоритетами.

                                                      не уверен — ставь скобки. А еще лучше разбивай сложное выращение на несколько простых. Читать удобнее. Code review делать удобнее. Ошибиться сложнее.

                                                      Из-за неуверенности в приоритетах и для упрощения чтения приходится расставлять излишнее число скобок.

                                                      Когда скобки успели обьявить злом?

                                                      Парсить инфиксную нотацию существенно сложнее и медленнее.

                                                      компиляторы любые зубодробительные выражения перемалывают за микросекунды.

                                                      Неконсистентность синтаксиса между вызовами функций и инфиксными операторами.

                                                      Прошу прощения но я вас тут не понял. Каким образом синтаксис вызова функции пересекается с синтаксисом операторов? S( 1,2 ) и 3+4

                                                      Практически невозможно расширять набор стандартных операторов вклиниваясь в иерархию приоритетов.

                                                      Ну наверное на то они и стандартные? Или вы хотите иметь возможность менять приоритетность операторов чтобы сложение в вашем проекте имело больший приоритет чем умножение? Если так — то это шикарный способ выстрелить себе в ногу.

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

                                                      когда встречаются такие сложные выражения это зачастую минус разработчику. Разбивать надо на более элементарные и понятные для чтения. code review делать потом проще будет.

                                                      Оператор может быть лишь 1 и 2 арным.

                                                      и это минус? Хотите изменить поведение оператора? Ну так его можно переопределить в большенстве ЯП.
                                                        +1
                                                        Каким образом синтаксис вызова функции пересекается с синтаксисом операторов?

                                                        Любой оператор — это не более чем функция для компилятора.


                                                        На остальную демагогию мне ответить нечего.

                                                          –1
                                                          Любой оператор — это не более чем функция для компилятора.

                                                          ну если уж так глубоко копать — то для вызовов функции есть ключевое слово CALL в ассемблере. А для операторов свои ключевые слова. ADD SUB XOR AND…
                                                          вот только инструкция ADD это не функция

                                                          вот только человек не компилятор — есть уникумы читающие машинные коды но их подавляющее меньшинство.
                                                          не задумывались почему в асме постфиксная запись а в Си который разработали для упрощения жизни программистам — нет?
                                              0
                                              Вы путаете «понятность» и «привычность». Польская (а тем более, обратная польская) запись понятнее инфиксной. Кстати, инфиксная нотация Айверсона (справа-налево) тоже понятнее классической инфиксной.

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

                                              P.S. В 1984 году в МГУ давали и префиксную, и постфиксную нотации. И это не дичь, а элементарные базовые знания, необходимые во многих разделах программирования — начиная с символьных вычислений и компиляторов.
                                                0
                                                Прошу прощения, но я понятность и привычность не путаю.
                                                Любому школьнику x = y + z и понятнее и привычнее. То что понятнее лишь выпускнику ВМК МГУ понятнее лишь выпускнику ВМК МГУ. Большая часть лишь изумленно пожмет плечами.
                                                  +1
                                                  Школьнику «x = y + z» привычнее потому, что в школе его учили только «x = y + z» — и никак иначе. Это не «понятность», а всего лишь результат школьной дрессировки.

                                                  «Понятность» — это про кол-во усилий, требуемых на чтение записи выражения. И стандартная инфиксная нотация — при наличии опыта использования альтернативных нотаций — в этом безусловно проигрывает.

                                                  Кстати, если школьнику в начале тех же 1980-х попадал в руки советский программируемый калькулятор, он очень быстро понимал, насколько постфиксная запись удобнее для вычислений, чем инфиксная. И для этого совсем не надо было учиться на ВМК.
                                                    0
                                                    Школьнику «x = y + z» привычнее потому, что в школе его учили только «x = y + z» — и никак иначе. Это не «понятность», а всего лишь результат школьной дрессировки.

                                                    Любая «понятность» — это результат обучения. Вопрос лишь в том понятно это всем ( ну или почти всем ) или только узкому кругу лиц обладающим необходимым опытом.

                                                    «Понятность» — это про кол-во усилий, требуемых на чтение записи выражения. И стандартная инфиксная нотация — при наличии опыта использования альтернативных нотаций — в этом безусловно проигрывает.

                                                    При наличии опыта, много что удобнее. Люди даже машинные коды читают как книгу.

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

                                                    да потому что там по факту сразу на асме программирование шло
                                                    mov ecx, 1
                                                    mov edx, 3
                                                    sub ecx, edx
                                                    mov ebx, ecx

                                                    не потому что так человеку удобнее и проще а потому что микропроцессору это удобнее
                                                    только не зря на смену асму Си пришел. Он удобнее и проще именно для человека оказался. Хотя люди на Си писали с большим опытом работы на асме. Но тем неменее не реализована постфиксная запись в Си. Не задумывались почему?
                                                      +1
                                                      Любая «понятность» — это результат обучения
                                                      Никакие обучение не может уменьшить объём дополнительной информации, которую необходимо держать в уме в процессе «понимания». И чем больше этот объем, тем сложнее «понимание». А для инфиксной нотации этот объём существенно больше, чем для альтернативных нотаций.
                                                      При наличии опыта, много что удобнее. Люди даже машинные коды читают как книгу.
                                                      Забавная демагогия. Машинные коды всегда будут читаться медленнее ассемблера — в силу более сложного процесса анализа информации.
                                                      да потому что там по факту сразу на асме программирование шло
                                                      Вы либо не понимаете, о чём идёт речь, либо опять занимаетесь демагогией. Программируемые калькуляторы куда чаще использовались именно как калькуляторы — для ручных вычислений. И я говорю именно об удобстве ручных вычислений.
                                                      не потому что так человеку удобнее и проще а потому что микропроцессору это удобнее
                                                      Ошибаетесь, удобнее именно человеку: не надо тратить время и силы на учёт приоритетов операций и расстановку скобок.
                                                      Но тем неменее не реализована постфиксная запись в Си. Не задумывались почему?
                                                      Потому, что любой язык программирования отражает личные вкусы его авторов. Не существует объективной причины использовать именно инфиксную нотацию.
                                                        +1
                                                        Потому, что любой язык программирования отражает личные вкусы его авторов. Не существует объективной причины использовать именно инфиксную нотацию.

                                                        Так Си писали люди которые кроме как на асме никогда не кодили
                                                        И для них sub ecx, edx более естественно и привычно было чем
                                                        ebx = ebx — ecx

                                                        Но соглашусь — в демагогию скатился. Извините.
                                          0
                                          clojurescript не подошел?
                                            0
                                            Clojure хорош, но все же это другой язык с сильно другим API и идеологией, а мне нужна была бесшовная интеграция с JavaScript.
                                              0
                                              >Clojure хорош
                                              всмысле clojurescript?
                                              clojurescript.org/reference/javascript-api
                                              www.verypossible.com/insights/clojurescript-and-javascript-interoperability-a-comprehensive-guide
                                              интеграция есть вроде, насколько это бесшовно не знаю
                                                0
                                                Да, я говорил о ClojureScript. Una гораздо ближе к чистому JS, чем ClojureScript. Почти все, что можно написать на JavaScript в функциональном стиле, можно написать и на Una точно также с минимальными отличиями. А у Clojure и ClojureScript все-таки немного другая философия языка.
                                                  0

                                                  Таки не понятно что там отличается))
                                                  Почти все что есть в JS если и в CJ. Только более удобно.
                                                  К тому же там ещё много других крутых возможностей например встроенная либо google closure.

                                            0
                                            Помнится, SQL тоже создавался «человекоориентированным», чтоб каждая кухарка могла. Что получилось в итоге мы все знаем.
                                              +2

                                              А что получилось? Почти любая субд сейчас его поддерживает.

                                                +11

                                                Но не любая кухарка.

                                                  +4

                                                  К сожалению — почти любая кухарка. У SQL очень низкий порог входа. Из-за этого очень много запросов, написанных "аналитиками" или людьми не понимающими СУБД или людьми далёкими от инженерной/разработческой культуры.
                                                  Как следствие много запросов а) неправильных по сути, но выдающие правильный результат в данной ситуации б) правильных по сути, но плохих для СУБД, в) написанных так, что их прочитать и понять можно только под тяжёлыми наркотиками, г) сгенерированных программами.
                                                  А на это накладывается отвратительная модель типов и практики проектирования ЯП середины прошлого века (тут я могу написать с десяток пунктов от имен идентификаторов до отсутствия модульности). Добавим сверху врождённую проблему почти любой СУБД — повсеместную мутабельность, конкурентность доступа, глобальность и необъятность состояния, неидемпотентность DDL (да, но в этом и суть СУБД). Полирнуть сверху тем, что РСУБД, реляционная теория и SQL — это три очень разные темы и вбить окончательный гвоздь тем, что его модель одинаково плохо мэтчится с моделями как "классических" "императивных" ЯП (C/C++/C#/Java), так и "продвинутых" "стремящихся к декларативности" ЯП (напр. Haskell).


                                                  Но есть еще нюанс. SQL, как я выше сказал, не только легко пишется "домохозяйками", но и выполняется близко к массивным объёмам данных, а из-за этого часто (отвратительный) код, написанный на SQL будет эффективнее, чем код на других ЯП.


                                                  Это приводит к тому, что у коммерческих потребителей (банки, шманки) образовались мегатонны этого кода. У 100% топ-30 банков РФ ключевые mission critical расчётные блоки написаны на SQL (T-SQL, PL/SQL, PL/pgSQL и т.п.). Миллионы, если не миллиарды строк. Их не отрефакторить, не выкинуть, не отмасштабировать, не структурировать. Да и даже новых перспективных идей ЯП для СУБД вроде как не видно на горизонте или, как минимум, я о них не знаю (Tutorial D "нещитова", конечно). Cтартапики фигачут микросервисную архитектуру, PhD придумывают Haskell/Scala/Coq/Agda, AWS/Google/MS строят облака в облаках, а триллионы долларов считаются всё теми же SELECT/INSERT/UPDATE/DELETE.


                                                  Вот и выходит, что SQL — это новый COBOL. Только другого масштаба.
                                                  Я с 2012-2013 надеюсь, что придёт новый Христос супергений, который соединит СУБД и современные наработки теории ЯП: функциональную парадигму, сильные системы типов, проверки завершаемости, встренную асинхронность и ленивость, отсутствие непредсказуемых побочных эффектов, повышение декомпозируемости, переиспользуемости и модульности и вот всё это. Но, кажется, что даже потребности в этом остальные пока не видят.
                                                  Наболело. Уфф. Dixi.

                                                    0
                                                    надеюсь, что придёт новый Христос супергений, который соединит СУБД и современные наработки теории ЯП
                                                    , нет, не придёт.
                                                    И тут есть три факта:
                                                    1. SQL — вообще не язык программирования. Это язык запросов. DDL вообще о другом — он меняет среду исполнения (и тут есть замечательный возможности… например, адаптивная модификация структуры хранения и кода, отвечающего за работу с данными).
                                                    2. ЯП в СУБД есть, но это T-SLQ, PL/SQL и т.п., и решают они специфические задачи вполне хорошо. Их «недостатки» связаны как раз с областью применения. И да, ФП там тоже есть, и много чего ещё…
                                                    3. Ну вот не нужен в СУБД ЯП общего назначения. Там нужно то, что будет эффективно данные обрабатывать. И все особенности тамошних языков вызваны потребностью выполнять в секунду тысячи вычислительных транзакций в условиях конкурентного доступа к данным.

                                                    Не нравится РСУБД — есть другие подходы. У каждого свои плюсы и минусы.
                                                      +1
                                                      SQL — вообще не язык программирования.

                                                      Сложно оспорить, потому что, видимо у нас разные определения и источники. Википедия считает, что ЯП. Дейт считает, что ЯП. ISO/ANSI формулируют, что это database language, но программисты пишут на расширениях SQL (T-SQL, PL/SQL), а не на голом SQL (ISO/IEC 9075: год). К тому же лично я не знаю ни одной сколько-либо полной имплементации этого стандарта (ближе всех Oracle), а сам стандарт реально безумное лоскутное одеяло фантазий и фич нескольких вендоров (процентов на 70 — Oracle). Вычислительно SQL даже в части запросов с рекурсивными CTE тьюринг-полный, есть система типов, есть control flow, процедуры и функции так что это ходит как утка и крякает, как утка.
                                                      DDL это просто часть SQL (как стандарта, так и расширений). Про "адаптивную модификацию структуры хранения и кода" я не понял. Приведите пример, что имелось в виду.


                                                      ЯП в СУБД есть, но это T-SQL, PL/SQL и т.п., и решают они специфические задачи вполне хорошо

                                                      Да я как раз и пишу, что нифига они хорошо не решают. Производительно — да, решают. Лаконично (по сравнению с другими) выражаются запросы — да, пожалуй, это существенное преимущество. Управляющие и структурные конструкции — примитивные (и это то, почему язык быстро осваивается), но сам язык удивительно нецелостный и разнородный.
                                                      Про ФП в SQL и его расширениях впервые слышу. Дайте пример, пожалуйста.


                                                      Ну вот не нужен в СУБД ЯП общего назначения.

                                                      Ну во-первых я не говорю, что ЯП должен быть "общего назначения". Наоборот, скажу, что ЯП общего назначения, даже самые передовые проигрывают в манипуляциях с данными языку SQL.
                                                      А во-вторых, да-да-да, совсем не нужен. А потом кода становится миллионы строк, программистов больше пары десятков, постоянных сущностей в БД 100к и ОПА — каждое прикосновение — боль.


                                                      Не нравится РСУБД — есть другие подходы.

                                                      1. Мне не нравится, когда смешивается понятие РСУБД и SQL. Идея РСУБД мне нравится (хотя она тоже хромая на обе ноги, но её можно, наверное вылечить).
                                                      2. SQL — это не "Р". Дедушка Дейт тоже так считает. Кодд тоже так считал.
                                                      3. Интересует, какие есть эффективные в разработке и эксплуатации "другие подходы", какие там языки (запросов и программирования, если их делить)?
                                                        0
                                                        То, что SQL не язык программирования, следует из его названия («язык структурированных запросов»). Далее вопрос в том, насколько широко растягивать понятие ЯП. Так-то и css — уже ЯП.
                                                        Да, даже в SQL-92 были добавлены процедуры, но из нельзя написать на ANSI-SQL, реализации есть именно в вендорских расширениях. И вот эти расширения уже можно рассматривать как ЯП.

                                                        Адаптивная модификация… Это у меня был такой эксперимент. Не знаю, делает ли ещё кто так… Но, если вкратце, была система без заранее определённой доменной модели. Для хранения данных сделали объектно-атрибутное хранение (объект — название/тип атрибута — значение атрибута). Новые типы объектов и модификация списка атрибутов происходят на лету, но по мере увеличения количества данных падает производительность. А т.к. вся работа и так сделана была через хранимки, была написана процедура оптимизации, которая по статистике решала, что надо вынести в обычные таблицы. И эта процедура создавала таблички, переносила данные, меняла код вспомогательных процедур, генерящих динамические запросы. Тот ещё мутант, но работало прикольно.

                                                        Про ФП в SQL. Речь про всякие T-SQL и PL/SQL, где есть функции, которые могут быть чистыми в терминах ФП. Это, в свою очередь, очень помогает оптимизатору. Ну и оконные функции тоже сюда можно отнести. Да, это не полноценные ФП-языки, но тем не менее.

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

                                                        Мне не нравится, когда смешивается понятие РСУБД и SQL
                                                        Мне тоже не нравится, но вот в чём фокус. Почти одинаково глупо работать с РСУБД без SQL и применять SQL без РСУБД.

                                                        Про другие подходы. Есть же много всякого. Document-oriented database, графовые БД, системы распределённых вычислений и т.д.

                                                          0
                                                          плохой код можно написать на любом языке.

                                                          Но на некоторых просто невозможно писать хороший.

                                                            0
                                                            Но на SQL таки можно.
                                                            0
                                                            То, что SQL не язык программирования, следует из его названия («язык структурированных запросов»).

                                                            По названию я тогда должен предположить, что Java и Kotlin это острова, а не ЯП? Неудачное разделение. Как мне понять, где вы провели границу, между ЯП и не ЯП? Мои критерии.


                                                            • на языке пишут программы для вычислительной техники (хранимку в 100к строк и витиеватой логикой сложно не назвать программой) и это его основное назначение
                                                            • вычислительно полный
                                                            • язык должен задавать алгоритмическую последовательность действий компьютера (возможно лениво и декларативно, асинхронно и параллельно выполняющуюся, но всё-таки), т.е. в каком-то смысле есть control flow
                                                            • есть система типов

                                                            И вот эти расширения уже можно рассматривать как ЯП.

                                                            И вот на них и пишутся тонны кода.


                                                            И эта процедура создавала таблички, переносила данные, меняла код вспомогательных процедур, генерящих динамические запросы. Тот ещё мутант, но работало прикольно.

                                                            Да, это мутант и это не прикольно. Такие штуки очень сложно поддерживать, они прибиты гвоздями к вендору СУБД, это сложно масштабируется и еще сложнее обеспечить консистентность и параллельную работу в среде высокой конкурентной нагрузки на запись.
                                                            Код, который генерирует код или развитые средства шаблонизации (что на самом деле близко) — обыденность и в других областях, но в современных ЯП это делается несколько более элегантно.


                                                            Про ФП в SQL.

                                                            Про ФП, наверное, нельзя говорить пока функции не 1st class objects. Ну хотя бы функциональный тип чтобы был. То, что некоторые функции не имеют побочных эффектов и возвращают детерминированное значение, и это позволяет применить оптимизацию — это вообще не ФП.


                                                            плохой код можно написать на любом языке.

                                                            Но на T-SQL невозможно написать хороший код (если мы говорим о крупных проектах). На PL/SQL и на PL/pgSQL можно написать код чуть лучше, но не очень хочется сейчас уходить в детализацию различий сортов отходов жизнедеятельности.


                                                            Почти одинаково глупо работать с РСУБД без SQL и применять SQL без РСУБД.

                                                            Тем не менее, я не готов смешивать обсуждение языка SQL и "реляционности", т.к. слово "реляционные" в этих "Р"СУБД — исторически сложившаяся маркетинговая уловка. Хотя есть еще много СУБД, которые сложно назвать реляционными, но в том или ином виде SQL там есть. Но, ОК, я понял, что для вас "БД с SQL" и "РСУБД" синонимы.


                                                            Про другие подходы. Есть же много всякого. Document-oriented database, графовые БД, системы распределённых вычислений и т.д.

                                                            Дайте, пожалуйста, список примеров систем/платформ учета на этих подходах. ERP или ABS какие-нибудь или что-то подобное?

                                                              0
                                                              где вы провели границу, между ЯП и не ЯП
                                                              тут всё просто. SQL задуман как язык запросов, а не программирование. Оное появилось там позже и отдельно от вендоров не существует именно языка программирования SQL (насколько я знаю).

                                                              они прибиты гвоздями к вендору СУБД
                                                              БД с бизнес-логикой и так прибита к вендору. Лично я вообще не сторонник писать сложную логику в СУБД (кроме, собственно, запросов).
                                                              А мой мутант был хорош тем, что был сокрыт за публичным АПИ, и его работа никак не влияла на этот АПИ. А вот если ходить мимо — то да, могли быть сюрпризы. Но и не говорю, что это очень уж хорошо :)

                                                              пока функции не 1st class objects.
                                                              Конечно, там нет полноценного функционального языка, хотя есть элементы функциональной парадигмы.

                                                              T-SQL невозможно написать хороший код (если мы говорим о крупных проектах)
                                                              А вот тут просто надо знать меру. Я видел и хорошие и плохие варианты и на T-SQL и на PL/SQL. И это даже не сильно зависело от размера. Гораздо больше это зависело от архитектуры и качества разработки.

                                                              есть еще много СУБД, которые сложно назвать реляционными, но в том или ином виде SQL там есть
                                                              а есть примеры, где SQL вне РСУБД лучший выбор, а не дань традиции?

                                                              для вас «БД с SQL» и «РСУБД» синонимы
                                                              Нет, не так. Но я считаю SQL наиболее удобным для запросов к данным РСУБД.

                                                              список примеров систем/платформ учета на этих подходах
                                                              Много их. К примеру: Hadoop, Apache Ignite

                                                +3
                                                Человекочитаемость
                                                Лаконичность
                                                Внутренняя непротиворечивость
                                                Чистота и красота

                                                Открываем Википедию
                                                Язык для человека, а не для компьютера.
                                                Просто, но не слишком просто.
                                                Принцип наименьшей неожиданности
                                                Ортогональность важна, но естественность важнее.
                                                Следовать простым и строгим правилам, но не доходить до педантизма.

                                                Также это все есть в питоне.
                                                А еще огромная проблема вашего языка — в нем мало плюшек и сахара для программиста. Да, это вопрос времени, но добавьте туда столько плюшек, сколько их в том же питоне — вы получите второй джаваскрипт, только лиспнутый на всю голову.
                                                  0
                                                  Питон совсем не лаконичен и местами очень странный. Возьмем простейший пример из доков питона:
                                                  def addition(n): 
                                                      return n + n 
                                                    
                                                  numbers = (1, 2, 3, 4) 
                                                  result = map(addition, numbers) 
                                                  print(list(result)) 
                                                  


                                                  Возникает множество вопросов:
                                                  • Почему функция map, примененная к листу, возвращает не лист, а итератор? Это противоречит самому смыслу маппинга
                                                  • Почему лямбда функция (одна из самых частоиспользуемых конструкций в любом языке) записывается не стрелочкой как во всех языка, а через слово отдельное слово lambda?
                                                    +1

                                                    Так она и принимает на вход итератор вроде. Лист — лишь частный случай итерируемой коллекции.

                                                      0
                                                      Это нарушение самой сути функции map. Функция map — это функция монады и для нее обязательно должно выполнятся равенство:
                                                      map(x => x, container) == container


                                                      А если функция принимает list, а возвращает iterable — это очень странно и неудобно.
                                                        0

                                                        Это называется полиморфизм. То, что вы функции передаёте — это вовсе не обязательно то, что она принимает. А возвращает map то, что принимает, а не то, что вы ей передали.

                                                          +1

                                                          Это какой-то очень странный полиморфизм.


                                                          map здорового человека выглядит как map : (a -> b) -> f a -> f b, где f — соответствующий функтор, и, более того, map id = id (это вообще необходимый закон для функторов). Обратите внимание, что f в возвращаемом значении такой же, как в принимаемом, и при подстановке id вместо f тип вырождается в f a -> f a.

                                                            0

                                                            Вам знакомо понятие "интерфейс"? map принимает и возвращает один и тот же интерфейс. Реализации этого интерфейса могут быть какими угодно.

                                                              0
                                                              Об этом я и написал. Реализация map в питоне противоречит общепринятой спецификации map-функтора. Из-за несоблюдения главного закона функтора map(x=>x, container) == container, питоновский map теряет возможность композиции.
                                                                +1

                                                                Вполне знакомо. Только не путаете параметрический полиморфизм и сабтайпинг-полиморфизм.

                                                              0

                                                              Дмитрий, вы когда пишите фразу "то что она принимает", что вы имеете ввиду? Передача это видимо про ее параметры, а про принимает это про результат или про ее контекст?


                                                              Вполне знакомо. Только не путаете параметрический полиморфизм и сабтайпинг-полиморфизм.

                                                              0xd34df00d сабтайпинг-полиморфизм это про контекст?

                                                        +1
                                                        Такое поведение map вполне обосновано: у вас есть выражение типа
                                                        map(a, filter(b, map(c, smth_list)))

                                                        Если в этом smth_list у вас 10**10 значений, то языку будет неободимо хранить в памяти smth_list, map1, filter, map2, то есть, в 4 раза больше значений. Поэтому же range(10**7) не занимает 100мб памяти, просто это будет бессмысленно.

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

                                                        В конце концов, ваш fuction_for_map не обязательно будет возвращать те же данные, что и получает, может, вы в мапе просто хотите получить 3 поля всех моделек из вашего queryset таблицы в 20 полей, кто ж вас знает. И питон не гадает, что вы там хотите, он говорит «ты взрослый человек, делай что хочешь, но и вся ответственность пусть лежит исключительно на тебе».

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

                                                        П.с. Сам я, наверное, ни разу не пользовался мапами и фильтрами, тк лично для меня удобнее вещи типа
                                                        [get_first_field(item) for item in item_table]
                                                        [item for item in item_table if item['is_mutable']]
                                                          +2

                                                          Ух, тяжко как без ленивости или без компилятора с fusion.

                                                            0

                                                            Во-первых, с повсеместной ленивостью мы получаем foldl, который потом стыдливо прикрываем его жадным братом foldl'. Во-вторых, все равно во всем мире, где не стремятся избежать успеха любой ценой, всегда есть два варианта: greedy (map) и lazy (по-разному). В питоне это что-то типа iterators.imap, в руби — .lazy.map, в эликсире — Stream.map.


                                                            Ну и синтаксический сахар с list comprehension, которые ваш оппонент продемонстрировал в конце — ленивый.

                                                              0
                                                              Ну и синтаксический сахар с list comprehension, которые ваш оппонент продемонстрировал в конце — ленивый.

                                                              Нет, как раз таки list comprehension энергичный, ленивым является generator comprehension.

                                                                0

                                                                А, ой, пардон, спасибо, да; не нужно было мне про питон догадки строить.

                                                            0
                                                            Сам я, наверное, ни разу не пользовался мапами и фильтрами

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


                                                            Вот в Haskell, например:


                                                            map getFirstField itemTable
                                                            filter isMutable itemTable
                                                        0
                                                        А что не написали полностью семантический язык, раз хотели максимум семантики?
                                                          0
                                                          Я думаю, когда-нибудь в редакторах появится возможность отображать стиль кода в зависимости от предпочтений текущего разработчика.
                                                          К примеру, в общем проекте одному нравится отступы с 2 пробелами, другому с 4, одному со скобочками другому без, одному if в одной строчке, другому в разных, кто то хочет; на конце, кто-то нет и тд.
                                                          И, наверное, можно гораздо дальше пойти вплоть до отображения в виде этого Una или чем-то подобном, при неизменном стандартном коде js в общем репозитории.
                                                          Может уже есть такие плагины для VS Code. Кто-нибудь видел?
                                                            0
                                                            Полагаю, что это если и возможно, то очень трудно реализуемо, иногда код в середине строки может выравниваться для красоты:
                                                            const screenLeft   as byte   = radius
                                                            const screenTop    as byte   = radius
                                                            const screenRight  as ushort = screenWidth  - radius
                                                            const screenBottom as ushort = screenHeight - radius

                                                            Как среда должна поступать в таких случаях, когда язык позволяет писать эти выражения на нескольких строках?
                                                              0
                                                              Я думаю, почти всё и даже всё можно описать алгоритмами.
                                                              Конкретно по приведённым строкам, тут например можно указать редактору, чтобы выравнивал по самым длинным названиям.
                                                                0
                                                                Ну в данном конкретном примере — да, наверное, можно, но тут всего 4 строки, и это только один из примеров. В других случаях пробелы могут расставляться совершенно не очевидным образом, тогда придется писать достаточно сложные алгоритмы. И если у нас будет файл на несколько тысяч строк, совершенно внезапно пересчет стиля сможет занять неприемлемое время
                                                                  0
                                                                  Файл несколько тысяч строк, сложно серьёзно комментировать, это по какой методологии такое может быть? )
                                                                  Уверен, любую простыню как минимум можно, но скорее нужно разделить.
                                                              0
                                                              Всё равно ревью происходит в GitLab / GitHub / других инструментах.
                                                              Код читают и пишут не только в IDE. И это вряд ли изменится.
                                                                0
                                                                Идея в том, чтобы код хранился в стандартном одном стиле, но представление в редакторе можно было бы настроить и редактор бы реально сохранял в первоначальном стиле.
                                                                0
                                                                Отступы регулируются, сколько себя помню. Есть волшебная кнопка tab для этого. Функции IDEA умеет сворачивать в одну строчку (только визуально). Скобки можно поставить цветом фона (возможно в VSCode для этого требуется отдельный плагин).
                                                                Короче движение есть, но разнонаправленное.
                                                                +3

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


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

                                                                  +1
                                                                  читаешь в слух и осмысленные предложения получается сразу

                                                                  И получается, внезапно, AppleScript. Правда из-за такой многословности он и не взлетел толком, ибо в полноценном софте не будешь писать строчки на пол-экрана типа tell MyLibrary to tell object sharedInstance to tell WebClient to fetch content of URL myUrl.


                                                                  Ну и у японцев есть подобные языки, по типу Nadesiko или MIND, в которых весь код является чисто текстом на слегка структурированном японском. Но японский — он сам суть тот же Форт, только самозародившийся.

                                                                  +2
                                                                  Знаете, посмотрев примеры кода, я почему-то сразу подумал, не поверите, как раз о Руби. Его создателю операции с массивами и строками казались интуитивными. А мне наоборот — нет. Здесь обращения к объектам и полям вызывают те же чувства. А еще «отступ» такое хорошее понятное слово. Об «индентацию» я сломал глаза и мозг.
                                                                    0
                                                                    Что-то крупное на этом не напишешь. Равно как и на чистом JS. Без строгой типизации и статического анализа, лаконичность превратится в боль и страдания

                                                                    Успехов с регулярками :)
                                                                      +1
                                                                      Мне очень понравилось! Единственное — не привычно, но я понимаю, что это просто вопрос времени. Куда важнее, что всё согласовано и куда логичнее, чем в js.

                                                                      Я правильно понял, что ваш язык можно использовать как эксперимент, но в случае чего, можно прогнать транслятор и получим тот же js, который однозначно будет рабочим и читаемым? Это нужно как аргумент, чтобы в случае чего малой кровью отказаться от Una (как страховка, так сказать)
                                                                        +1
                                                                        Да, конечно. На выходе он выдает обычный JavaScript. И можно все .una файлы откомпилировать в JavaScript и выкинуть Una из проекта.
                                                                        0

                                                                        Как писал один мой знакомый:


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

                                                                        Зачем вообще нужен новый ЯП, если единственное, что он даёт — новый синтаксис? Где интересная семантика?

                                                                          +1

                                                                          Затем же, зачем остальные DSL. Чтобы уменьшить объём однотипного кода при решении задач из предметной области.

                                                                            0

                                                                            Ну так я тут что-то не вижу уменьшения объёма. Синтаксис отображается один в один, каких-то более семантически ёмких конструкций, чем в Javascript, я не вижу. Ну и в чём профит тогда?

                                                                              +1

                                                                              В исчезновении колонки из слов "const"

                                                                          +1

                                                                          Почти уверен, что не взлетит в промышленном масштабе, но в вашем Uno достаточно много интересных идей, доведённых до хоть какой-то реализации. И это реально круто.
                                                                          А прочтение статьи побуждает задуматься о некоторых моментах для других DSL.

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

                                                                          Самое читаемое