...

суббота, 31 августа 2013 г.

Строковая интерполяция. Сказка-быль

Постановка задачи




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

'hello, %(thing)s' % {'thing': 'world'}




Или вот так:

'hello, {thing}'.format(**{'thing': 'world'})








Ближайший аналог в JS — конкатенация (operator +), которая очень плохо масштабируется с увеличением длины строки, да еще и выглядит безобразно до предела:

'<div class="input-append"><input type="text" name="username" '+
'id="signup_username" placeholder="'+placeholder+'"><input '+
'type="hidden" name="password" value="'+generated+'"><button '+
...




По возможности хотелось бы этого избежать.

Jeremy Ashkenas, когда разрабатывал CoffeeScript, также обратил на эту особенность JS внимание, и случайно диалект PHP:



"hello, #{document.cookie}"




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

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



– написать функцию

– которая подставляет переменные в строку

– загруженную из файла

– не PHP





Поиск решения




Обычно в таких случаях используют готовые библиотеки, более того, в NPM по слову template находится более двух тысяч пакетов.

В самом деле, mustache или lodash (underscore.js) работают превосходно, но… очень медленно: 10-20 мкс на одну подстановку. Не предел мечтаний ни в коем случае, особенно когда «продвинутый» функционал вроде циклов и фильтров совершенно не нужен.


А конкатенация, хоть и выглядит страшно, как звериный оскал коллективизма, работает все-таки в 10-30 раз быстрее. Таким образом, мы добавляем к постановке задачи:



– транслируется в конкатенацию

– и работает очень быстро





Вот теперь по этой спецификации можно изобретать велосипед. Because why not.

Что получилось




У меня получилась вот такая штука: Ruby-like simple string interpolation (GitHub)

В ней 9 строк кода, и она выполняет миллион триста тысяч подстановок в секунду (около 0,77 мкс на подстановку) на той же машине, где mustache делает 130 тысяч, а lodash/underscore 45 тысяч подстановок в секунду.


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


RSSI.js можно установить из npm очевидной командой npm install rssi, поддерживается также Bower (bower install rssi); на стороне клиента можно использовать AMD (RequireJS), а можно не использовать.



Спасибо за прочитывание этого не очень связного текста! Пишите патчи, господа хорошие, и до новых встреч.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий