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