Imba — это опенсорсный язык программирования, созданный компанией Scrimba специально для разработки веб-приложений. Он компилируется в JavaScript и способен работать внутри существующей JS-экосистемы. Речь идёт, например, о Node.js, об npm, о Webpack.

Основная сильная сторона Imba заключается в том, что этот язык позволят создавать гораздо более быстрые приложения, чем те, которые основаны на библиотеках, применяющих технологию Virtual DOM, наподобие React и Vue. Рост производительности приложений достигается за счёт того, как Imba работает с обновлениями DOM. Подробности об этом можно почитать здесь.



Автор этого материала, сооснователь проекта Scrimba, говорит, что пользуется Imba уже несколько лет. По его словам, писать на этом языке — сплошное удовольствие, так как он, в сравнении с JavaScript, отличается более чистым синтаксисом, что улучшает читабельность кода.

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

О проектах, в которых используется Imba


Прежде чем мы займёмся кодом, мне хотелось бы обратить ваше внимание на то, что Imba — это не нечто вроде очередного странного языка, компилируемого в JS и используемого исключительно в любительских проектах. Он применяется и в серьёзных приложениях больших компаний.

Один из примеров его применения — платформа, поддерживающая рыбный аукцион в Исландии. В этой стране на торговлю рыбой приходится около 1.6% ВВП, а это примерно 390 миллионов долларов.


Исландский рыбный аукцион

Ещё один пример — обучающая платформа Scrimba.com, где Imba используется на клиентской и на серверной частях проекта. Удобство работы с этой платформой, в основе которой лежит сложное приложение, сильно зависит от возможностей Imba по быстрой синхронизации изменений DOM.


Платформа Scrimba.com

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

Синтаксис


Синтаксис Imba во многом похож на JavaScript, но влияние на него оказали и другие языки, такие как Ruby и Python. Пожалуй, особенности синтаксиса Imba удобно будет рассмотреть на примере. Ниже показана простая JS-функция, которая возвращает наибольшее из двух переданных ей чисел, или, если эти числа равны, значение false.

function findGreatest(num1, num2) {
  if (num1 > num2) {
    return num1
  } else if (num2 > num1){
    return num2
  } else {
    return false
  }
}

Теперь напишем то же самое на Imba.

def findGreatest num1, num2
    if num1 > num2
        num1
    elif num2 > num1
        num2
    else
        false

Вероятно, сравнив эти два примера, вы сразу сможете увидеть различия между Imba и JavaScript. А именно, они заключаются в следующем:

  1. function превращается в def. Ключевое слово function заменено ключевым словом def.
  2. Отсутствие скобок. Параметры функции не заключены в скобки. В Imba, на самом деле, скобки нужны редко, хотя, если хотите, вы можете их использовать.
  3. Отступы. Отступы играют очень важную роль в Imba. Это означает, что фигурные скобки здесь не нужны.
  4. Отсутствие ключевого слова return. В Imba возврат значений из функций выполняется неявно, то есть, в ключевом слове return необходимости не возникает. Imba автоматически возвращает последнее выражение функции.

Нельзя сказать, что вышеописанные особенности синтаксиса — это самый главный аспект Imba, но они делают код более лаконичным, чем аналогичный код, написанный на JavaScript. Это преимущество станет более заметным по мере нашего продвижения по материалу.

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


Поговорим о создании пользовательских интерфейсов с использованием Imba. Собственно говоря, данный язык создан именно для этого. В частности, это означает, что узлы DOM встроены в язык в виде так называемых «объектов первого класса».

Если у вас есть опыт React-разработки, вы можете рассматривать эту особенность Imba так, как будто в Imba есть собственная версия JSX, встроенная в язык.

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

class App extends React.Component {

  logOut() {
    console.log('button clicked!')
  }

  render() {
    return (
      <div className="container">
        <button onClick={this.logOut}>click me!</button>
      </div>
    )
  }
}

Если это переписать на Imba, то получится следующее.

tag App

    def logOut e
        log 'button clicked!'

    def render
        <self.container>
            <button :tap.logOut> 'Click me!'

Imba.mount <App>

