Interesting recursive lambda example - javascript

I just stumbled upon an interesting example of recursive lambdas and I don't really understand why it works in this manner.
rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec
rec = lambda x: x+1
print(f(10))
Same in javascript.
var rec = function(a) {
if (a == 0) return 1;
return rec(a - 1) * a;
}
var f = rec
rec = function(a) {
return a + 1;
}
console.log(f(10));
To my surprise both of these print 100 instead of 10! (as I would expect).
Why does the reassignment of rec change the behavior of the f function? When the rec variable is captured in lambda, doesn't it refer to the lambda itself?
Edit.
As most of the answers explain what is going on, let me rephrase the question because I am looking for a more in depth explanation.
So at the moment of the declaration of the function rec in the first line why doesn't the rec in the body of the function bind to itself?
For example if you take JavaScript and rewrite the first line in a seemingly "same" way as suggested in one of the answers you get:
var rec =function rec(a) {
if (a == 0) return 1;
return rec(a - 1) * a;
};
f = rec;
rec = function (a) {
return a + 1;
}
console.log(f(10));
This one prints out 10! as one would expect.
So in this case the "inner rec"(in the function body) binds to the rec of the function-name instead of looking at rec variable and the reassignment of the variable rec didn't change the behavior.
So what I am really asking is the mechanism by which those languages decide what to bind the variables in the lambdas.
I am writing an interpreter myself for a class project and I came across to the same question of when and where to bind those variables. So I wanted to understand how this works in popular languages to implement something similar.

I will address it for python because that is what i am familiar with.
First, this behaviour is only possible because python (and looks like javascript i presume) follows late-binding for their closures. further read
Late binding is when the names within a closure are looked up at runtime (unlike early binding where the names are looked up at compile time.)
What this allows is to mutate behaviours at run time, by rebinding variables that are being looked up at runtime(such as functions like rec).
The last step then is just converting the lambda functions into equivalent def syntax so the real behaviour is clearer.
The code:
rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec
rec = lambda x: x+1
print(f(10))
Can be equivalent to:
First:
def somefunc(x):
return 1 if x==0 else rec(x-1)*x
Note, python will not complain about rec not existing even on a clean session/kernel because it does not look the value up during function definition. late binding means unless this function is called, python does not care about what rec is.
Then:
rec = somefunc
f = rec
def someotherfunc(x):
return x + 1
f(10) #3628800
Now we change the rec function
rec = someotherfunc
And observe that subsequent function calls of f will use the late-bound rec, that is looked up on the function call.
f(10) #100
PS. Complete code added below:
def somefunc(x):
return 1 if x==0 else rec(x-1)*x
rec = somefunc
f = rec
def someotherfunc(x):
return x + 1
f(10) #3628800
rec = someotherfunc
f(10) #100

You could add some console.log and view, that first f is called with 10, then rec with 9 and the result is 10 * 10.
var rec = function(a) {
console.log('f', a);
if (a == 0) return 1;
return rec(a - 1) * a;
};
f = rec;
rec = function(a) {
console.log('rec', a);
return a + 1;
}
console.log(f(10));
Keeping rec.
var rec = function rec(a) {
console.log('f', a);
if (a == 0) return 1;
return rec(a - 1) * a;
};
f = rec;
rec = function(a) {
console.log('rec', a);
return a + 1;
}
console.log(f(10));

These 3 statements can sum up to a single statement
rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec
rec = lambda x: x+1
from 1 & 2
f = lambda x : 1 if x==0 else rec(x-1)*x
from above & 3
f = lambda x : 1 if x==0 else x*x

I will suggest to use variable names properly, here you don't need reassignment
why it uses second rec not the first one ?
well your function call is happening after reassignment of rec so you have the latest value in rec as
rec = function(a) {
return a + 1;
}
var f = function(a) {
if (a == 0) return 1;
return rec(a - 1) * a;
}
var rec = function(a) {
return a + 1;
}
console.log(f(10));

Related

Assignement with parantheses in closure in d3 source code

