JavaScript. Подробное руководство, 6-е издание, стр. 105
<b>// Ниже приводится функция, принимающая три аргумента </b><b>var f = function(x,y,z) { return x * (у - z); };</b><b>// Обратите внимание на отличия между следующими тремя частичными применениями </b><b>partialLeft(f, 2)(3,4) // => -2: Свяжет первый аргумент: 2 * (3 - 4)</b><b>partialRight(f, 2)(3,4) // => 6: Свяжет последний аргумент: 3 * (4 - 2)</b><b>partial(f, undefined, 2)(3,4) // => -6: Свяжет средний аргумент: 3 * (2 - 4)</b>Эти функции частичного применения позволяют легко объявлять новые функции на основе уже имеющихся функций. Например:
<b>var increment = partialLeft(sum, 1); </b><b>var cuberoot = partialRight(Math.pow, 1/3);</b><b>String.prototype.first = partial(String.prototype.charAt, 0);</b><b>String.prototype.last = partial(String.prototype.substr, -1, 1);</b>Прием частичного применения становится еще более интересным, когда он используется в комбинации с функциями высшего порядка. Например, ниже демонстрируется еще один способ определения функции
<b>not()</b><b>var not = partialLeft(compose, function(x) { return !x; });</b><b>var even = function(x) { return x % 2 === 0; };</b><b>var odd = not(even);</b><b>var isNumber = not(isNaN)</b>Прием композиции и частичного применения можно также использовать для вычисления среднего значения и стандартного отклонения в крайне функциональном стиле:
<b>var data = [1,1.З,5,5]; // Исходные данные</b><b>var sum = function(x.y) { return x+y; }; // Две элементарные функции</b><b>var product = function(x,у) { return x*y; };</b><b>var neg = partial(product, -1); // Определения других функций</b><b>var square = partial(Math.pow, undefined, 2);</b><b>var sqrt = partial(Math.pow, undefined, .5);</b><b>var reciprocal = partial(Math.pow, undefined, -1);</b><b>// Вычислить среднее и стандартное отклонение. Далее используются только функции</b><b>// без каких либо операторов, отчего программный код начинает напоминать</b><b>// программный код на языке Lisp!</b><b>var mean = product(reduce(data, sum), reciprocal(data.length)); </b><b>var stddev = sqrt(product(reduce(map(data, compose(square,</b><b> partial(sum, neg(mean)))), sum),</b><b> reciprocal(sum(data.length,-1))));</b>8.8.4. Мемоизация
В разделе 8.4.1 была определена функция нахождения факториала, которая сохраняет ранее вычисленные результаты. В функциональном программировании такого рода кэширование называется мемоизацией (memorization). В следующем примере демонстрируется функция
<b>memoize()</b><b>// Возвращает мемоизованную версию функции f. Работает, только если все возможные </b><b>// аргументы f имеют отличающиеся строковые представления, </b><b>function memoize(f) {</b><b> var cache = {}; // Кэш значений сохраняется в замыкании, </b><b> return function() {</b><b> // Создать строковую версию массива arguments для использования </b><b> // в качестве ключа кэша.</b><b> var key = arguments.length + Array.prototype.join.call(arguments,",")</b><b> if (key in cache) return cache[key];</b><b> else return cache[key] = f.apply(this, arguments);</b><b> };</b><b>}</b>Функция
<b>memoize()</b><b>arguments</b><b>memoize():</b><b>// Возвращает наибольший общий делитель двух целых чисел, используя </b><b>// алгоритм Эвклида: </b><a href="http://en.wikipedia.org/wiki/Euclidean_algorithm"><b>http://en.wikipedia.org/wiki/Euclidean_algorithm</b></a><b>function gcd(a.b) { // Проверка типов а и b опущена</b><b> var t; // Временная переменная для обмена</b><b> if (а < b) t=b, b=a, a=t; // Убедиться, что а >= b</b><b> while(b ! = 0) t=b, b = a%b, a=t; // Это алгоритм Эвклида поиска НОД </b><b> return а;</b>