Давайте сравним эти два фрагмента кода. А именно, обратим внимание на следующие три особенности:

  1. Встроенные теги. Обратите внимание на то, что конструкция вида class App extends React.Component была преобразована к гораздо более простому виду — tag App. Ключевое слово tag встроено в язык. Встроенными являются и теги DOM.
  2. Отсутствие закрывающих тегов. Так как выравнивание строк определяет структуру программы, закрывать теги (например — используя тег </button>) не нужно. Это ускоряет ввод текста программы и уменьшает его размер.
  3. Простой синтаксис классов. В Imba упрощена работа с HTML-классами. А именно, вместо громоздкой конструкции className="container" здесь достаточно добавить .container к самому тегу.

Возможно, вы обратили внимание и на особенности обработчиков событий в Imba. А именно, мы подключаем к кнопке соответствующий обработчик с помощью конструкции :tap.logOut, используемой вместо onClick={this.logOut}. Это — лишь один из нескольких способов обработки событий, поступающих от пользователя. Подробности об этом можно почитать здесь.

Работа с данными


Теперь поговорим о работе с данными в Imba. В следующем примере показано React-приложение, в состоянии компонента App которого имеется переменная count, равная 0. Значение этой переменной уменьшается или увеличивается при щелчке по соответствующим кнопкам.

class App extends React.Component {

  state = {
    count: 0
  }

  increase = () => {
    this.setState({
      count: this.state.count + 1
    })
  }

  decrease = () => {
    this.setState({
      count: this.state.count - 1
    })
  }

  render() {
    return (
      <div className="container">
        <button onClick={this.increase}>Increase!</button>
        <button onClick={this.decrease}>Decrease!</button>
        <p>{this.state.count}</p>
      </div>
    )
  }
}

Вот как то же самое будет выглядеть на Imba.

tag App

    prop count default: 0

    def increase
        count += 1

    def decrease
        count -= 1

    def render
        <self.container>
            <button :tap.increase> 'Increase!'
            <button :tap.decrease> 'Decrease!'
            <p> count
Imba.mount <App>

Первое, что бросается в глаза при сравнении этих двух примеров — разница в объёме кода.

Пример на Imba примерно в два раза короче — и по количеству строк, и по объёму кода.

Хотя само по себе сравнение числа строк кода при сопоставлении языков программирования — это не так уж и важно, это, тем не менее, влияет на читабельность кода, что, в масштабах некоей кодовой базы, уже играет определённую роль. Меньший объём кода на Imba означает лучшую его читабельность в сравнении с React.

Неявное обращение к self


Вы могли заметить, что в вышеприведённом примере мы обращаемся к переменной экземпляра объекта напрямую, упоминая лишь её имя count. В React же то же самое выполняется с помощью конструкции this.state.count.

В нашем примере на Imba можно было бы использовать и конструкцию вида self.count, однако обращение к self здесь выполняется неявным образом, поэтому указывать self необязательно. Imba, при обращении к count, выясняет, имеется ли такая переменная либо в области видимости, либо у самого экземпляра App.

Мутабельность


Ещё одно серьёзное различие между двумя предыдущими примерами заключается в том, как в них реализовано изменение состояния. В примере, написанном на Imba, состояние мутабельно, что позволяет менять значение переменной count напрямую.

В React используется другой подход, при котором значение this.state рассматривается как иммутабельное, в результате единственный способ его изменить заключается в использовании this.setState.

Если вы предпочитаете работать с иммутабельным состоянием — вы можете использовать совместно с Imba соответствующую библиотеку. Язык Imba в этом смысле не привязан к какому-то определённому решению. Мы же, в проекте Scrimba, используем мутабельное состояние, так как полагаем, что излишние затраты ресурсов системы, необходимые для обеспечения иммутабельности, нам ни к чему.

Настройка среды разработки


Теперь, когда вы ознакомились с основами Imba, пришло время поэкспериментировать. Для этого вам понадобится настроить среду разработки. Для того чтобы это сделать, достаточно выполнить следующие команды.

git clone https://github.com/somebee/hello-world-imba.git
cd hello-world-imba
npm install
npm run dev

После этого перейдите в браузере по адресу http://localhost:8080/ и вы увидите главную страницу проекта. Для того чтобы модифицировать приложение — отредактируйте файл, который можно найти по адресу src/client.imba.

Если локальная установка Imba вам не подходит — можете воспользоваться интерактивной онлайн-песочницей проекта Scrimba.

Производительность Imba


