<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: A Better Javascript Un-memoizer. Part 1: Epic FAIL!</title>
	<atom:link href="http://unscriptable.com/2009/05/07/a-better-javascript-un-memoizer-part-1-epic-fail/feed/" rel="self" type="application/rss+xml" />
	<link>http://unscriptable.com/2009/05/07/a-better-javascript-un-memoizer-part-1-epic-fail/</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Wed, 25 Jan 2012 04:45:41 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: Prestaul</title>
		<link>http://unscriptable.com/2009/05/07/a-better-javascript-un-memoizer-part-1-epic-fail/#comment-73</link>
		<dc:creator>Prestaul</dc:creator>
		<pubDate>Thu, 04 Jun 2009 20:56:26 +0000</pubDate>
		<guid isPermaLink="false">http://unscriptable.com/?p=332#comment-73</guid>
		<description>I should have tested what I posted before because it really doesn&#039;t even come close to working...  But, I also think that your current versions of memoize, memoize2 and memoize3 aren&#039;t working.  You need to not only cache the result of memoizeArg when argPos &gt; 0, but also call it immediately.

Clearing the array in my previously posted code has no affect on the individual caches because of the closures that are created when memoizeArg is called.  The only solution I can come up with is to create a function closures that can clear the caches for us.  These functions get pushed into an array so that we can call them later...  I&#039;m not sure if this qualifies as &quot;better&quot;, but this code has been tested and does work.



&lt;pre&gt;
// whole-cache reset via setInterval or manual
function memoize(func, context, cacheLifetime) {
    var resetters = [],
        fn = memoizeArg(func.length - 1);
    fn.resetCache = reset;
    function reset() { 
        var i = resetters.length;
        while(i--) resetters[i]();
    };
    function memoizeArg(argPos) {
        if(!argPos &amp;&amp; cacheLifetime) {
            setInterval(reset, cacheLifetime);
            cacheLifetime = 0;
        }
        var cache = {};
        if(!argPos) resetters.push(function() { cache = {}; });
        return function() {
            var arg = arguments[argPos];
            if(argPos)
            	return (arg in cache ? cache[arg] : cache[arg] = memoizeArg(argPos - 1)).apply(null, arguments);
            else
            	return (arg in cache ? cache[arg] : cache[arg] = func.apply(context, arguments));
        };
    }
    return fn;
}
&lt;/pre&gt;

