I am trying to develop a game engine for personal use in JS. I want to have my engine be able to use elements of separate classes. One such problem I am trying to solve is chaining methods from one class (say a math class that chains functions) to my main function.
Here is an example of what I want it to look like:
let game = new Engine()
game.operator(5).sum(3).divide(2)
Here's what it might be in my code, although this is where I am not sure what to do.
class Engine {
constructor() {
//Set up engine here
/* This is where I am unsure how to link the following operator class to this one.
* Do I put it here in constructor or ...
*/
}
/* ... do I put it here? (Or not in this class at all?)
*
* This is what I tried doing as a function
*
* operator(input) {
* let op = new Operator(input);
* }
*/
}
class Operator {
/*The following class is different than the one I am using, but follows similar syntax:
* Basic usage: operator(5).sum(3, 4) => Should output 12
* How the class works is mostly irrelevant, just know it chains methods.
*/
constructor(input) {
this.input = input;
this.answer = this.input;
}
sum() {
let a = arguments[0]
for(var i = 1; i < arguments.length; i++) {
a += arguments[i];
}
this.answer += a;
return this;
}
divide() {
let a = arguments[0];
for(var i = 1; i < arguments.length; i++) {
a *= arguments[i];
}
this.answer /= a;
return this;
}
}
How can I get one class to be able to chain methods from different class?
A pattern for chaining is to have the instance keep a chain state, and to provide a 'value' method that returns the chain state. To chain between two classes, I guess I'd include a special value method that returns an instance of the other class. (To keep the reader oriented, name it something that indicates the type change)...
class ObjectA {
constructor(string) {
this.chainValue = string
this.string = string
}
transformA() {
this.chainValue = this.chainValue.toUpperCase()
return this
}
transformB() {
this.chainValue = this.chainValue + "bar"
return this
}
// the regular value method
get value() {
return this.chainValue
}
// like the value method, but named to explicitly return MyNumber
get numberValue() {
return new MyNumber(this.value.length)
}
}
class MyNumber {
constructor(int) {
this.chainValue = int
this.int = int
}
add(n) {
this.chainValue += n
return this
}
get value() {
return this.chainValue
}
}
let a = new ObjectA("foo")
console.log(
a
.transformB() // append "bar"
.transformA() // convert to upper case
.numberValue // return a number (arbitrarily, the length of the chain state)
.add(12) // add 12
.value // expect 18
)
You can use Proxy for that purpose.
class Engine {
operator() {
// code
console.log('call operator')
}
}
class Operator {
sum() {
// code
console.log('call sum')
}
divide() {
console.log('call divide')
}
}
class SuperOperator {
negate() {
console.log('call negate')
}
}
const operator = new Operator();
const superOperator = new SuperOperator();
const engine = new Engine();
const objectsToChainFrom = [
engine,
operator,
superOperator,
];
// create helper function for proxy
function wrapper(originalMethod, ctx) {
return function () {
originalMethod.apply(ctx, arguments);
// return proxy;
return this;
}
}
var proxy1 = new Proxy(objectsToChainFrom, {
get(target, methodToCall, receiver) {
const objectWithMethod = target.find(el => el[methodToCall]);
return wrapper(objectWithMethod[methodToCall], objectWithMethod)
}
});
proxy1
.sum()
.operator()
.divide()
.negate()
Can we use getters and setters without defining a method for a member?
For example, transform this
class int {
set value(val) {
this._value = val | 0; // Truncate
}
get value() {
return this._value;
}
}
var x = new int();
x.value = 5 / 2;
console.log(x.value); // shows 2 instead of 2.5
to something like this:
class int {
set (val) {
this = val | 0; // Truncate
}
get () {
return this;
}
}
var x = new int();
x = 5 / 2;
console.log(x); // shows 2 instead of 2.5
There's no operation you can tap into for when the value of a variable (x in your case) is replaced with a new value. That's just not something JavaScript has. You can't do that even with a Proxy.
Your first definition of int is probably about as close as you're going to get.
People have tried various ways of getting primitive-like things like your int. None of them is really satisfactory. For instance, this is a not-uncommon attempt:
class Int {
constructor(value) {
Object.defineProperty(this, "value", {
value: value | 0,
enumerable: true
});
}
set(value) {
return new this.constructor[Symbol.species](value);
}
valueOf() {
return this.value;
}
toString() {
return this.value; // Even though it's not a string
}
static get [Symbol.species]() {
return this;
}
}
then:
let n = new Int(5);
console.log(`n = ${n}`); // n = 5
n = n.set(n / 2);
console.log(`n = ${n}`); // n = 2
but as soon as you do something that doesn't coerce to a primitive, like:
console.log(n);
you see the object-ness of it. You have to do:
console.log(+n);
which makes it a pretty big footgun, though the immutability helps with things like let m = n..
Example:
class Int {
constructor(value) {
Object.defineProperty(this, "value", {
value: value | 0,
enumerable: true
});
}
set(value) {
return new this.constructor[Symbol.species](value);
}
valueOf() {
return this.value;
}
toString() {
return this.value; // Even though it's not a string
}
static get [Symbol.species]() {
return this;
}
}
let n = new Int(5);
console.log(`n = ${n}`); // n = 5
n = n.set(n / 2);
console.log(`n = ${n}`); // n = 2
// But
console.log(n); // (object representation of it)
After searching for quite some time, I still haven't found what I'm looking for.
There's a fair amount of examples that either require creating a new instance, or only have functions that don't return anything (which means the problem can be solved with returning this).
I hope the following example illustrates my point well:
// Say I have these functions
function aNumber(){
var max = 100, min = 0;
return (Math.floor(Math.random() * (max - min + 1)) + min);
}
function divideBy(_number, _divider){
return (_number / _divider);
}
function multiplyBy(_number, _multi){
return (_number * _multi);
}
function add(_number, _add){
return (_number + _add);
}
function subtract(_number, _sub){
return (_number - _sub);
}
// #########################################################
// I can do this with them
var test = aNumber();
test = divideBy(aNumber, 2);
test = add(aNumber, 5);
test = multiplyBy(aNumber, 3);
test = subtract(aNumber, 10);
// I would like to do this however:
var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10);
What would be the most efficient way to make the last line work?
Am I misinformed that this is possible without creating a new instance of something?
Yes, this requires changing the Prototype of an Object. Objects are instances. So you need to create an object to do this kind of thing.
function MyNum(value) {
this._val = value; // Having _variable is for denoting it is a private variable.
}
Initialize objects using:
var myNum = new MyNum(5);
And now using this, define these:
MyNum.prototype.divideBy = function () {}
MyNum.prototype.multiplyBy = function () {}
Don't forget to use return this; inside these functions.
Try like below for creating without instance and prototype keyword.
One more method is been added here you can set number or random number by default. if the number not specified.
var Calculator = {
setNumber: function(givenNumber) {
var max = 100,
min = 0;
this.number = (givenNumber) ? givenNumber : (Math.floor(Math.random() * (max - min + 1)) + min);
return this;
},
divideBy: function(_divider) {
this.number = (this.number / _divider);
return this;
},
multiplyBy: function(_multi) {
this.number = (this.number * _multi);
return this;
},
add: function(_add) {
this.number = (this.number + _add);
return this;
},
subtract: function(_sub) {
this.number = (this.number - _sub);
return this;
},
result: function () {
return this.number;
}
}
document.write('<pre>');
document.writeln(Calculator.setNumber(2).divideBy(2).add(5).multiplyBy(3).subtract(10).result());
document.writeln(Calculator.setNumber(4).divideBy(2).add(5).multiplyBy(3).subtract(10).number);
document.writeln(Calculator.setNumber().divideBy(2).add(5).multiplyBy(3).subtract(10).result());
document.write('</pre>');
Yes, you do need to create an instance of something. This can be a simple object literal, function constructor, etc...
The idea is that all of your methods are stored on some object, right? The only way to access those methods is to access them through that object. With this in mind, each function must RETURN the object that holds all of these methods.
A quick example
var myMethods = {
one: function() {
console.log('one');
// You can return 'this' or reference the object by name
return this;
// or
// return myMethods;
},
two: function() {
console.log('two');
return this;
}
};
myMethods.one().two().one().two();
//=> 'one', 'two', 'one', 'two'
Watch out when you reference the method directly, like so
var someMethod = myMethods.one;
someMethod() //=> undefined
This is because 'this' is now referencing the global object, which is another story for another day. Just watch out if you reference a method in this way.
Although it is generally not recommended to add functions to the prototype of JavaScript primitives, you can do what you are looking for by doing so.
function aNumber(){
var max = 100, min = 0;
return (Math.floor(Math.random() * (max - min + 1)) + min);
}
function divideBy(_number, _divider){
return (_number / _divider);
}
function multiplyBy(_number, _multi){
return (_number * _multi);
}
function add(_number, _add){
return (_number + _add);
}
function subtract(_number, _sub){
return (_number - _sub);
}
Number.prototype.divideBy = function(_divider){
return divideBy(this, _divider);
};
Number.prototype.multiplyBy = function(_multi){
return multiplyBy(this, _multi);
};
Number.prototype.add = function(_add){
return add(this, _add);
};
Number.prototype.subtract = function(_sub){
return subtract(this, _sub);
};
var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10);
Just like Praveen and Venkatraman said, I found the following posts about chaining, but there all have to declare a new instanse before accessing any methods for changing
method-chaining-in-javascript and beautiful-javascript-easily-create-chainable-cascading-methods-for-expressiveness
or you can use this implementation https://jsfiddle.net/ayinloya/zkys5dk6/
function aNumber() {
var max = 100;
var min = 0;
this._number = (Math.floor(Math.random() * (max - min + 1)) + min);
console.log("a init", this._number)
}
aNumber.prototype.divideBy = function(_divider) {
this._number = (this._number / _divider)
return this;
}
aNumber.prototype.multiplyBy = function(_multi) {
this._number = (this._number * _multi);
return this;
}
aNumber.prototype.add = function(_add) {
this._number = (this._number + _add);
return this;
}
aNumber.prototype.subtract = function(_sub) {
this._number = (this._number - _sub);
return this;
}
aNumber.prototype.ans = function() {
return this._number;
}
var a = new aNumber()
alert(a.add(2).subtract(1).ans())
If you don't want to pull in a library and want to have functions that are reusable (and not bind to a specific class, e.g. a Calculator). What you can do is to wrap the input into an array and then pass it through a series of map functions. In the end just take the first element and you will have your result.
function aNumber(){
var max = 100, min = 0;
return (Math.floor(Math.random() * (max - min + 1)) + min);
}
function divideBy(_number, _divider){
return (_number / _divider);
}
function multiplyBy(_number, _multi){
return (_number * _multi);
}
function add(_number, _add){
return (_number + _add);
}
function subtract(_number, _sub){
return (_number - _sub);
}
// #########################################################
var result = [aNumber()]
.map(item => divideBy(item, 2))
.map(item => add(item, 5))
.map(item => multiplyBy(item, 3))
.map(item => subtract(item, 10))
[0];
console.log(result);
This probably is not the most efficient way but usually speed is "good enough".
I want to declare a local variable as such:
(var n=1)
Mostly so I can manipulate the order it gets evaluated in.
Eg Then I could do
var increaseadNumber = (
ar={
inc:function(n){
return n+1
},
dec:function(n){
return n+2
}
}
).inc(1);
console.log(ar)//the object
console.log(increaseadNumber )//2
But, in my example ar is in the global namespace, and
var increaseadNumber = (
var ar={
inc:function(n){
return n+1
},
dec:function(n){
return n+2
}
}
).inc(1);//syntax error
generates "SyntaxError: Unexpected token var"
Granted I could declare this over 2 statements, but I would prefer to it with 1 statement.
Why not separate it into two lines?
var ar={inc:function(n){return n+1},dec:function(n){return n+2}};
ar.inc(1);
And add some sensible white space while you're at it:
var ar = {
inc: function(n) {
return n + 1
},
dec: function(n) {
return n + 2
}
};
ar.inc(1);
Or if you're really whitespace-averse, here's a compromise:
var ar = {
inc: function(n) { return n + 1 },
dec: function(n) { return n + 2 }
};
ar.inc(1);
The var keyword cannot follow an open parenthesis except in for (var ...). Maybe wrap the expression in a function:
ar = (function (n) {
return /* compute the value for ar here */;
})(1)
You can split the statement into:
var ar={inc:function(n){return n+1},dec:function(n){return n+2}}; ar.inc(1);
var ar = {
inc: function (n) { return n+1 },
dec: function (n) { return n+2 }
};
ar.inc(1);
Just declare it locally and invoke it in a seperate expression.
If you really want one expression I would recommend you declare a throwaway local variable __
var ar = {
inc: function (n) { return n+1 },
dec: function (n) { return n+2 }
}, __ = ar.inc(1);
The only way to invoke multiple expressions where one is a variable declaration is to declare multiple variables
If you want a local variable try declare it in a function,
(function () {
var ar={inc:function(n){return n+1},dec:function(n){return n+2}};
return ar;
})().inc(1)
not sure what is is you want to do, but this IIF (Immediately Invoked Function) may be an idea for you? Added a bit of spacing, which is ... advisable if you want to maintain your code.
alert(
(function(n){
n = n || 1;
return {
inc: function(n){ return n+1; },
dec: function(n){ return n+2; }
};
}(1)).inc(1)
); //=> 2
I want to make this syntax possible:
var a = add(2)(3); //5
based on what I read at http://dmitry.baranovskiy.com/post/31797647
I've got no clue how to make it possible.
You need add to be a function that takes an argument and returns a function that takes an argument that adds the argument to add and itself.
var add = function(x) {
return function(y) { return x + y; };
}
function add(x) {
return function(y) {
return x + y;
};
}
Ah, the beauty of JavaScript
This syntax is pretty neat as well
function add(x) {
return function(y) {
if (typeof y !== 'undefined') {
x = x + y;
return arguments.callee;
} else {
return x;
}
};
}
add(1)(2)(3)(); //6
add(1)(1)(1)(1)(1)(1)(); //6
It's about JS curring and a little strict with valueOf:
function add(n){
var addNext = function(x) {
return add(n + x);
};
addNext.valueOf = function() {
return n;
};
return addNext;
}
console.log(add(1)(2)(3)==6);//true
console.log(add(1)(2)(3)(4)==10);//true
It works like a charm with an unlimited adding chain!!
function add(x){
return function(y){
return x+y
}
}
First-class functions and closures do the job.
function add(n) {
sum = n;
const proxy = new Proxy(function a () {}, {
get (obj, key) {
return () => sum;
},
apply (receiver, ...args) {
sum += args[1][0];
return proxy;
},
});
return proxy
}
Works for everything and doesn't need the final () at the end of the function like some other solutions.
console.log(add(1)(2)(3)(10)); // 16
console.log(add(10)(10)); // 20
try this will help you in two ways add(2)(3) and add(2,3)
1.)
function add(a){ return function (b){return a+b;} }
add(2)(3) // 5
2.)
function add(a,b){
var ddd = function (b){return a+b;};
if(typeof b =='undefined'){
return ddd;
}else{
return ddd(b);
}
}
add(2)(3) // 5
add(2,3) // 5
ES6 syntax makes this nice and simple:
const add = (a, b) => a + b;
console.log(add(2, 5));
// output: 7
const add2 = a => b => a + b;
console.log(add2(2)(5));
// output: 7
Arrow functions undoubtedly make it pretty simple to get the required result:
const Sum = a => b => b ? Sum( a + b ) : a;
console.log(Sum(3)(4)(2)(5)()); //14
console.log(Sum(3)(4)(1)()); //8
This is a generalized solution which will solve add(2,3)(), add(2)(3)() or any combination like add(2,1,3)(1)(1)(2,3)(4)(4,1,1)(). Please note that few security checks are not done and it can be optimized further.
function add() {
var total = 0;
function sum(){
if( arguments.length ){
var arr = Array.prototype.slice.call(arguments).sort();
total = total + arrayAdder(arr);
return sum;
}
else{
return total;
}
}
if(arguments.length) {
var arr1 = Array.prototype.slice.call(arguments).sort();
var mytotal = arrayAdder(arr1);
return sum(mytotal);
}else{
return sum();
}
function arrayAdder(arr){
var x = 0;
for (var i = 0; i < arr.length; i++) {
x = x + arr[i];
};
return x;
}
}
add(2,3)(1)(1)(1,2,3)();
This will handle both
add(2,3) // 5
or
add(2)(3) // 5
This is an ES6 curry example...
const add = (a, b) => (b || b === 0) ? a + b : (b) => a + b;
This is concept of currying in JS.
Solution for your question is:
function add(a) {
return function(b) {
return a + b;
};
}
This can be also achieved using arrow function:
let add = a => b => a + b;
solution for add(1)(2)(5)(4)........(n)(); Using Recursion
function add(a) {
return function(b){
return b ? add(a + b) : a;
}
}
Using ES6 Arrow function Syntax:
let add = a => b => b ? add(a + b) : a;
in addition to what's already said, here's a solution with generic currying (based on http://github.com/sstephenson/prototype/blob/master/src/lang/function.js#L180)
Function.prototype.curry = function() {
if (!arguments.length) return this;
var __method = this, args = [].slice.call(arguments, 0);
return function() {
return __method.apply(this, [].concat(
[].slice.call(args, 0),
[].slice.call(arguments, 0)));
}
}
add = function(x) {
return (function (x, y) { return x + y }).curry(x)
}
console.log(add(2)(3))
Concept of CLOSURES can be used in this case.
The function "add" returns another function. The function being returned can access the variable in the parent scope (in this case variable a).
function add(a){
return function(b){
console.log(a + b);
}
}
add(2)(3);
Here is a link to understand closures http://www.w3schools.com/js/js_function_closures.asp
const add = a => b => b ? add(a+b) : a;
console.log(add(1)(2)(3)());
Or (`${a} ${b}`) for strings.
With ES6 spread ... operator and .reduce function. With that variant you will get chaining syntax but last call () is required here because function is always returned:
function add(...args) {
if (!args.length) return 0;
const result = args.reduce((accumulator, value) => accumulator + value, 0);
const sum = (...innerArgs) => {
if (innerArgs.length === 0) return result;
return add(...args, ...innerArgs);
};
return sum;
}
// it's just for fiddle output
document.getElementById('output').innerHTML = `
<br><br>add() === 0: ${add() === 0 ? 'true' : 'false, res=' + add()}
<br><br>add(1)(2)() === 3: ${add(1)(2)() === 3 ? 'true' : 'false, res=' + add(1)(2)()}
<br><br>add(1,2)() === 3: ${add(1,2)() === 3 ? 'true' : 'false, res=' + add(1,2)()}
<br><br>add(1)(1,1)() === 3: ${add(1)(1,1)() === 3 ? 'true' : 'false, res=' + add(1)(1,1)()}
<br><br>add(2,3)(1)(1)(1,2,3)() === 13: ${add(2,3)(1)(1)(1,2,3)() === 13 ? 'true' : 'false, res=' + add(2,3)(1)(1)(1,2,3)()}
`;
<div id='output'></div>
can try this also:
let sum = a => b => b ? sum(a + b) :a
console.log(sum(10)(20)(1)(32)()) //63
const sum = function (...a) {
const getSum = d => {
return d.reduce((i,j)=> i+j, 0);
};
a = getSum(a);
return function (...b) {
if (b.length) {
return sum(a + getSum(b));
}
return a;
}
};
console.log(sum(1)(2)(3)(4,5)(6)(8)())
function add(a, b){
return a && b ? a+b : function(c){return a+c;}
}
console.log(add(2, 3));
console.log(add(2)(3));
This question has motivated so many answers already that my "two pennies worth" will surely not spoil things.
I was amazed by the multitude of approaches and variations that I tried to put "my favourite" features, i. e. the ones that I would like to find in such a currying function together, using some ES6 notation:
const add=(...n)=>{
const vsum=(a,c)=>a+c;
n=n.reduce(vsum,0);
const fn=(...x)=>add(n+x.reduce(vsum,0));
fn.toString=()=>n;
return fn;
}
let w=add(2,1); // = 3
console.log(w()) // 3
console.log(w); // 3
console.log(w(6)(2,3)(4)); // 18
console.log(w(5,3)); // 11
console.log(add(2)-1); // 1
console.log(add()); // 0
console.log(add(5,7,9)(w)); // 24
.as-console-wrapper {max-height:100% !important; top:0%}
Basically, nothing in this recursively programmed function is new. But it does work with all possible combinations of arguments mentioned in any of the answers above and won't need an "empty arguments list" at the end.
You can use as many arguments in as many currying levels you want and the result will be another function that can be reused for the same purpose. I used a little "trick" to also get a numeric value "at the same time": I redefined the .toString() function of the inner function fn! This method will be called by Javascript whenever the function is used without an arguments list and "some value is expected". Technically it is a "hack" as it will not return a string but a number, but it will work in a way that is in most cases the "desired" way. Give it a spin!
Simple Recursion Solution for following use cases
add(); // 0
add(1)(2)(); //3
add(1)(2)(3)(); //6
function add(v1, sum = 0) {
if (!v1) return sum;
sum += v1
return (v2) => add(v2, sum);
}
function add() {
var sum = 0;
function add() {
for (var i=0; i<arguments.length; i++) {
sum += Number(arguments[i]);
}
return add;
}
add.valueOf = function valueOf(){
return parseInt(sum);
};
return add.apply(null,arguments);
}
// ...
console.log(add() + 0); // 0
console.log(add(1) + 0);/* // 1
console.log(add(1,2) + 0); // 3
function A(a){
return function B(b){
return a+b;
}
}
I found a nice explanation for this type of method. It is known as Syntax of Closures
please refer this link
Syntax of Closures
Simply we can write a function like this
function sum(x){
return function(y){
return function(z){
return x+y+z;
}
}
}
sum(2)(3)(4)//Output->9
Don't be complicated.
var add = (a)=>(b)=> b ? add(a+b) : a;
console.log(add(2)(3)()); // Output:5
it will work in the latest javascript (ES6), this is a recursion function.
Here we use concept of closure where all the functions called inside main function iter refer and udpate x as they have closure over it. no matter how long the loop goes , till last function , have access to x.
function iter(x){
return function innfunc(y){
//if y is not undefined
if(y){
//closure over ancestor's x
x = y+x;
return innfunc;
}
else{
//closure over ancestor's x
return x;
}
}
}
iter(2)(3)(4)() //9
iter(1)(3)(4)(5)() //13
let multi = (a)=>{
return (b)=>{
return (c)=>{
return a*b*c
}
}
}
multi (2)(3)(4) //24
let multi = (a)=> (b)=> (c)=> a*b*c;
multi (2)(3)(4) //24
we can do this work using closure.
function add(param1){
return function add1(param2){
return param2 = param1 + param2;
}
}
console.log(add(2)(3));//5
I came up with nice solution with closure, inner function have access to parent function's parameter access and store in its lexical scope, when ever we execute it, will get answer
const Sum = function (a) {
return function (b) {
return b ? Sum(a + b) : a;
}
};
Sum(1)(2)(3)(4)(5)(6)(7)() // result is 28
Sum(3)(4)(5)() // result is 12
Sum(12)(10)(20) // result is 42
enter image description here
You should go in for currying to call the function in the above format.
Ideally, a function which adds two numbers will be like,
let sum = function(a, b) {
return a + b;
}
The same function can be transformed as,
let sum = function(a) {
return function(b) {
return a+b;
}
}
console.log(sum(2)(3));
Let us understand how this works.
When you invoke sum(2), it returns
function(b) {
return 2 + b;
}
when the returned function is further invoked with 3, b takes the value 3. The result 5 is returned.
More Detailed Explanation:
let sum = function(a) {
return function(b) {
return a + b;
}
}
let func1 = sum(2);
console.log(func1);
let func2 = func1(3)
console.log(func2);
//the same result can be obtained in a single line
let func3 = sum(2)(3);
console.log(func3);
//try comparing the three functions and you will get more clarity.
This is a short solution:
const add = a => b => {
if(!b) return a;
return add(a + b);
}
add(1)(2)(3)() // 6
add(1)(2)(3)(4)(5)() // 15