Related
A friend of mine challenged me to write a function that works with both of these scenarios
add(2,4) // 6
add(2)(4) // 6
My instinct was the write an add() function that returns itself but I'm not sure I'm heading in the right direction. This failed.
function add(num1, num2){
if (num1 && num2){
return num1 + num2;
} else {
return this;
}
}
alert(add(1)(2));
So I started reading up on functions that return other functions or return themselves.
http://davidwalsh.name/javascript-functions
JavaScript: self-calling function returns a closure. What is it for?
JavaScript: self-calling function returns a closure. What is it for?
I am going to keep trying, but if someone out there has a slick solution, I'd love to see it!
I wrote a curried function whose valueOf() method and function context (this) are bound with the sum no matter how many arguments are passed each time.
/* add function */
let add = function add(...args) {
const sum = args.reduce((acc, val) => acc + val, this);
const chain = add.bind(sum);
chain.valueOf = () => sum;
return chain;
}.bind(0);
/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));
The reason why both mechanisms are required is because the body of add() must use the called function's bound context in order to access the sum of the intermediate partial application, and the call site must use the valueOf() member (either implicitly or explicitly) in order to access the final sum.
There is an article on Dr.Dobs Journal about "Currying and Partial Functions in JavaScript" which describes exactly this problem.
One solution found in this article is:
// a curried add
// accepts partial list of arguments
function add(x, y) {
if (typeof y === "undefined") { // partial
return function (y) {
return x + y;
};
}
// full application
return x + y;
}
function add(num1, num2){
if (num1 && num2) {
return num1 + num2;
} else if (num1) {
return function(num2){return num1 + num2;};
}
return 0;
}
The concept that you're looking for is called currying and it has to do with function transformation and partial function application. This is useful for when you find yourself calling the same function over and over with mostly the same arguments.
An example of implementing add(2)(6) via currying would look something like this...
function add(x,y) {
if (typeof y === 'undefined') {
return function(y) {
return x + y;
}
}
}
add(2)(4); // => 6
Additionally, you could do something like this...
var add6 = add(6);
typeof add6; // => 'function'
add6(4); // => 10
var add = function(){
// the function was called with 2 arguments
if(arguments.length > 1)
arguments.callee.first_argument = arguments[0];
// if the first argument was initialized
if(arguments.callee.first_argument){
var result = arguments.callee.first_argument + arguments[arguments.length - 1];
arguments.callee.first_argument = 0;
return result;
}else{// if the function was called with one argument only then we need to memorize it and return the same function handler
arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
return arguments.callee;
}
}
console.log(add(2)(4));
console.log(add(2, 4));
An extended solution which depends on the environment:
function add(){
add.toString = function(){
var answer = 0;
for(i = 0; i < add.params.length; i++)
answer += add.params[i];
return answer;
};
add.params = add.params || [];
for(var i = 0; i < arguments.length; i++)
add.params.push(arguments[i])
return add;
}
console.log(add(2)(4)(6)(8))
console.log(add(2, 4, 6, 8));
We can use the concept of closures which is provided by Javascript.
Code snippet:
function add(a,b){
if(b !== undefined){
console.log(a + b);
return;
}
return function(b){
console.log(a + b);
}
}
add(2,3);
add(2)(3);
In general you need to have an agreement whether the function should return a function (for calling with more arguments) or the end result. Imagine the add function would have to work like this as well:
add(1, 2, 3)(4, 5) // -> 15
...then it becomes ambiguous, because you might want to call again:
add(1, 2, 3)(4, 5)(6) // -> 21
...and so add(1, 2, 3)(4, 5) should have returned a function, and not 15.
You could for instance agree that you have to call the function again, but without arguments, in order to get the numeric result:
function add(...args) {
if (args.length === 0) return 0;
let sum = args.reduce((a, b) => a+b, 0);
return (...args) => args.length ? add(sum, ...args) : sum;
}
console.log(add()); // 0
console.log(add(1,2,3)()); // 6
console.log(add(1,2,3)(4,5)()); // 15
console.log(add(1,2,3)(4,5)(6)()); // 21
One may think that he/she has to invoke the same function two times, but if you think deeply you will realize that the problem is pretty straight forward, you have to invoke the add function one time then you need to invoke what ever the add function returns.
function add(a){
return function(b){
return a+b;
}
}
console.log(add(20)(20));
//output: 40
you can return function as many as time you want. suppose for y = mx+c
const y= function (m){
return function(x){
return function (c){
return m*x+c
}
}
}
console.log(y(10)(5)(10));
//out put: 60
I want to create callback function with some parameters, but I want that one of the values within never change and be set when the function is created!
P.e.
let a = 2;
let y = (b) => { let staticValue = a; return staticValue * b; }
y(1) => 2 -> OK
then
a = 3
y(1) => 3 -> Not OK -> I want the function to have the original value of a.
I know, this happens because the variable a is only evaluated when the function is called. But is there any workaround?
You can accomplish this with what is called an IIFE (immediately invoked function expression)
let a = 2;
const y = (staticValue => b => staticValue * b)(a);
a = 44;
console.log(y(1));
What's happening here is that you have two functions. The first one, staticValue => ... is immediately invoked, and staticValue is given the value of a. Since a is given as an argument of the IIFE, once the function is invoked staticValue won't change, even if the value of a is changed.
The return value of the first function is a second function, b=> ....
let a = 2
let makeY = () => {
let staticValue = a;
return (b)=> staticValue * b;
}
let y = makeY();
or
let a = 2
let y = ((staticValue, b) => {
return staticValue * b;
}).bind(null, a)
you can use closure
function first (a) {
function second (b) {
return a * b;
}
return second;
}
let x = first(2) // the inner function second will close around the variable a which is 2 in this case
console.log(x(3))
let y = first(5) // the inner function second will close around the variable a which is 5 in this case
console.log(y(3))
I think you could apply a Functional programming approach.
const getYFn = (a , b) => {
return a * b;
}
const a = 2
const y = getYFn.bind(null, a);
// the constant y now is a function that partially applied first param
console.log(y(1)); // 2
console.log(y(3)); // 6
I have a scenario where I would like to send in 2 or more functions (as parameters) into a handler function, and have that handler function execute each passed function as a callback function for the preceding function.
Here is a general concept of the function I am trying to write:
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
call arguments[i];
}
}
}
// example
functionChain( function1, function2, function3 );
... so in the code above, each function will be called in succession.
Where I am getting stuck is how to treat each call as a callback when the previous function completes.
The way I would approach this is to have a variable (for simplicity, lets just say a global variable named functionChainComplete), and wait to launch the next function -- and of course, each function I call would set functionChainComplete to true. So, something like this:
// set global var for tracking
var functionChainComplete;
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// SET GLOBAL VAR TO FALSE
functionChainComplete = true;
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
if ( functionChainComplete == true ) {
// call the next function and wait for true again
functionChainComplete = false;
call arguments[i];
} else {
// try again in 50 ms (maybe setTimeout)?
}
}
}
}
function1() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function2() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function3() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
// example
functionChain( function1, function2, function3 );
As you can see, the code above does not address the callback piece, and I am not sure where to take it from here - I suspect some sort of recursive function? I am stuck.
Say you have some function, double, that takes an argument, x, and a callback, k
const double = (x, k) =>
k(x * 2)
double(2, console.log) // 4
double(3, console.log) // 6
Now say we want to run it 3 times in a row
const double = (x, k) =>
k(x * 2)
const tripleDouble = (x, k) =>
double(x, y =>
double(y, z =>
double(z, k)))
tripleDouble(2, console.log) // 16
tripleDouble(3, console.log) // 24
But of course we had to statically code each continuation (y => ..., and z => ...). How would we make this work with a variable amount (array) of functions?
const double = (x, k) =>
k(x * 2)
const composek = (...fs) => (x, k) =>
fs.reduce((acc, f) =>
k => acc(x => f(x, k)), k => k(x)) (k)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
This is ripe for some abstraction tho, and introduces my favourite monad, the Continuation Monad.
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) =>
acc.chain(x =>
Cont(k => f(x,k))), Cont.of(x)).runCont(k)
const double = (x, k) =>
k(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
If you have freedom to change the functions you're chaining, this cleans up a little bit more – here, double has 1 parameter and returns a Cont instead of taking a callback as a second argument
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
// simplified
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) => acc.chain(f), Cont.of(x)).runCont(k)
// simplified
const double = x =>
Cont.of(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
Of course if double was actually asynchronous, it would work the same
// change double to be async; output stays the same
const double = x =>
Cont(k => setTimeout(k, 1000, x * 2))
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
Something like this? (See comments, but fairly self-explanatory.)
function functionChain() {
var args = arguments;
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( args.length < 1 ) { return; }
// Start the process
var i = -1;
go();
function go() {
// Pre-increment so we start at 0
++i;
if (i < args.length) {
// We have a next function, do it and continue when we get the callback
args[i](go);
}
}
}
Example:
function functionChain() {
var args = arguments;
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( args.length < 1 ) { return; }
// Start the process
var i = -1;
go();
function go() {
// Pre-increment so we start at 0
++i;
if (i < args.length) {
// We have a next function, do it and continue when we get the callback
args[i](go);
}
}
}
// Just some functions for an example:
function a(callback) {
console.log("a");
callback();
}
function b(callback) {
console.log("b");
callback();
}
// Note this one is async
function c(callback) {
setTimeout(function() {
console.log("c");
callback();
}, 100);
}
function d(callback) {
console.log("d");
callback();
}
functionChain(a, b, c, d);
That said, one of the reasons for promises is to allow composing possibly-async functions. If your functions returned promises, we'd use the reduce idiom:
function functionChain() {
// Assumes the functions return promises (or at least thenables)
Array.prototype.reduce.call(arguments, function(p, f) {
return p.then(f);
}, Promise.resolve());
}
function functionChain() {
Array.prototype.reduce.call(arguments, function(p, f) {
return p.then(f);
}, Promise.resolve());
}
// Just some functions for an example:
function a(callback) {
return new Promise(function(resolve) {
console.log("a");
resolve();
});
}
function b(callback) {
return new Promise(function(resolve) {
console.log("b");
resolve();
});
}
// Note this one has a delay
function c(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
console.log("c");
resolve();
}, 100);
});
}
function d(callback) {
return new Promise(function(resolve) {
console.log("d");
resolve();
});
}
functionChain(a, b, c, d);
This could be done with nsynjs:
Wrap all slow functions with callbacks into nsynjs-aware wrappers (see wait()),
Put your logic into function as if it was synchronous (see synchronousCode()),
Run that function via nsynjs engine (see nsynjs.run())
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>
<script>
var wait = function (ctx, ms) {
setTimeout(function () {
console.log('firing timeout');
ctx.resume();
}, ms);
};
wait.nsynjsHasCallback = true;
function synchronousCode() {
function function1() {
console.log('in function1');
wait(nsynjsCtx,1000);
};
function function2() {
console.log('in function2');
wait(nsynjsCtx,1000);
};
function function3() {
console.log('in function3');
wait(nsynjsCtx,1000);
};
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) return;
for ( var i=0; i<arguments.length; i++) {
//console.log(i,arguments[i]);
if ( typeof arguments[i] === 'function' ) {
arguments[i]();
};
};
};
functionChain(function1,function2,function3);
}
nsynjs.run(synchronousCode,{},function(){
console.log("Synchronous Code done");
})
</script>
See https://github.com/amaksr/nsynjs/tree/master/examples for more examples.
I am working my way through Eloquent JavaScript, and I am having questions about problem #6.3 (second edition).
Here is the problem:
Design an interface that abstracts iteration over a collection of
values. An object that provides this interface represents a sequence,
and the interface must somehow make it possible for code that uses
such an object to iterate over the sequence, looking at the element
values it is made up of and having some way to find out when the end
of the sequence is reached.
When you have specified your interface, try to write a function
logFive that takes a sequence object and calls console.log on its
first five elements—or fewer, if the sequence has fewer than five
elements.
Then implement an object type ArraySeq that wraps an array and allows
iteration over the array using the interface you designed. Implement
another object type RangeSeq that iterates over a range of integers
(taking from and to arguments to its constructor) instead.
I wrote this solution:
function ArraySeq(collection) {
this.values = collection;
}
ArraySeq.prototype.iterate = function(start, end, action) {
var n = Math.min(this.values.length, end);
for (var i = start; i < n; i++) {
action(this.values[i]);
}
};
function RangeSeq(from, to) {
var array = [];
for (var i = from; i <= to; i++)
array.push(i);
ArraySeq.call(this, array);
}
RangeSeq.prototype = Object.create(ArraySeq.prototype);
function logFive(sequenceObject) {
sequenceObject.iterate(0, 5, console.log);
}
//This code to test how the solution works was provided by the author
logFive(new ArraySeq([1, 2]));
// → 1
// → 2
logFive(new RangeSeq(100, 1000));
// → 100
// → 101
// → 102
// → 103
// → 104
The solutions by the author are different, here are both of them:
// I am going to use a system where a sequence object has two methods:
//
// * next(), which returns a boolean indicating whether there are more
// elements in the sequence, and moves it forward to the next
// element when there are.
//
// * current(), which returns the current element, and should only be
// called after next() has returned true at least once.
function logFive(sequence) {
for (var i = 0; i < 5; i++) {
if (!sequence.next())
break;
console.log(sequence.current());
}
}
function ArraySeq(array) {
this.pos = -1;
this.array = array;
}
ArraySeq.prototype.next = function() {
if (this.pos >= this.array.length-1)
return false;
this.pos++;
return true;
};
ArraySeq.prototype.current = function() {
return this.array[this.pos];
};
function RangeSeq(from, to) {
this.pos = from - 1;
this.to = to;
}
RangeSeq.prototype.next = function() {
if (this.pos >= this.to)
return false;
this.pos++;
return true;
};
RangeSeq.prototype.current = function() {
return this.pos;
};
logFive(new ArraySeq([1, 2]));
// → 1
// → 2
logFive(new RangeSeq(100, 1000));
// → 100
// → 101
// → 102
// → 103
// → 104
// This alternative approach represents the empty sequence as null,
// and gives non-empty sequences two methods:
//
// * head() returns the element at the start of the sequence.
//
// * rest() returns the rest of the sequence, or null if there are no
// elemements left.
//
// Because a JavaScript constructor can not return null, we add a make
// function to constructors of this type of sequence, which constructs
// a sequence, or returns null if the resulting sequence would be
// empty.
function logFive2(sequence) {
for (var i = 0; i < 5 && sequence != null; i++) {
console.log(sequence.head());
sequence = sequence.rest();
}
}
function ArraySeq2(array, offset) {
this.array = array;
this.offset = offset;
}
ArraySeq2.prototype.rest = function() {
return ArraySeq2.make(this.array, this.offset + 1);
};
ArraySeq2.prototype.head = function() {
return this.array[this.offset];
};
ArraySeq2.make = function(array, offset) {
if (offset == null) offset = 0;
if (offset >= array.length)
return null;
else
return new ArraySeq2(array, offset);
};
function RangeSeq2(from, to) {
this.from = from;
this.to = to;
}
RangeSeq2.prototype.rest = function() {
return RangeSeq2.make(this.from + 1, this.to);
};
RangeSeq2.prototype.head = function() {
return this.from;
};
RangeSeq2.make = function(from, to) {
if (from > to)
return null;
else
return new RangeSeq2(from, to);
};
logFive2(ArraySeq2.make([1, 2]));
// → 1
// → 2
logFive2(RangeSeq2.make(100, 1000));
// → 100
// → 101
// → 102
// → 103
// → 104
My questions:
My solution produces exactly the same results as the author's solutions. I tested all three with various test cases. I did utilize the material of the chapter when writing my solution (the chapter talks about OOP techniques in JavaScript, inheritance and such). Given all this, is my solution wrong or not?
Why are his solutions written the way they are written? I mean, is there something wrong with my approach? Not abstract enough? Is it a bad thing that my method accepts arguments? His methods do not require arguments. Are there any drawbacks to my solution comparing to his? (I must confess, I barely understood the problem, so my solution probably reflects the level of my understanding of the problem.)
Thank you!
Your solution is not correct, because the whole point of the iterator protocol is to iterate lazily, so that RangeSeq(1, 10000000) doesn't fill up memory with all elements if we only need five.
The author's code is ok, but unnecessarily verbose. Iterator protocols are usually implemented like this:
an Iterable is an object that has the iterator() method
Iterable.iterator() returns an Iterator object
Iterator provides the method .next which returns a pair (done, value). Alternatively, .next can throw an exception when called on an exhausted Iterator.
Examples:
function RangeSeq(from, to) {
this.iterator = function() {
var i = from;
return {
next: function() { return [i >= to, i++] }
}
}
}
function ArraySeq(ary) {
this.iterator = function() {
var i = 0;
return {
next: function() { return [ i >= ary.length, ary[i++]] }
}
}
}
function logN(seq, n) {
var it = seq.iterator();
while (n--) {
let [done, value] = it.next();
if (done) break;
console.log(value)
}
}
logN(new RangeSeq(100, 100000000), 5);
console.log('--------------');
logN(new ArraySeq([11,22,33,44,55,66,77,88,99]), 5);
That said, modern JS engines have this kind of stuff built-in, so the Range example can be written much simpler as
function RangeSeq(from, to) {
this[Symbol.iterator] = function*() {
for (let i = from; i < to; i++)
yield i;
}
}
n = 0;
rs = new RangeSeq(100, 10000000);
for (let x of rs) {
if (n++ >= 5) break;
console.log(x)
}
Problem
I'm learning functional programming using the book "Functional Javascript". Currently, I'm fairly puzzled by the console output from the fnull method. I'm looking for an explanation to what is going on and why I am observing the results that I am observing.
I suspect the extra arguments are the iterator and context. However, the function defined by fnull only takes two arguments, total and n. Where does the iterator and context come from?
Code
JSFiddle
function existy(x) { return x != null };
function fnull(fun /*, defaults */) {
var defaults = _.rest(arguments);
return function(/* args */) {
console.log("checking " + arguments[1]);
var args = _.map(arguments, function(e, i) {
console.log(e + "," + i);
return existy(e) ? e : defaults[i];
});
return fun.apply(null, args);
};
};
var safeMult = fnull(function(total, n) { return total * n }, 1, 1);
console.log(_.reduce([1,2,3,null,5], safeMult));
Output
checking 2
1,0
2,1
1,2 /* <-- Where do these arguments come from? */
1,2,3,,5,3 /* <-- */
checking 3
2,0
3,1
2,2
1,2,3,,5,3
checking null
6,0
null,1
3,2
1,2,3,,5,3
checking 5
6,0
5,1
4,2
1,2,3,,5,3
30
[edits below]
Reduce Source
Looking over the source code of the reduce method, it brings over the iterator and context. So even though fun uses total and n, iterator and context are being provided.
Below is the source for the reduce method from the underscore.js site:
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduce && obj.reduce === nativeReduce) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
}
});
if (!initial) throw new TypeError(reduceError);
return memo;
};
First of all, the function defined by fnull takes any number of arguments. It is the function that is returned by fnull.
function fnull(...) {
...
return function(/* args */) { // <-- this is the function defined by fnull
....
}
}
The function that is passed to fnull (function(total, n) { return total * n }) is stored in the fun argument of fnull. In other words:
safeMult is the returned function of fnull
fun is function(total, n) { return total * n }
What you're writing to the console are the parameters passed to safeMult by_.reduce.