Частичное применение функций
Еще одна идея, которая пришла из функционального программирования, и может быть очень полезной, если уметь ее правильно готовить.
В качестве примера мы будем создавать DOM элементы.
(Прим. переводчика: cull.dom — библиотека, автора, которую он создавал для одного из проектов. Но функции в ней очевидны и просты.)
var ul = cull.dom.el("ul"); //document.createElement("ul")
ul.nodeType === 1 // true
Также можно задавать атрибуты свойств.
var ul = cull.dom.el("ul", {className: "bands"});
И указывать дочерние элементы
var li = cull.dom.el("li", "Tom Waits");
var ul = cull.dom.el("ul", {className: "bands"}, li);
Если их использовать друг внутри друга, можно получить некое подобие DSL для HTML.
va ul = cull.dom.el("ul", className:"bands"},
cull.dom.el("li", "Tom Waits"));
А теперь все-таки приступим к обсуждению частичного применения функций. Помните один из первых примеров?
function makeAdder(base){
return function(num){
return base + num;
}
}
Он возвращает функцию, которая будет суммировать два числа. Естественно, при необходимости мы можем использовать именованные функции.
function makeAdder(base){
return function(num){
return add(base, num);
}
}
И теперь мы видим, что функция makeAdder берет функцию add и фиксирует один из ее аргументов. Вы получаете функцию сложения, в которой один из аргументов — константа
var add2 = cull.partial(add, 2);
add2(5); //7
Теперь мы получили достаточно интересную возможность — сделать наш DSL по созданию DOM элементов еще красивее.
var ul = cull.partial(cull.dom.el, "ul");
var li = cull.partial(cull.dom.el, "li");
И можем строить HTML списки приблизительно так
var list = ul({className: "bands"},
[li("Diamanda Galas"),
li("Руки вверх"),
li("John Zorn")]);
Если вы как и я, не любите программировать на уровне строковых переменных — это отличный способ упростить себе жизнь. У вас теперь будет работать автодополнение кода, и другие приятные вещи. А еще ваш код очень похож на обычный HTML.
И поскольку наш подход достаточно красив, мы можем создать функции для всех элементов документа заранее:
["a", "br", "code", "div", ...].forEach(function(tagName){
cull.dom.el[tagName] = cull.partial(cull.dom.el, tagName);
});
Таким образом, мы создадим функцию для каждого HTML элемента.
Конечно, пространство имен не всегда удобно использовать полностью, поэтому будем упрощать еще дальше.
var e = cull.dom.el;
var list = ul({className: "bands"},
[e.li("Pan Sonic"),
e.li("Веня Дркин"),
e.li("Muslimgauze")]);
Теперь мы не завязаны на глобальные переменные и функции, что хорошо.