Поговорим о производительности приложений, написанных на Imba. Причина, по которой Imba позволяет создавать крайне быстрые веб-приложения, заключается, в том, что этот язык не использует концепцию Virtual DOM, которая стала весьма популярной с подачи React. В Imba применяется технология Memoized DOM. Она проще, чем Virtual DOM, и использует меньше промежуточных механизмов для работы с DOM.

В этом бенчмарке, который вы можете запустить у себя, просто нажав на кнопку RUN BENCHMARK на его странице, произведено сравнения количества операций с DOM, которое можно выполнить за секунду в процессе модификации TODO-списка средствами Imba, React и Vue.

В тесте, результаты которого показаны ниже, оказалось, что Imba в 20-30 раз быстрее React и Vue. На разных компьютерах результаты теста будут различаться.


Результаты измерения производительности Imba, React и Vue

Как видите, использование Imba означает возможность крайне быстрой работы с DOM.

Итоги


В этом материале мы рассмотрели лишь самые основы Imba. Если вас этот язык заинтересовал — загляните в его документацию. В частности, полезно будет освоить его концепцию использования геттеров и сеттеров и механизм неявных вызовов. Вот список полезных ресурсов, связанных с Imba. Надо отметить, что поначалу этот язык может показаться сложным, на его освоение потребуется некоторое время, но, как всем известно, без труда не вытянешь и рыбку из пруда.

Уважаемые читатели! Планируете ли вы использовать язык Imba в своих проектах?