While looking through the d3 source code, I found this snippet:
scale.unknown = function(_) {
return arguments.length ? (unknown = _, scale) : unknown;
};
This implements the pattern here: https://bost.ocks.org/mike/chart/. Here's a minimal example that works, with the above code adapted:
function closure() {
let mult
function my(t) {
return t * mult
}
my.mult = function(_) {
return arguments.length ? (mult = _, my) : mult
}
return my
}
Afterwards, you can use it like this:
fn = closure()
fn.mult(2)
console.log(fn(3)) // 6
fn.mult(4)
console.log(fn(3)) // 12
What I don't understand in my above example is this line:
return arguments.length ? (mult = _, my) : mult
This checks if there are arguments, and assigns the parameter to mult if there are, or returns mult if there aren't.
But what does the parentheses mean in (mult = _, my)? What does putting the returned function at the very end do?
I believe you have actually two different questions here.
The first one is about the parenthesis: Bostock (D3 creator) did that to take advantage of the comma operator, which he commonly uses in his codes. In short, this...
return arguments.length ? (mult = _, my) : mult
Translates to: does the function has any passed argument? If no, return the value of mult; if yes, return the my function AND assign the passed parameter to mult.
Then you have a second question:
What does putting the returned function at the very end do?
Not much, because that's not necessary. The test of argument.length is just to use a getter, that is, returning the stored value if no argument is passed. It could be just:
return arguments.length ? mult = _ : mult;
You can check this here:
function closure() {
let mult
function my(t) {
return t * mult
}
my.mult = function(_) {
return arguments.length ? mult = _ : mult;
}
return my
}
fn = closure()
fn.mult(2)
console.log(fn(3))
fn.mult(4)
console.log(fn(3))
console.log("stored value: " + fn.mult())

Javascript: If variable mets a condittion defined on another variable

My problem is simple but I can't find a way to make thag work
The idea is that if a variable (number) mets a condittion defined on another variable (cond), run some code
Example:
var cond = '> 4';
var number = 5;
// Some type of if statement to check if 5 is > 4
You can use eval but usually if you resort to eval, you're not understanding the problem correctly.
var cond = '> 4';
var number = 5;
if (eval(number + cond)) {
console.log(number + cond);
}
Another possibility would be to create functions which correlate with the condition then store the operand in another variable.
var compareFunctions = {
'>': function(a, b) {
return a > b;
}
};
var op = '>';
var operand = 4;
var number = 5;
if (compareFunctions[op](number, operand)) {
console.log(number + op + operand);
}
Do you mean like this?
if (eval(number+cond)){
console.log("success");
  }
You could use a function for the check of the condition.
var cond = function (x) { return x > 4; };
var number = 5;
console.log(cond(number));
The simple, but likely dangerous and ugly way would be to use eval()
var cond = '> 5';
console.log(eval(4 + cond));
console.log(eval(6 + cond));
However, this is dangerous because if that string is in any way coming from the user, they could enter bad things and make bad things happen.
A more proper way to handle it would be to parse it properly:
let cond = '> 5';
const evaluateCondition = (value, condition) => {
// Allows for >, <, >=, <=, !=, ==
let [, operator, operand] = condition.match(/^\s*(>|<|>=|<=|!=|==)\s*(\d+)$/);
switch(operator) {
case '>':
return value > operand;
case '<':
return value < operand;
case '==':
return value == operand;
// ... implement other operators here
}
};
console.log(evaluateCondition(4, cond));
console.log(evaluateCondition(6, cond));
This will let you define valid operators and handle them in a safe manner, also easily catching invalid input.
Below was done before an edit changed the question.
You have to declare the variable outside of it, but you can set it pretty easily. The syntax I would use looks like this:
var a = 5, b;
a == 5 && (b = 2);
The bit after the && only executes if the first condition is true. To set a variable in a syntax like this, you just wrap it in parentheses.
The more traditional way would be to use an if statement:
var a = 5, b;
if (a == 5) {
b = 2;
}
If you declare the second variable inside of the if statement, it doesn't exist outside of it:
var a = 5;
if (a == 5) {
var b = 2;
}
console.log(b) // undefined
which might be what was tripping you up.
You could use eval just be careful and make sure you read up on eval first:
var cond = '> 4';
var number = 5;
console.log(eval(("" + number + cond)));

