I am trying to optimise the usage of a function to check whether a number is prime or not.
I have written the following function:
function isPrime(num) {
var start = 2;
// code to check whether num has already been checked for Prime
while(start <= Math.sqrt(num)) {
if (num % start++ < 1) {
return false;
}
}
return num > 1;
}
However, before the execution of my while loop I want to check if a number already has been passed through my isPrime function, so that I can return whether it is prime or not without having to execute the while loop.
Note, I want to do this without the usage of a global variable or without extending Object.prototype.
You can use the technique of Memoization .
Memoization is a programming technique which attempts to increase a function’s performance by caching its previously computed results.
The basic idea is that we build a empty Object and then add Keys as the hash value or the argument value and then if we get a argument which is already available on the Object keys then we return the Object value for that key.
There are several variation of the below function, but this one performs much better then other implementation. A code Snippet Taken from Addy Osmani article here .
function memoize( fn ) {
return function () {
var args = Array.prototype.slice.call(arguments),
hash = "",
i = args.length;
currentArg = null;
while (i--) {
currentArg = args[i];
hash += (currentArg === Object(currentArg)) ?
JSON.stringify(currentArg) : currentArg;
fn.memoize || (fn.memoize = {});
}
return (hash in fn.memoize) ? fn.memoize[hash] :
fn.memoize[hash] = fn.apply(this, args);
};
}
Usage:
var cachedIsPrime = memoize(isPrime);
var isPrime = cachedIsPrime(2);
isPrime = cachedIsPrime(3);
And then you can pass the function which needs to be Memoized.
OP Notes:
For the above context with a single argument, a simple memoize function like the following does work:
var memoize = function(passedFunc) {
var cache = {};
return function(x) {
if (x in cache) return cache[x];
return cache[x] = passedFunc(x);
};
};
Declare the variable inside an IIFE to create a closure.
var isPrime = (function () {
var checked_numbers = [];
function isPrime(num) { ... }
return isPrime;
}();
checked_numbers is in scope for the returned isPrime function (which is accessible outside the IIFE because it (the function itself) is assigned to a global variable), but nothing outside the IIFE can touch it.
What you are looking for is the memoization pattern.
From Wikipedia:
In computing, memoization is an optimization technique
used primarily to speed up computer programs by storing the results of
expensive function calls and returning the cached result when the same
inputs occur again.
You can write your own memoize function (as suggested by the other answers) or you can use one of the many optimized and well-tested implementations available on npm, like fast-memoize.js or memoizee. If you already use Lodash, it also has its own _.memoize function.
Example:
var isPrime = memoize(/* your function */)
isPrime(2) // => true
isPrime(2) // => true (from the cache)
Related
I am having multiple problems with this function. It's part of a bonus question for a Data Structures and Algorithms class and I've invested so much time in this one problem, that I'd really like to get it to work and understand what's going on.
There is one main problem, which has caused several little ones...this problem's name is JavaScript. We've never programmed in JavaScript before, but for some reason we have to use it.
The function has to pass tests (this one and fibonacci), which are structured like this:
var fn = (n) => 2 * n
var m_fn = memoize(fn)
expect(m_fn(18)).to.equal(fn(18))
So I have to pass the function I want to memoize as a parameter of the memoize function and the memoize function has to return a function. I am not allowed to do it any other way.
I did all of the reading and researched the memoize function, but all of the implementations take a different approach.
Basically, I understand what I have to do, but I don't quite understand HOW. I know what the memoize function should do, but I don't understand how to adjust the original function using my memoize function. This is what I have so far/what I don't have:
I know it's wrong. But I think I'm missing something major. I am supposed to return a function, but I am returning values...
In the test, it's writen var m_fn = memoize(fn), so the memoize function passes fn, then returns a new function, but in my memoize, I am returning values for fn(n), so I AM doing something wrong...
/**
* Creates a memoized version of the function fn. It is assumed that fn is a referentially transparent
* function.
* #param {function} fn Some referentially transparent function that takes a basic datatype (i.e. number / string)
* #returns {function} A new function that is the memoized version of fn. It never calculates the result of
* a function twice.
*/
memoize: (fn) => { //here we enter the function that we want to memoize
var memory = []; //we need to create an array to hold the previously calculated values, length n (parameter of fn)
if(this.n > memory.length){ //Check to see if this particular value is in the array already.
return memory[this.n]; //How do I access the integer parameter that was passed through fn though? Is this correct?
} else{ // if not, we want to save it and return it
var result = fn(this.n);
memory.push(result);
return result;
}
}
Indeed, you need to return a function.
Secondly, an array is not the ideal structure for memory, because it takes linear time to find an argument value in it. I would suggest to use a Map for this, which is ideal for such purposes. It has has(), get() and set() methods which run in near-constant time:
function memoize(fn) {
var memory = new Map();
return function(arg) {
if (memory.has(arg)) {
console.log('using memory');
return memory.get(arg);
} else {
var result = fn(arg);
memory.set(arg, result);
return result;
}
};
}
var fn = (n) => 2 * n
var m_fn = memoize(fn)
console.log(fn(18));
console.log(m_fn(18));
console.log(m_fn(18)); // outputs also "using memory"
You could use a Map as memory.
var memoize = f =>
(map => v => (!map.has(v) && map.set(v, f(v)), map.get(v)))(new Map),
fn = (n) => 2 * n,
m_fn = memoize(fn);
console.log(m_fn(18), fn(18));
Looking at your code and in-code comments and assuming I'm interpreting correctly, you're really close to the solution. As you've said in the question, you need to return a function that returns the values rather than returning the values.
See comments for explanation:
function memoize(f) {
// An array in which to remember objects with the input arg and result
var memory = [];
// This is the function that will use that array; this is the
// return value of memoize
return function(arg) {
// This code runs when the function returned by memoize is called
// It's *here* that we want to process the argument, check the `memory`
// array, call `f` if necessary, etc.
var entry;
// See if we have a previously-saved result for `arg`
var entry = memory.find(entry => entry.arg === arg);
if (!entry) {
// No -- call `fn`, remember the `arg` and result in an object
// we store in memory``
entry = {arg, result: f(arg)};
memory.push(entry);
}
// We have it (now), return the result
return entry.result;
};
}
function fn(arg) {
console.log("fn called with " + arg);
return 2 * arg;
}
var m_fn = memoize(fn);
console.log(m_fn(18));
console.log(m_fn(18));
console.log(m_fn(20));
console.log(m_fn(20));
Note: There was an arrow function in your code, so I've assumed it's okay to use ES2015 features above. There's not actually very much of it, though, just the arrow function passed to memory.find, the assumption that Array#find will be available, and the syntax used to create the entry object (in ES5 we' need entry = {arg: arg, result: f(arg)} instead).
Note that if we can assume that arg will be a string or number or other value that can reliably be converted to string, we can use an object to store the data rather than an array.
And actually, given this is ES2015, we can use a Map:
function memoize(f) {
// An Map in which to remember objects with the input arg and result
const memory = new Map();
// This is the function that will use that array; this is the
// return value of memoize
return function(arg) {
// This code runs when the function returned by memoize is called
// It's *here* that we want to process the argument, check the `memory`
// array, call `f` if necessary, etc.
let result;
// See if we have a previously-saved result for `arg`
if (!memory.has(arg)) {
// No -- call `fn`, remember the `arg` and result in an object
// we store in memory``
result = f(arg);
memory.set(arg, result);
} else {
// Yes, get it
result = memory.get(arg);
}
// We have it (now), return the result
return result;
};
}
function fn(arg) {
console.log("fn called with " + arg);
return 2 * arg;
}
var m_fn = memoize(fn);
console.log(m_fn(18));
console.log(m_fn(18));
console.log(m_fn(20));
console.log(m_fn(20));
Note that in both cases, I've written the code verbosely to allow for comments and easy comprehension. The ES2015 version with Map, in particular, can be quite a lot shorter.
I'm getting around to learning JavaScript - really learning JavaScript. I come from a PHP background so some JavaScript concepts are still new to me, especially asynchronous programming. This question might have already been answered many times before but I have not been able to find an answer. It might be because I don't really even know how to ask the question other than by showing an example. So here it is:
When using the deferred package from npm, I see the following example:
delayedAdd(2, 3)(function (result) {
return result * result
})(function (result) {
console.log(result); // 25
});
They refer to this as chaining and it actually works as I'm currently using this code to check when a promise is resolved or is rejected. Even though they call it chaining, it reminds me of trailing closures like in Swift.
I don't really understand what type of chaining this is since we have a function invocation and then immediately after, an anonymous function enclosed in parentheses.
So I guess I have two questions.
What pattern is this?
How does it work? This may be a loaded question but I like to know how something works so when someone asks me about this I can give them a detailed explanation.
Here is the delayedAdd function:
var delayedAdd = delay(function (a, b) {
return a + b;
}, 100);
which uses the following function:
var delay = function (fn, timeout) {
return function () {
var def = deferred(), self = this, args = arguments;
setTimeout(function () {
var value;
try {
value = fn.apply(self, args));
} catch (e) {
def.reject(e);
return;
}
def.resolve(value);
}, timeout);
return def.promise;
};
};
It's actually really easy to understand. Let's look at what's going on here when the expression is evaluated:
First the delayedAdd(2, 3) function will be called. It does some stuff and then returns. The "magic" is all about its return value which is a function. To be more precise it's a function that expects at least one argument (I'll get back to that).
Now that we evaluated delayedAdd(2, 3) to a function we get to the next part of the code, which is the opening parenthesis. Opening and closing parenthesis are of course function calls. So we're going to call the function that delayedAdd(2, 3) just returned and we're going to pass it an argument, which is what gets defined next:
That argument is yet another function (as you can see in your example). This function also takes one argument (the result of the computation) and returns it multiplied by itself.
This function that was returned by the first call to delayedAdd(2, 3) returns yet another function, which we'll call again with an argument that is another function (the next part of the chain).
So to summarize we build up a chain of functions by passing our code to whatever function delayedAdd(2, 3) returned. These functions will return other functions that we can pass our functions again.
I hope this makes the way it works somewhat clear, if not feel free to ask more.
mhlz's answer is very clear. As a supplementary, here I compose a delayedAdd for your to better understand the process
function delayedAdd(a, b) {
var sum = a + b
return function(f1) {
var result1 = f1(sum)
return function(f2) {
f2(result1)
}
}
}
Where in your example code, the function you passed as f1 is:
function (result) {
return result * result
}
and f2 is:
function (result) {
console.log(result)
}
Functions are first-class citizens in JS - that means (among others), they can take the role of actual parameters and function return values. Your code fragment maps functions to functions.
The signatures of the functions in your chained call might look like this.
delayedAdd: number -> fn // returns function type a
a: fn ( number -> number) -> fn // returns function type b
b: fn ( number -> void ) -> void // returns nothing ( guessing, cannot know from your code portion )
General setting
Of course, JS is a weakly typed language, so the listed signatures are derived from the code fragment by guessing. There is no way to know whether the code actually does what is suggested above apart from inspecting the sources.
Given that this showed up in the context of 'chaining', the signatures probably rather look like this:
delayedAdd: number x number -> fn (( fn T -> void ) -> ( fn T -> void ))
Which means that delayedAdd maps two numbers to a function x, which maps functions of arbitrary signatures to functions of the same signature as itself.
So who would do anything like this ? And why ?
Imagine the following implementation of x:
//
// x
// Collects functions of unspecified (possibly implicit) signatures for later execution.
// Illustrative purpose only, do not use in production code.
//
// Assumes
function x ( fn ) {
var fn_current;
if (this.deferred === undefined) {
this.deferred = [];
}
if (fn === undefined) {
// apply functions
while ( this.deferred.length > 0 ) {
fn_current = this.deferred.shift();
this.accumulator = fn_current(this.accumulator);
}
return this.accumulator;
}
else {
this.deferred.push ( fn );
}
return this;
}
Together with a function delayedAdd that actually returns an object of the following kind ...:
function delayedAdd ( a1, a2) {
return x ( function () { a1 + a2; } );
}
... you'll effectively register a chain of functions to be executed at some later point of time (e.g. in a callback to some event).
Notes and reminders
JS functions are JS objects
The signatures of the registered functions may actually be arbitrary. Considering them to be unified just serves to keep this exposition simpler (well ...).
Caveat
I do not know whether the outlined codeis what node.js does (but it could be ... ;-))
To be fair this pattern can be either chaining or currying(or partial application). Depending how it's implemented. Note this is a theoretical answer to provide more information about the pattern and not your specific use case.
Chaining
There is nothing special here because we can just return a function that will be called again. Functions in javascript are first class citizens
function delayedAdd(x, y) {
// In here work with x and y
return function(fn) {
// In here work with x, y and fn
return function(fn2) {
//Continue returning functions so long as you want the chain to work
}
}
}
This make it unreadable in my opinion. There is a better alternative.
function delayedAdd(x, y) {
// In here work with x and y
return {
then: function(fn) {
// In here work with x, y and fn
return {
then: function(fn2) {
//Continue returning functions so long as you want the chain to work
}
}
}
}
}
This changes the way your functions are called from
delayedAdd(..)(..)(..); // 25
is transformed to
delayedAdd().then().then()
Not only is more readable when you are passing several callback functions but allows a distinction from the next pattern called currying.
Currying
The term cames after the mathematician Haskell Curry. The definition is this
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application). It was introduced by Moses Schönfinkel and later developed by Haskell Curry.
Basically what it does is take several arguments and merge with the subsecuents and apply them to the original function passed in the first argument.
This is a generic implementation of this function taken from Stefanv's Javascript Patterns.
{Edit}
I changed my previous version of the function to one which has partial application included to make a better example. In this version you must call the function with no argument to get the value returned or you will get another partially applied function as result. This is a very basic example, a more complete one can be found on this post.
function schonfinkelize(fn) {
var slice = Array.prototype.slice,
stored_args = [],
partial = function () {
if (arguments.length === 0){
return fn.apply(null, stored_args);
} else {
stored_args = stored_args.concat(slice.call(arguments));
return partial;
}
};
return partial;
}
This are the results of the application of this function
function add(a, b, c, d, e) {
return a + b + c + d + e;
}
schonfinkelize(add)(1, 2, 3)(5, 5)(); ==> 16
Note that add (or in your case delayedAdd) can be implemented as the curying function resulting in the pattern of your example giving you this
delayedAdd(..)(..)(..); // 16
Summary
You can not reach a conclusion about the pattern just by looking at the way the functions are called. Just because you can invoke one after the other it doens't mean is chaining. It could be another pattern. That depends on the implementation of the function.
All excellent answers here, especially #mhlz and #Leo, I'd like to touch on the chaining part you've mentioned. Leo's example shows the idea of calling functions like foo()()() but only works for fixed number of callbacks. Here's an attempt to imlpement unlimited chaining:
delayedAdd = function da(a, b){
// a function was passed: call it on the result
if( typeof a == "function" ){
this.result = a( this.result )
}
else {
// the initial call with two numbers, no additional checks for clarity.
this.result = a + b;
}
// return this very function
return da;
};
Now you can chain any number of functions in () after the first call:
// define some functions:
var square = function( number ){ return number * number; }
var add10 = function( number ){ return number + 10; }
var times2 = function( number ){ return number * 2; }
var whatIs = function( number ){ console.log( number ); return number; }
// chain them all!
delayedAdd(2, 3)(square)(whatIs)(add10)(whatIs)(times2)(whatIs);
// logs 23, 35 and 70 in the console.
http://jsfiddle.net/rm9nkjt8/3/
If we expand this syntax logically we would reach something like this:
var func1 = delayedAdd(2, 3);
var func2 = function (result) {
return result * result
};
var func3 = function (result) {
console.log(result);
};
var res = func1(func2); // variable 'res' is of type 'function'
res(func3);
I have the following code
var arr = [];
$("#Target").click(function () {
function Stuff() {
console.log("Dummy");
}
var found = false;
for (var i = 0; i < arr.length; i++) {
found = found || arr[i] == Stuff;
}
if (!found)
arr.push(Stuff);
alert(arr.length);
});
Each time I click the button it increases the count of the array. However, if I modify the code like this
function Stuff() {
console.log("Dummy");
}
var arr = [];
$("#Target").click(function () {
var found = false;
for (var i = 0; i < arr.length; i++) {
found = found || arr[i] == Stuff;
}
if (!found)
arr.push(Stuff);
alert(arr.length);
});
It detects the equality and array contains 1 element at max. What is happening here is that each time click event is fired, anonymous handler is instantiated again, so is Stuff function.
In the first code block anonymous function is instantiated each time the event fired. In the second code block, as the Stuff function is a global function (read "property of a window object") it is not instantiated.
My question is, is there an established way of testing equality of this kind of functions?
PS: I know that there is a workaround like
arr[i].toString() == Stuff.toString();
But I want to restrain this kind of "wizardry"
Edit
A bit more details: I want to create a function
$.throttle = function(func, delay){
// Here I need to check whether this function was already passed,
// and if yes, I need to clear previous timeout and create new
}
and it may be called like this
$.throttle(function () { console.log("Foo"); }, 5000);
What is happening here is that each time click event is fired anonymous handler is instantiated again, so is Stuff function.
No, that's not what's happening in your second code block. Each time click fires, the same Stuff function is pushed onto the array; the anonymous function is just run by the click handler, not instantiated by it. (It's instantiated by the code hooking up the click handler.)
If you have two references to a function and want to know if they refer to the same function, you can compare them with === or ==:
var ref1 = Stuff;
var ref2 = Stuff;
console.log(ref1 === ref2); // true
console.log(ref1 === Stuff); // true
console.log(ref2 === Stuff); // true
If you want to create two different copies of a function (as in your first code block) and see if they have the same code, there's no official way to do that. You can compare the result of toString as you've pointed out (although the spec doesn't actually require toString to return code), but while that will compare their code content (if it works), it won't compare their context. Consider:
function foo(bar) {
return function() {
alert(bar);
};
}
var f1 = foo("one");
var f2 = foo("two");
f1(); // alerts "one"
f2(); // alerts "two"
console.log(f1.toString() === f2.toString()); // true
The functions we got back from calling foo have the same code in them, but they are not equivalent functions. As far as I'm aware, there is no standard way of comparing functions for equivalence, only for identity.
Functions (in JavaScript) are Objects (function () {}) instanceof Object, and equality of Objects is done ByRef, i.e. identical is not equal
If you want to do something like you describe, you need to have a closure over the reference so you can access it, perhaps you want something like this
var arr = [];
$("#Target").click((function () {
function Stuff() {
console.log("Dummy");
}
return function () {
var found = false;
for (var i = 0; i < arr.length; i++) {
found = found || arr[i] == Stuff;
}
if (!found)
arr.push(Stuff);
alert(arr.length);
};
}()); // note IIFE execution
What's different here? Stuff is only created once, but it is used by the returned function which becomes the click handler
If you want to pass in abstract functions which may have been defined elsewhere, you can do it as parameters/args to the IIFE
function foo() {
// ...
}
$("#Target").click((function (Stuff) {
return function () {
// `foo` is called `Stuff` here
};
}(foo));
I've read
http://www.sitepoint.com/implementing-memoization-in-javascript/
Automatic Memoization
In all of the previous examples, the functions were explicitly modified to add memoization. It is also possible to implement a memoization infrastructure without modifying the functions at all. This is useful because it allows the function logic to be implemented separately from the memoization logic. This is done by creating a utility function which takes a function as input and applies memoization to it. The following memoize() function takes a function, “func”, as input. memoize() returns a new function which wraps a caching mechanism around “func”. Note that this function does not handle object arguments. In order to handle objects, a loop is required which would inspect each argument individually and stringify as needed.
function memoize(func) {
var memo = {};
var slice = Array.prototype.slice;
return function() {
var args = slice.call(arguments);
if (args in memo)
return memo[args];
else
return (memo[args] = func.apply(this, args));
}
}
using this, I did
var fib = function(n)
{
if (n <= 1)
{
return 1; // as the Fib definition in Math
}
else
{
return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
}
};
log(memoize(fib)(43));
log(fib(43));
However, I confirmed there's no effect.
I also tried a npm library for the same purpose,
https://github.com/medikoo/memoize
and
var memoize = require('memoizee');
log(memoize(fib)(43));
log(fib(43));
The result, same.
What do I miss, and how to fix and make it work?
Thanks!
EDIT
require('memoizee');
var fib = function(n)
{
if (n <= 1)
{
return 1; // as the Fib definition in Math
}
else
{
return fib(n - 2) + fib(n - 1); // as the Fib definition in Math
}
};
var generator = function(f)
{
return memoize(f);
};
var _fib = generator(fib);
console.log(_fib(40)); //no effect
The memoize call does not alter the fib function, but returns its new, memoized counterpart. In your code, you're calling that one only once, and the original fib function the next time. You need to create one memoized "wrapper", and call that multiple times:
var mFib = memoize(fib);
log(mFib(43));
log(mFib(43));
You could also overwrite the original fib = memoize(fib);, which would have the additional benefit that the recursive calls (which are the interesting ones) will be memoized as well.
I'm wondering if there is a way to implement a generic "memoize" functional (as in a function with a function as input and a function as output, as python's decorators) capable of handling also cps-style functions.
for a normal function (as in "the result value comes back by the return, the parameters are only for input!") a memoize function can be as simple as (in javascript)
function memoize(fun) {
var cache = {};
return function () {
var args = Array.prototype.slice.call(arguments);
if (args in cache)
return cache[args];
var ret = fun.apply(this, arguments);
cache[args] = ret;
return ret;
};
}
but a cps-style function cannot be memoized by my simple memoize function, cause I need to evaluate "again" the arguments of type function, knowing also the parameter to pass to them.
For example, given the function
function cps(param, next) {
var ret = param + 1;
// setTimeout for simulate async behaviour
setTimeout(function () {
next(ret);
}, 0);
}
maybe I can find that next is a function, but its signature (well... maybe, but it's tricky), and definitely not the parameters used in the function!
Can someone tell me I'm wrong? :D
I'm interested to be able to memoize an half dozen of cps-style functions and I don't want to mess with the logic inserting a "cache" in every one of them.
I'm new to CPS, but I think you'll have to construct your functions in a particular way.
Your CPS functions have the following structure (generalising from your example):
function cps(param, next) {
var ret = someFunctionOfParam(param);
// setTimeout for simulate async behaviour
setTimeout(function () {
next(ret);
}, 0);
}
So, you could use your standard memoizer, and construct the CPS function as well. Keeping this separate for the sake of it, first the CPS-maker (assumes the last argument for the functions is always the function to pass to):
function cpsMaker(transformFunc) {
return function() {
var args = Array.prototype.slice.call(arguments);
var next = args.pop(); // assume final arg is function to call
var ret = transformFunc.apply(this,args);
// setTimeout for simulate async behaviour
setTimeout(function () {
next(ret);
}, 0);
}
}
And then the memoizer can be used in conjunction with it:
function plusOne(val) {
return val+1;
}
var memoPlusOne = memoize(plusOne);
var cpsMemPlusOne = cpsMaker(memoPlusOne);
cpsMemPlusOne(3,function(n){console.log(n)});
The point is to separate the memoization of the transform from the CPS construction.
Thank you for introducing the idea of memoized CPS; even if this answer is rubbish, it has been an eye-opener for me!