Комментарии (30)


  1. altrus
    05.12.2018 12:17
    +8

    Вы уверены, что если убрать из языка все открывающие-закрывающие круглые и фигурные скобки, а также закрывающие html теги, то его читабельность повышается?


    1. adictive_max
      05.12.2018 12:51
      +2

      <sarcasm>
          Но ведь это же уменьшает количество символов. Разве это не одно и то же?


    1. potan
      05.12.2018 19:43

      Мой опыт работы с Haskell говорит что да. После этого обилие пунктуации в других языках пугаетю


    1. bro-dev0
      06.12.2018 07:23

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


  1. anonymous
    05.12.2018 12:46

    Еще один… За что?

    «Один из примеров его применения — платформа, поддерживающая рыбный аукцион в Исландии.» — блин да там пара кнопок.

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


  1. nuit
    05.12.2018 12:52
    +1

    А ещё в Imba есть крутая фича как отсутствие компонентов, так что можете забыть о композиции даже на уровне реакта в 2014ом. Наконец-то вы сможете насладиться любимым ООП и наследоваться от DOM элементов :)

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

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

    — Imba: localvoid.gitlab.io/imba-dbmon/?m=0.001
    — vdom: localvoid.github.io/ivi-examples/benchmarks/dbmon-raw/?m=0.001

    Хотя нет, чота не подтверждается.


  1. AndrewTishkin
    05.12.2018 12:53

    Пример на Imba примерно в два раза короче — и по количеству строк, и по объёму кода.
    По-моему, справедливости ради, надо сравнивать ещё и длину значащих пробелов.
    Есть ли редакторы/IDE, чтобы постоянно не думать об отступах в таком языке?

    PS: у вас доступ к серверам дата-центра надолго отдохнуть прилёг? Уже не меньше двадцати минут дрыхнет
    502 — Bad Gateway. That’s an error.

    Looks like we have got an invalid response from the upstream server. That’s all we know


    1. ru_vds Автор
      05.12.2018 13:37

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

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


  1. nemilya
    05.12.2018 13:30

    Спасибо за перевод, приглядываюсь к ней.

    Кстати на scrimba.com действительно есть интересные курсы, и для начинающих (например по css), есть по Ractjs, Angular, Vue и т.п. При этом для просмотра этих «видео» не надо качать «видео поток» — демонстрация будет происходить интерактивно в браузере, и +аудио канал — что кардинально меняет «видео» туториалы (на несколько порядков меньше трафика). И конечно же можно записать любые свои туториалы, бесплатно — единственное условие всё должно происходит в рамках веб-редактора от Scrimba, и использовать css, html, js.

    ps: да, и т.к вся демонстрация происходит в рамках того же браузера — то можно остановить в любой момент и скопировать «as text» любой фрамент, что на экране (в видео туториалах такое конечно же недоступно..)


  1. vba
    05.12.2018 15:21
    +1

    Coffeescript возвращение?


  1. k12th
    05.12.2018 15:26
    +3

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


  1. faiwer
    05.12.2018 15:44
    +1

    Читал эту статью давеча. Сразу полез смотреть бенчмарк автора с тудухами, имея плохие предчувствия. И да, я не ошибся. Если так писать на Vue и React, то конечно они будут тормозить. По сути оба решения, что на Vue, что на React, у автора render-ятся целиком при каждом изменении. В случае Vue автор всё вообще записал в 1 компонент, в случае React-а там антипаттерн на антипаттерне, и вообще мои глаза… за что. Суть та же, что и у Vue, vDom всего приложения перестраивается целиком. Я даже полез было ковыряться и оптимизировать, но понял, что нужно переписать вообще всё, и в итоге забил :)


    1. nuit
      05.12.2018 15:52

      Автор пытался протестировать скорость реконсайлера и поэтому при каждом изменении всё рендерится целиком. А так да, реализация бенчмарка на реакте там какая-то совсем корявая. Года 3 назад он ещё использовал ресайклинг в реализации на Имбе и делал заявления что Имба в 40 или 60 раз быстрее Реакта, печально что чувак за эти годы так ничему и не научился.


      1. faiwer
        05.12.2018 16:05

        Автор пытался протестировать скорость реконсайлера и поэтому при каждом изменении всё рендерится целиком

        Я не думаю, что его решение на react такое кривое донельзя из-за того, что он хотел протестировать reconciler. Он просто не умеет в React. Это совершенно нормально, в этом нет ничего зазорного, пока ты не пытаешься всем доказать, что твоё решение в 10+ раз быстрее :)


        1. nuit
          05.12.2018 16:12

          У него идея в том что если мы создадим очень быстрый реконсайлер, то не нужно будет замарачиваться со всякими redux'ами/mobx'ами и можно будет просто при каждом изменении делать полный ререндер и вынимать данные откуда угодно. Поэтому он в этом бенчмарке не использует `sCU`, а делает полный ререндер. Но это только про полный ререндер, в остальном же я полностью согласен с тем что реализация на реакте оч корявая.



  1. tuxi
    05.12.2018 18:07

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


    1. potan
      05.12.2018 19:48

      Реально это мешает только в REPL. В Haskell на этот случай можно использовать фигурные скобки и ';'. К сожалению, другие языки этому примеру не последовали, в результате в тех же Idris и Elm REPL мало осмысленный.


    1. 0NotNull
      05.12.2018 19:50

      почему:
      ??вас это пугает?


      1. tuxi
        05.12.2018 23:58

        Сейчас мне удобно читать с экрана java/javascript код с 2 пробелами.
        А лет через 5..10 (судя по динамике) наверное уже с 4-мя придется иметь дело.
        Вот мой коллега, более свежего года выпуска, может наверное еще лет 20 читать хоть с отступом хоть без.
        Кстати, есть идея для нового языка: отступы же еще можно дополнить межстрочным интервалом! :-) Дарю бесплатно :)))


        1. extempl
          06.12.2018 08:46

          отступы же еще можно дополнить межстрочным интервалом

          А оно и используется в некоторых языках, насколько я знаю. Что-то вроде "между методами должна быть одна пустая строка".


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


          1. tuxi
            06.12.2018 10:32

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


  1. Pappageno
    05.12.2018 19:50

    function findGreatest(num1, num2) {
      if (num1 > num2) {
        return num1
      } else if (num2 > num1){
        return num2
      } else {
        return false
      }
    }


    Буквально недавно спрашивал про почти такое же и вот оно опять тут.

    Если уж мы пишем без скобок, то надо и писать без скобок. Что за глупые манипуляции?
    
    
    function findGreatest(num1, num2) {
      if(num1 > num2)
        return num1
      else if(num2 > num1)
        return num2
      else
        return false
    }


    function превращается в def. Ключевое слово function заменено ключевым словом def.

    И что же это дало? Да ничего, никто не пишет код в блокноте, а значит никакой разницы между function и def нет. К тому же function писать удобнее.

    Отсутствие скобок. Параметры функции не заключены в скобки.

    О да, прям отличие из отличий. Как там, num1 = 123 — оно осилит распарсить?

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

    Т.е. без скобок нельзя? Неужели это специально подобранный пример?
    Отступы. Отступы играют очень важную роль в Imba. Это означает, что фигурные скобки здесь не нужны.

    Это всяко лучше скобок, особенно с ТЗ компилишена. Зачем нам предсказуемый синтаксис — мы будем страдать.

    Отсутствие ключевого слова return.

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

    Я прям поверил.
    Imba автоматически возвращает последнее выражение функции.

    А, ну т.е. из функции может быть только один return?


    1. extempl
      06.12.2018 08:43

      А, ну т.е. из функции может быть только один return?

      Очевидно — нет. Там где функция заканчивает свою работу — там и return. Если это в первом ифе — вернётся выражение из первого ифа. Или это сарказм такой?
      И да, я не топлю за Имбу, так, наблюдения.


      1. Pappageno
        06.12.2018 10:13

        Очевидно — нет.

        Из чего это очевидно?
        Там где функция заканчивает свою работу — там и return.

        Нету такого понятия «заканчивает работу» в базовой семантике. Заканчивает работу функции ruturn, либо аналогичная конструкция. Т.е. это делается явно.

        >> Если это в первом ифе — вернётся выражение из первого ифа.
        Каким образом? Я не хочу ещё раз объяснять очевидные вещи. Вот вам функций

        function f(x) {
          if(x) return 1;
          return 2;
        }

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


        1. extempl
          06.12.2018 11:44

          Ваш последний пример подразумевает явный возврат результата в любом случае, будь то imba или, например, CoffeeScript, который так же поддерживает неявный возврат "результата последнего вычисленного выражения" (это к фразе "Нету такого понятия" (нет слова "нету", btw))


          1. Pappageno
            06.12.2018 13:21

            Я ответа на свой вопрос так и не услышал и могу констатировать необоснованные попытки критиковать мои выводы? Хорошо.

            Ваш последний пример подразумевает явный возврат результата в любом случае

            Мой пример, как и пример из статьи подразумевает два выхода из функции. Всё остальное — попытки уйти от ответа.

            который так же поддерживает неявный возврат «результата последнего вычисленного выражения»

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

            К тому же, что за попытки необоснованно опровергать мой тезис рандомной фразой. Что она опровергает? Что из неё следует? К чему это написано? Ответа нет(и не будет).

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

            который так же поддерживает неявный возврат «результата последнего вычисленного выражения

            В это фразе определяется то, что в функции нету возврата, нету такого понятия как возврат. У функции есть лишь последнее вычисленное выражение, а уже возврат — это неясная семантика. Да и вообще это совершенно другое понятие, а не возврат. Это некий „подвозврат“ т.к. он не обладает полнотой семантики базового.

            Объясню проще. Есть базовая семантика {a; b; c; d;} — в ней нет никакого возврата. То, что такой-то „язык“ взял и впилил какую-то пародию на возврат в d; — это не значит, что эта семантика стала частью базовой.


    1. Pappageno
      06.12.2018 10:20

      Я только сейчас посмотрел на код функции у которой я выкидывал скобочки. Да там манипуляции ещё похлеще скобочек.

      function findGreatest(num1, num2) {
        if(num1 > num2)
          return num1
        if(num2 > num1)
          return num2
        return false
      }

      Правильно код выше должен выглядеть так. А теперь, я думаю, что вторая манипуляция очевидна.

      Т.к. в этом «языке» нет явного return, то там попросту нельзя написать такой код. Именно поэтому родилась подобная портянка:

      def findGreatest num1, num2
          if num1 > num2
              num1
          elif num2 > num1
              num2
          else
              false
      

      Т.е. автор кортянки пытается свести логику к одному выходу через ifelse, когда как в js этого делать не нужно, ведь там может быть больше одного выхода. Но он сделал тоже самое в js, хотя подобный код — это лишь следствия слабости его «языка». А почему он так сделал? Он пытался всех обмануть.

      Это так же ответ на вопрос выше — почему не может. Именно потому, что не может быть два return и родился такой код.


  1. sanchezzzhak
    05.12.2018 20:12
    +1

    С нативным js я чувствую силу, а тут только отголоски силы.


    В стандартном js можно программировать и без скобок — стрелочными функциями, если this не нужен. lmba я не буду использовать, не люблю обертки вокруг нативного языка.
    Смотришь что это чудо нагенерировала и диву девишся. Подожду es20xx, когда сделают типизацию.


  1. zim32
    06.12.2018 12:03

    Всем смузи.за мой счёт