How to pass a parameter with function signature

I don't have a control over the function invocation and I need to pass a few parameters with a pointer. Is it possible to do it?
var a = function(a, b){
return a + b;
}
b = a; //parameter here???
Any help will be appreciated!
You can use currying, the outer function call will return a pointer to another function that references the parameters you passed. Then you can call the inner function without passing the parameters.
var a = function(x, y) {
function(){
return x + y;
}
}
b = a(2, 3);
b();
The correct way to pass parameters to a is to replace your last line with : b = a(1, 2);.
This will give you 3 as a result, stored into the variable b.
You can see the current value of b at any time by running console.log(b); :
var a = function(a, b){
return a + b;
}
b = a(1, 2); // parameters here
console.log(b); // prints 3
But as I said, the use of b twice here is confusing. A better naming would be :
// sum is a better name
var sum = function(a, b){
return a + b;
}
result = sum(1, 2); // parameters here : 1 corresponds to a, 2 to b
console.log(result); // prints 3
Figured out myself. I am sorry if the question is not clear enough.
This is what I needed.
var a = function(a, b) {
return function(){
console.log(a + b);
}
};
b = a(3, 4);
b();

Is there a mechanism to loop x times in ES6 (ECMAScript 6) without mutable variables?

The typical way to loop x times in JavaScript is:
for (var i = 0; i < x; i++)
doStuff(i);
But I don't want to use the ++ operator or have any mutable variables at all. So is there a way, in ES6, to loop x times another way? I love Ruby's mechanism:
x.times do |i|
do_stuff(i)
end
Anything similar in JavaScript/ES6? I could kind of cheat and make my own generator:
function* times(x) {
for (var i = 0; i < x; i++)
yield i;
}
for (var i of times(5)) {
console.log(i);
}
Of course I'm still using i++. At least it's out of sight :), but I'm hoping there's a better mechanism in ES6.
Using the ES2015 Spread operator:
[...Array(n)].map()
const res = [...Array(10)].map((_, i) => {
return i * 10;
});
// as a one liner
const res = [...Array(10)].map((_, i) => i * 10);
Or if you don't need the result:
[...Array(10)].forEach((_, i) => {
console.log(i);
});
// as a one liner
[...Array(10)].forEach((_, i) => console.log(i));
Or using the ES2015 Array.from operator:
Array.from(...)
const res = Array.from(Array(10)).map((_, i) => {
return i * 10;
});
// as a one liner
const res = Array.from(Array(10)).map((_, i) => i * 10);
Note that if you just need a string repeated you can use String.prototype.repeat.
console.log("0".repeat(10))
// 0000000000
OK!
The code below is written using ES6 syntaxes but could just as easily be written in ES5 or even less. ES6 is not a requirement to create a "mechanism to loop x times"
If you don't need the iterator in the callback, this is the most simple implementation
const times = x => f => {
if (x > 0) {
f()
times (x - 1) (f)
}
}
// use it
times (3) (() => console.log('hi'))
// or define intermediate functions for reuse
let twice = times (2)
// twice the power !
twice (() => console.log('double vision'))
If you do need the iterator, you can use a named inner function with a counter parameter to iterate for you
const times = n => f => {
let iter = i => {
if (i === n) return
f (i)
iter (i + 1)
}
return iter (0)
}
times (3) (i => console.log(i, 'hi'))
Stop reading here if you don't like learning more things ...
But something should feel off about those...
single branch if statements are ugly — what happens on the other branch ?
multiple statements/expressions in the function bodies — are procedure concerns being mixed ?
implicitly returned undefined — indication of impure, side-effecting function
"Isn't there a better way ?"
There is. Let's first revisit our initial implementation
// times :: Int -> (void -> void) -> void
const times = x => f => {
if (x > 0) {
f() // has to be side-effecting function
times (x - 1) (f)
}
}
Sure, it's simple, but notice how we just call f() and don't do anything with it. This really limits the type of function we can repeat multiple times. Even if we have the iterator available, f(i) isn't much more versatile.
What if we start with a better kind of function repetition procedure ? Maybe something that makes better use of input and output.
Generic function repetition
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// power :: Int -> Int -> Int
const power = base => exp => {
// repeat <exp> times, <base> * <x>, starting with 1
return repeat (exp) (x => base * x) (1)
}
console.log(power (2) (8))
// => 256
Above, we defined a generic repeat function which takes an additional input which is used to start the repeated application of a single function.
// repeat 3 times, the function f, starting with x ...
var result = repeat (3) (f) (x)
// is the same as ...
var result = f(f(f(x)))
Implementing times with repeat
Well this is easy now; almost all of the work is already done.
// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
if (n > 0)
return repeat (n - 1) (f) (f (x))
else
return x
}
// times :: Int -> (Int -> Int) -> Int
const times = n=> f=>
repeat (n) (i => (f(i), i + 1)) (0)
// use it
times (3) (i => console.log(i, 'hi'))
Since our function takes i as an input and returns i + 1, this effectively works as our iterator which we pass to f each time.
We've fixed our bullet list of issues too
No more ugly single branch if statements
Single-expression bodies indicate nicely separated concerns
No more useless, implicitly returned undefined
JavaScript comma operator, the
In case you're having trouble seeing how the last example is working, it depends on your awareness of one of JavaScript's oldest battle axes; the comma operator – in short, it evaluates expressions from left to right and returns the value of the last evaluated expression
(expr1 :: a, expr2 :: b, expr3 :: c) :: c
In our above example, I'm using
(i => (f(i), i + 1))
which is just a succinct way of writing
(i => { f(i); return i + 1 })
Tail Call Optimisation
As sexy as the recursive implementations are, at this point it would be irresponsible for me to recommend them given that no JavaScript VM I can think of supports proper tail call elimination – babel used to transpile it, but it's been in "broken; will reimplement" status for well over a year.
repeat (1e6) (someFunc) (x)
// => RangeError: Maximum call stack size exceeded
As such, we should revisit our implementation of repeat to make it stack-safe.
The code below does use mutable variables n and x but note that all mutations are localized to the repeat function – no state changes (mutations) are visible from outside of the function
// repeat :: Int -> (a -> a) -> (a -> a)
const repeat = n => f => x =>
{
let m = 0, acc = x
while (m < n)
(m = m + 1, acc = f (acc))
return acc
}
// inc :: Int -> Int
const inc = x =>
x + 1
console.log (repeat (1e8) (inc) (0))
// 100000000
This is going to have a lot of you saying "but that's not functional !" – I know, just relax. We can implement a Clojure-style loop/recur interface for constant-space looping using pure expressions; none of that while stuff.
Here we abstract while away with our loop function – it looks for a special recur type to keep the loop running. When a non-recur type is encountered, the loop is finished and the result of the computation is returned
const recur = (...args) =>
({ type: recur, args })
const loop = f =>
{
let acc = f ()
while (acc.type === recur)
acc = f (...acc.args)
return acc
}
const repeat = $n => f => x =>
loop ((n = $n, acc = x) =>
n === 0
? acc
: recur (n - 1, f (acc)))
const inc = x =>
x + 1
const fibonacci = $n =>
loop ((n = $n, a = 0, b = 1) =>
n === 0
? a
: recur (n - 1, b, a + b))
console.log (repeat (1e7) (inc) (0)) // 10000000
console.log (fibonacci (100)) // 354224848179262000000
for (let i of Array(100).keys()) {
console.log(i)
}
Here is another good alternative:
Array.from({ length: 3}).map(...);
Preferably, as #Dave Morse pointed out in the comments, you can also get rid of the map call, by using the second parameter of the Array.from function like so:
Array.from({ length: 3 }, () => (...))
I think the best solution is to use let:
for (let i=0; i<100; i++) …
That will create a new (mutable) i variable for each body evaluation and assures that the i is only changed in the increment expression in that loop syntax, not from anywhere else.
I could kind of cheat and make my own generator. At least i++ is out of sight :)
That should be enough, imo. Even in pure languages, all operations (or at least, their interpreters) are built from primitives that use mutation. As long as it is properly scoped, I cannot see what is wrong with that.
You should be fine with
function* times(n) {
for (let i = 0; i < n; i++)
yield i;
}
for (const i of times(5)) {
console.log(i);
}
But I don't want to use the ++ operator or have any mutable variables at all.
Then your only choice is to use recursion. You can define that generator function without a mutable i as well:
function* range(i, n) {
if (i >= n) return;
yield i;
return yield* range(i+1, n);
}
times = (n) => range(0, n);
But that seems overkill to me and might have performance problems (as tail call elimination is not available for return yield*).
I think it is pretty simple:
[...Array(3).keys()]
or
Array(3).fill()
const times = 4;
new Array(times).fill().map(() => console.log('test'));
This snippet will console.log test 4 times.
Answer: 09 December 2015
Personally, I found the accepted answer both concise (good) and terse (bad). Appreciate this statement might be subjective, so please read this answer and see if you agree or disagree
The example given in the question was something like Ruby's:
x.times do |i|
do_stuff(i)
end
Expressing this in JS using below would permit:
times(x)(doStuff(i));
Here is the code:
let times = (n) => {
return (f) => {
Array(n).fill().map((_, i) => f(i));
};
};
That's it!
Simple example usage:
let cheer = () => console.log('Hip hip hooray!');
times(3)(cheer);
//Hip hip hooray!
//Hip hip hooray!
//Hip hip hooray!
Alternatively, following the examples of the accepted answer:
let doStuff = (i) => console.log(i, ' hi'),
once = times(1),
twice = times(2),
thrice = times(3);
once(doStuff);
//0 ' hi'
twice(doStuff);
//0 ' hi'
//1 ' hi'
thrice(doStuff);
//0 ' hi'
//1 ' hi'
//2 ' hi'
Side note - Defining a range function
A similar / related question, that uses fundamentally very similar code constructs, might be is there a convenient Range function in (core) JavaScript, something similar to underscore's range function.
Create an array with n numbers, starting from x
Underscore
_.range(x, x + n)
ES2015
Couple of alternatives:
Array(n).fill().map((_, i) => x + i)
Array.from(Array(n), (_, i) => x + i)
Demo using n = 10, x = 1:
> Array(10).fill().map((_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
> Array.from(Array(10), (_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
In a quick test I ran, with each of the above running a million times each using our solution and doStuff function, the former approach (Array(n).fill()) proved slightly faster.
I am late to the party, but since this question turns up often in search results, I would just like to add a solution that I consider to be the best in terms of readability while not being long (which is ideal for any codebase IMO). It mutates, but I'd make that tradeoff for KISS principles.
let times = 5
while( times-- )
console.log(times)
// logs 4, 3, 2, 1, 0
Array(100).fill().map((_,i)=> console.log(i) );
This version satisifies the OP's requirement for immutability. Also consider using reduce instead of map depending on your use case.
This is also an option if you don't mind a little mutation in your prototype.
Number.prototype.times = function(f) {
return Array(this.valueOf()).fill().map((_,i)=>f(i));
};
Now we can do this
((3).times(i=>console.log(i)));
+1 to arcseldon for the .fill suggestion.
Not something I would teach (or ever use in my code), but here's a codegolf-worthy solution without mutating a variable, no need for ES6:
Array.apply(null, {length: 10}).forEach(function(_, i){
doStuff(i);
})
More of an interesting proof-of-concept thing than a useful answer, really.
If you're willing to use a library, there's also lodash _.times or underscore _.times:
_.times(x, i => {
return doStuff(i)
})
Note this returns an array of the results, so it's really more like this ruby:
x.times.map { |i|
doStuff(i)
}
Afaik, there is no mechanism in ES6 similar to Ruby's times method. But you can avoid mutation by using recursion:
let times = (i, cb, l = i) => {
if (i === 0) return;
cb(l - i);
times(i - 1, cb, l);
}
times(5, i => doStuff(i));
Demo: http://jsbin.com/koyecovano/1/edit?js,console
In the functional paradigm repeat is usually an infinite recursive function. To use it we need either lazy evaluation or continuation passing style.
Lazy evaluated function repetition
const repeat = f => x => [x, () => repeat(f) (f(x))];
const take = n => ([x, f]) => n === 0 ? x : take(n - 1) (f());
console.log(
take(8) (repeat(x => x * 2) (1)) // 256
);
I use a thunk (a function without arguments) to achieve lazy evaluation in Javascript.
Function repetition with continuation passing style
const repeat = f => x => [x, k => k(repeat(f) (f(x)))];
const take = n => ([x, k]) => n === 0 ? x : k(take(n - 1));
console.log(
take(8) (repeat(x => x * 2) (1)) // 256
);
CPS is a little scary at first. However, it always follows the same pattern: The last argument is the continuation (a function), which invokes its own body: k => k(...). Please note that CPS turns the application inside out, i.e. take(8) (repeat...) becomes k(take(8)) (...) where k is the partially applied repeat.
Conclusion
By separating the repetition (repeat) from the termination condition (take) we gain flexibility - separation of concerns up to its bitter end :D
Advantages of this solution
Simplest to read / use (imo)
Return value can be used as a sum, or just ignored
Plain es6 version, also link to TypeScript version of the code
Disadvantages
- Mutation. Being internal only I don't care, maybe some others will not either.
Examples and Code
times(5, 3) // 15 (3+3+3+3+3)
times(5, (i) => Math.pow(2,i) ) // 31 (1+2+4+8+16)
times(5, '<br/>') // <br/><br/><br/><br/><br/>
times(3, (i, count) => { // name[0], name[1], name[2]
let n = 'name[' + i + ']'
if (i < count-1)
n += ', '
return n
})
function times(count, callbackOrScalar) {
let type = typeof callbackOrScalar
let sum
if (type === 'number') sum = 0
else if (type === 'string') sum = ''
for (let j = 0; j < count; j++) {
if (type === 'function') {
const callback = callbackOrScalar
const result = callback(j, count)
if (typeof result === 'number' || typeof result === 'string')
sum = sum === undefined ? result : sum + result
}
else if (type === 'number' || type === 'string') {
const scalar = callbackOrScalar
sum = sum === undefined ? scalar : sum + scalar
}
}
return sum
}
TypeScipt version
https://codepen.io/whitneyland/pen/aVjaaE?editors=0011
The simplest way I can think of for creating list/array within range
Array.from(Array(max-min+1), (_, index) => index+min)
I have another alternative
[...Array(30).keys()]
addressing the functional aspect:
function times(n, f) {
var _f = function (f) {
var i;
for (i = 0; i < n; i++) {
f(i);
}
};
return typeof f === 'function' && _f(f) || _f;
}
times(6)(function (v) {
console.log('in parts: ' + v);
});
times(6, function (v) {
console.log('complete: ' + v);
});
Generators? Recursion? Why so much hatin' on mutatin'? ;-)
If it is acceptable as long as we "hide" it, then just accept the use of a unary operator and we can keep things simple:
Number.prototype.times = function(f) { let n=0 ; while(this.valueOf() > n) f(n++) }
Just like in ruby:
> (3).times(console.log)
0
1
2
I wrapped #Tieme s answer with a helper function.
In TypeScript:
export const mapN = <T = any[]>(count: number, fn: (...args: any[]) => T): T[] => [...Array(count)].map((_, i) => fn())
Now you can run:
const arr: string[] = mapN(3, () => 'something')
// returns ['something', 'something', 'something']
I made this:
function repeat(func, times) {
for (var i=0; i<times; i++) {
func(i);
}
}
Usage:
repeat(function(i) {
console.log("Hello, World! - "+i);
}, 5)
/*
Returns:
Hello, World! - 0
Hello, World! - 1
Hello, World! - 2
Hello, World! - 3
Hello, World! - 4
*/
The i variable returns the amount of times it has looped - useful if you need to preload an x amount of images.
I am just going to put this here. If you are looking for a compact function without using Arrays and you have no issue with mutability/immutability :
var g =x=>{/*your code goes here*/x-1>0?g(x-1):null};
For me, this is the easiest answer to understand for many levels of developers
const times = (n, callback) => {
while (n) {
callback();
n--;
}
}
times(10, ()=> console.log('hello'))
It seems to me that the most correct answer (which is debatable) to this question is buried in a comment by Sasha Kondrashov and is also the most concise, using just two characters: "no". There is no functional alternative to a for-loop as nice as the syntax that Ruby has. We might want there to be one, but there just isn't.
It is not explicitly stated in the question, but I would argue any solution to the problem of 'looping N times' should not allocate memory, at least not proportional to N. That criterium would rule out most of the answers that are 'native to javascript'.
Other answers show implementations like the one in Ruby, which is fine, except that the question explicitly asks for a native javascript solution. And there is already a very decent hand-rolled solution in the question, arguably one of the most readable of all.

Trouble understanding Javascript nested function/closure

I'm attempting to port the following JavaScript code to ruby:
https://github.com/iguigova/snippets_js/blob/master/pokerIn4Hours/pokerIn4Hours.js
I think I have most of it sorted, the function that is giving me grief is:
var kickers = function(idx){ // http://en.wikipedia.org/wiki/Kicker_(poker)
idx = idx || -15;
var notplayed = Math.max(input.length - 1/*player input*/ - 5, 0);
return function(all, cardinality, rank) {
return (all || 0) + (((cardinality == 1) && (notplayed-- <= 0)) ? rank * Math.pow(10, ++idx) : 0);
};
}();
And it is called further down like so:
k = kickers(k, cardsofrank[i], i);
I was wondering if someone could explain how this works in JavaScript. The fact that the inner function has 3 parameters and the outer only has 1 is confusing, especially given that it is called with 3 parameters. I would like to understand what it's trying to accomplish, so that I can port the code with confidence.
function(idx) this function returns a new function function(all, cardinality, rank) and this new function is referred by kickers variable in turn. so kickers is basically pointing at the inner function you have returned.
the only way to call your returned function is this kickers(k, cardsofrank[i], i)
var kickers = function(idx){
var xyz;//below function in return statement can access this and argument idx
return function(...) {//this ensures that your kickers is infact a function
};
}();//invoke this function instantly due to () and assign the output to kickers
When Javascript interpreter read above assignment to Kickers it will execute the anonymous function
Since that function itself returns a function, the kickers will now a function (with closure).
Meaning the kickers function will have a reference to the environment variables (idx and notplayed )
Edit:
1) Where it is getting value of idx - Since nothing is passed while invoking the function(last line ();) the idx will be undefined and idx = idx || -15; will assign the value -15 to it.
2) Could this be re-written without an inner function? - Yes. But the current implementation has an advantage where the scope of idx and notplayed is limited to kicker function and will not be accessible globally. Here is how you can write it directly as a function
/* now idx and notplayed is global- but its meant to be used only by kicker
* we cant move it inside the function definition as it will behave as local variable to the function
* and hence will be freed up once executed and you cannot maintain the state of idx and notplayed
*/
var idx = -15;
var notplayed = Math.max(input.length - 1/*player input*/ - 5, 0);
var kickers = function(all, cardinality, rank) {
return(all || 0) + (((cardinality == 1) && (notplayed-- <= 0)) ? rank * Math.pow(10, ++idx) : 0);
}

Categories