Számítás önmagukat felüldefiniáló és memoizációt használó JavaScript függvényekkel
Ádám majd úgy is ki fog javítani, hogy ezeket hogyan lehetne magyarul írni: self defining function és memoization. Mindenesetre felmerült a probléma, hogy hogyan lehetne optimalizálni rekurzív függvényeket, úgy hogy egyfajta iterátorként is működhessenek. Ehhez írtam egy nagyszerű kis függvényt, ami a Fibonacci-sort számítja ki, de kicsit érdekesen. Ami meglepő lehet, hogy a függvény az első sorban felüldefiniálja és bővíti magát pár tulajdonsággal és metódussal. Például gyorstárazza a már eddig kiszámolt értékeket, mindezt egy hordozható formában.
Várom róla a véleményeket:
/**
* Kiszámolja az n. Fibonacci-számot.
*
* @param {Number} n
* Az a természetes szám, amelyik elemre a Fibonacci-sorban szükségünk van.
* @return {Number}
* Az n. Fibonacci-szám.
*/
function fib(n) {
/**
* Felüldefiniáljuk a függvényünket, mely visszaadja az n. Fibonacci-számot.
*/
fib = function (n) {
if (fib.cache[n] === undefined) {
fib.cache[n] = fib(n - 1) + fib(n - 2);
}
return fib.cache[n];
}
// Bővítjük saját tulajdonsággal és metódussal.
fib.cache = [0, 1];
/**
* A következő nem gyorsítótárazott Fibonacci-számot számolja ki.
*
* @return {Number}
* A következő még ki nem számított Fibonacci-szám.
*/
fib.next = function () {
return fib(fib.cache.length);
}
return fib(n);
}
(function(n) {
// Lekérdezzük a 0. elemet.
fib(0);
while (n--) {
// Meghívjuk a next metódust 10-szer.
console.log(fib.next());
}
console.log('A 20. Fibonacci-szám:', fib(20));
}(10));
Kimenet:
1 2 3 5 8 13 21 34 55 89 A 20. Fibonacci szám: 6765
Ezeket általában úgy szokás,
Egyébként én mindegyszerűen öníró (nektek öndefiniáló) függvényeknek nevezném őket. A memoizációra akadémiai körökben lehet, hogy létezik már valamilyen szép magyar fordítás, én hirtelenjében mondjuk az emlékező függvényt adnám nekik a keresztségben.
Gyorsítás
Hát igazából ez egy tervezési minta, amivel az inicializálást és ellenőrzést lehet elkerülni. A lényeg, hogy egészen addig nem történik meg a függvény előkészítése, amíg meg nem hívódik. Ezzel memóriát, illetve amennyiben az inicializáció költséges akkor teljesítményt javíthatunk. Amennyiben a függvényünket nem hívják meg, az inicializáció se fut le feleslegesen. És igen a függvényben minden egyes futáskor nem kell ellenőrizni, hogy megtörtént-e már az inicializáció, mert ebben biztosak lehetünk.
Ugyanakkor vannak más tényezők is. Például idegen kód törölheti a gyorsítótárunkat, de erre felkészülhetünk, ha hozzáadunk a függvényhez egy
init
metódust, ami elvégzi az újbóli inicializációt, és így konzisztens maradhat a működés, és a gyorsítótár is üríthető, amennyiben a működés azt megkívánja.Például:
Príma
Böngésző független eseménykezelés
Érdekes megoldás, én ezt alap
Ezért jó nevet adni a
A memoizálásban az a szép,
fun
De, persze.
Yepp, innentől meg ugyanott
Inicializálás…
var myFun = (fib(0), fib);
init csak egyszer
Hasznos cucc, már fel is