</description>
		<content:encoded><![CDATA[<p>I should have tested what I posted before because it really doesn&#8217;t even come close to working&#8230;  But, I also think that your current versions of memoize, memoize2 and memoize3 aren&#8217;t working.  You need to not only cache the result of memoizeArg when argPos &gt; 0, but also call it immediately.</p>
<p>Clearing the array in my previously posted code has no affect on the individual caches because of the closures that are created when memoizeArg is called.  The only solution I can come up with is to create a function closures that can clear the caches for us.  These functions get pushed into an array so that we can call them later&#8230;  I&#8217;m not sure if this qualifies as &#8220;better&#8221;, but this code has been tested and does work.</p>
<pre>
// whole-cache reset via setInterval or manual
function memoize(func, context, cacheLifetime) {
    var resetters = [],
        fn = memoizeArg(func.length - 1);
    fn.resetCache = reset;
    function reset() {
        var i = resetters.length;
        while(i--) resetters[i]();
    };
    function memoizeArg(argPos) {
        if(!argPos &amp;&amp; cacheLifetime) {
            setInterval(reset, cacheLifetime);
            cacheLifetime = 0;
        }
        var cache = {};
        if(!argPos) resetters.push(function() { cache = {}; });
        return function() {
            var arg = arguments[argPos];
            if(argPos)
            	return (arg in cache ? cache[arg] : cache[arg] = memoizeArg(argPos - 1)).apply(null, arguments);
            else
            	return (arg in cache ? cache[arg] : cache[arg] = func.apply(context, arguments));
        };
    }
    return fn;
}
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Prestaul</title>
		<link>http://unscriptable.com/2009/05/07/a-better-javascript-un-memoizer-part-1-epic-fail/#comment-72</link>
		<dc:creator>Prestaul</dc:creator>
		<pubDate>Wed, 03 Jun 2009 14:14:46 +0000</pubDate>
		<guid isPermaLink="false">http://unscriptable.com/?p=332#comment-72</guid>
		<description>The problem is that you have seperate caches for each closure.  Why not create a single cache array (really an array of caches)?  Caches for each argument could then be accessed by argument index, but could all be cleared by emptying a single array.  I used setInterval rather than setTimeout, assuming that usually we will want fresh data on a regular interval and not just a single refresh, and I added a check to ensure that a lifetime was passed before setting the interval.

// whole-cache reset via setInterval
function memoize (func, context, /* msec */ cacheLifetime) {
    var cache = [];
    function memoizeArg (argPos) {
        if(argPos == 0 &amp;&amp; cacheLifetime)
            setInterval(function () { cache.length = 0; }, cacheLifetime);
        var local = cache[argPos] &#124;&#124; (cache[argPos] = {});
        return function () {
            var arg = arguments[argPos];
            if (argPos == 0) {
                return arg in local ? local[arg] : local[arg] = func.apply(context, arguments);
            }
            else {
                return arg in local ? local[arg].apply(this, arguments) : local[arg] = memoizeArg(argPos - 1);
            }
        }
    }
    return memoizeArg(func.length - 1);
}


Did you have any thoughts of adding a manual method for resetting the cache?  I know this modifies the function in a way you were trying to avoid, but it is an absolute necessity in some cases:

// whole-cache reset via setInterval or manual
function memoize (func, context, /* msec */ cacheLifetime) {
    var cache = [];
    var reset = func.resetCache = function () { cache.length = 0; };
    function memoizeArg (argPos) {
        if(argPos == 0 &amp;&amp; cacheLifetime)
            setInterval(reset, cacheLifetime);
        var local = cache[argPos] &#124;&#124; (cache[argPos] = {});
        return function () {
            var arg = arguments[argPos];
            if (argPos == 0) {
                return arg in local ? local[arg] : local[arg] = func.apply(context, arguments);
            }
            else {
                return arg in local ? local[arg].apply(this, arguments) : local[arg] = memoizeArg(argPos - 1);
            }
        }
    }
    return memoizeArg(func.length - 1);
}

var fn = memoize(function(v) { return v; });
fn.resetCache();</description>
		<content:encoded><![CDATA[<p>The problem is that you have seperate caches for each closure.  Why not create a single cache array (really an array of caches)?  Caches for each argument could then be accessed by argument index, but could all be cleared by emptying a single array.  I used setInterval rather than setTimeout, assuming that usually we will want fresh data on a regular interval and not just a single refresh, and I added a check to ensure that a lifetime was passed before setting the interval.</p>
<p>// whole-cache reset via setInterval<br />
function memoize (func, context, /* msec */ cacheLifetime) {<br />
    var cache = [];<br />
    function memoizeArg (argPos) {<br />
        if(argPos == 0 &amp;&amp; cacheLifetime)<br />
            setInterval(function () { cache.length = 0; }, cacheLifetime);<br />
        var local = cache[argPos] || (cache[argPos] = {});<br />
        return function () {<br />
            var arg = arguments[argPos];<br />
            if (argPos == 0) {<br />
                return arg in local ? local[arg] : local[arg] = func.apply(context, arguments);<br />
            }<br />
            else {<br />
                return arg in local ? local[arg].apply(this, arguments) : local[arg] = memoizeArg(argPos &#8211; 1);<br />
            }<br />
        }<br />
    }<br />
    return memoizeArg(func.length &#8211; 1);<br />
}</p>
<p>Did you have any thoughts of adding a manual method for resetting the cache?  I know this modifies the function in a way you were trying to avoid, but it is an absolute necessity in some cases:</p>
<p>// whole-cache reset via setInterval or manual<br />
function memoize (func, context, /* msec */ cacheLifetime) {<br />
    var cache = [];<br />
    var reset = func.resetCache = function () { cache.length = 0; };<br />
    function memoizeArg (argPos) {<br />
        if(argPos == 0 &amp;&amp; cacheLifetime)<br />
            setInterval(reset, cacheLifetime);<br />
        var local = cache[argPos] || (cache[argPos] = {});<br />
        return function () {<br />
            var arg = arguments[argPos];<br />
            if (argPos == 0) {<br />
                return arg in local ? local[arg] : local[arg] = func.apply(context, arguments);<br />
            }<br />
            else {<br />
                return arg in local ? local[arg].apply(this, arguments) : local[arg] = memoizeArg(argPos &#8211; 1);<br />
            }<br />
        }<br />
    }<br />
    return memoizeArg(func.length &#8211; 1);<br />
}</p>
<p>var fn = memoize(function(v) { return v; });<br />
fn.resetCache();</p>
]]></content:encoded>
	</item>
</channel>
</rss>

