Reputation: 113455
During the Math classes we learned how to define new operators. For example:
(ℝ, ∘), x ∘ y = x + 2y
This defines ∘
law. For any real numbers x and y, x ∘ y is x + 2y.
Example: 2 ∘ 2 = 2 + 4 = 6
.
Is possible to define operators like this in JavaScript? I know that a function would do the job:
function foo (x, y) { return x + 2 * y; }
but I would like to have the following syntax:
var y = 2 ∘ 2; // returns 6
instead of this:
var y = foo(2, 2);
Which is the closest solution to this question?
Upvotes: 49
Views: 23765
Reputation: 1775
A somewhat late addition based on @iUrii answer using Number.prototype
Using the shorthand square bracket notation [], Number operations can be shown as:
Number.prototype["ӕ"] = function(y){ return this + 2 * y; };
Then, the operation requested can be written (fairly condensed) as:
var custom_op_result = (2)["ӕ"](2);
// Expands out to 2 + 2 * 2 = 6;
// console.log( custom_op_result ) Returns 6
Rather long combinations can also be written using complex notation, variables, parentheses, ect... such as (with above):
Number.prototype["Ϡ"] = function(y){ return this / y; };
Number.prototype["փ"] = function(y){ return y ** this; };
var starting_number = 2;
var custom_op_result = ( starting_number["Ϡ"](2) + (2)["փ"]((2)["ӕ"](2)) ) * 2;
// Expands out to ( 2 / 2 + (2 + 2 * 2) ** 2 ) * 2 = 74
// console.log( custom_op_result ) Returns 74
Or... If you want to get really crazy, and possibly confusing you can even assign the operators to variables individually like so:
var ӕ = "ӕ";
var Ϡ = "Ϡ";
var փ = "փ";
var custom_op_result = (2)[ӕ](2)[Ϡ](2)[փ](2);
// Expands out to 2**( (2+2*2) /2 )
// NOTE: Third property actually works backwards to expected
// Would have "expected" 3**2, except it is reversed as 2**3
// console.log( custom_op_result ) Returns 8
Here's the simple version as a clickable example:
<html>
<head>
<!-- Static Info and Links-->
<title>Quick demo of math operators</title>
<!-- Variable -->
<script type="text/javascript">
function main(){
Number.prototype["Ϡ"] = function(y){ return this + 2 * y; };
var Ϡ = "Ϡ";
var result = (2)[Ϡ](2);
var out_string = "Formula is: 2 Ϡ 2<br>";
out_string += "Where: (R,Ϡ), x Ϡ y = x + 2y<br>";
out_string += ("Result is: " + result);
document.getElementById( "output" ).innerHTML = out_string;
console.log( result );
// Formula is: 2 Ϡ 2
// Where: (R,Ϡ), x Ϡ y = x + 2y
// expands out to result = 2 + 2 * 2;
}
</script>
</head>
<body onLoad="main()" onmousedown="" onmouseup="" onmousemove="">
<div id="output">Initial Text That Should Be Replaced</div>
</body>
</html>
This also leads to reeeally weird stuff that might work (need to test as of 8/26/2024) like operator objects with properties, such as ӕ.pp, that applies (x+(pp++)*y) with each application of the operator. (I'm not sure if math even does that... like anywhere)
Anyway, this technically provides very short operator notation, with what may be almost more condensed notation than any actual writer desires (and bonus pinata features!)
I have also made a small javascript library including this feature. It can be found at: https://github.com/conceptualGabrielPutnam/simple_lib_js
A functional example using this library based method can be tried at: https://raw.githack.com/conceptualGabrielPutnam/simple_lib_js/main/StarterHTML.html
Notably, the original author @Ionică Bizău eventually answered their own question with: https://github.com/IonicaBizau/js-custom-operators that is also a rather elegant way to deal with the issue (although it requires esprima and escodegen and code-mirror for viewing)
Upvotes: 1
Reputation: 13818
Since JS doesn't allow to define custom operators now and if you don't want to use complex solutions you can take a look on extending Number
class with needed functions (operators), for instance:
Number.prototype.o = function(y) {
return this + 2 * y;
};
// 2 ∘ 2
let n = 2;
const r1 = n.o(2);
console.log(r1); // Prints: 6
// OR
const r2 = (2).o(2);
console.log(r2); // Prints: 6
With this approach you can make complex math expressions by chaining operators each after another:
Number.prototype.pow = function(exponent) {
return Math.pow(this, exponent);
};
Number.prototype.sqrt = function() {
return Math.sqrt(this);
};
// √((2 ∘ 2)² - 11)
const r3 = (((2).o(2)).pow(2) - 11).sqrt();
console.log(r3); // Prints: 5
Upvotes: 0
Reputation: 421
There are several tools, compilers, or language extensions providing such a possibility, and even using emojis and other stuff, that are uncommon in JavaScript itself. sweet.js
is the closest one I can remember, and also another JavaScript compiled tool might be useful.
Upvotes: 0
Reputation: 7332
Set of compiled to JS languages support custom operators.
I would highlight ReasonML (ocaml-syntax-readable-by-js-folks) and Bucklescript (ocaml-to-js-compiler) which makes custom operators look neat:
For example an operator to concatenate strings can look like:
let (>|<) = (list, seperator) => Belt.List.reduce(list, "", (a, b) => a ++ seperator ++ b);
which can then be used like:
[Styles.button, Media.Classes.atLeastTablet] >|< " "
The downside of all this is the fact it has to be written in such compiled-to-js language, and it comes with lots of pros and cons, but usually those languages have the appeal of tons of nice syntactic sugar you don't get in js/ts
Upvotes: 2
Reputation: 17384
Given the somewhat new tagged template literals feature that was added in ES6 one can create custom DSLs to handle embedded expressions such as these including different algebraic symbols.
ex. (run in stackblitz)
function math(strings, x, y) {
// NOTE: Naive approach as demonstration
const operator = strings[1].replace(/\s/gi, "");
if (operator == "∘") {
return x + 2 * y;
}
else if (operator == "^") {
return Math.pow(x, y);
}
else {
return `Unknown operator '${operator}'`;
}
}
console.log(math`${2} ∘ ${2}`)
Note that since tagged template literals don't necessarily return strings as results they can return more complex intermediate AST like structures to build up an expression that can then be further refined and then interpreted while keeping close to the domain specific language at hand. I haven't found any existing library that does this yet for Javascript but it should be an interesting and quite approachable endeavor from what it appears from what I know of tagged template literals and usage in such places as lit-html.
Upvotes: 8
Reputation: 276416
The short answer is no. ECMAScript (the standard JS is based on) does not support operator overloading.
As an aside, in ECMAScript 7, you'll be able to overload a subset of the standard operators when designing custom value types. Here is a slide deck by language creator and Mozilla CTO Brendan Eich about the subject. This won't allow arbitary operators, however, and the overloaded meaning will only be applied to value types. <- haha that ended up not happening.
It is possible to use third party tools like sweet.js to add custom operators though that'd require an extra compilation step.
I've answered with a solution from outside JavaScript using esprima - this is changing JavaScript and extending it, it's not native.
Upvotes: 32
Reputation: 1
I was asking this question too, and here's my answer:
function myCustomOperation(string){
var res = String.fromCharCode(9762);
var thing = string.replace(/☢/g," + 10 + ");
thing=thing.replace(/☣/g," * 2 + ");
thing=thing.replace(/☠/g," / 3 * ");
return [eval(thing),string+" = "+eval(thing)];
};
var thing = myCustomOperation("
3 ☠ 4
");
document.write(thing[1]);
Upvotes: 0
Reputation:
Read the comments below the answer.
Apparently you can't. Here is something close :
function exec(input) {
return Function(
'return ' + input.replace(/∘( *[\d.]+)/g, '+ 2 * $1') + ';'
)();
}
exec('2 ∘ 2'); // 6
Upvotes: 2
Reputation: 4154
The slightly longer then the short one is that Yes you can, but its a bit more involved then what you did in Math class
To extend the language with new constructs you can use a transformer like http://esprima.org/ or any of the others. You need to define your syntax, write the parser to parse your statement and finally add the actual code to do the math parts. When these parts is in place you have made a new language that works just as javascript but with the added support of the ∘
operator.
Its really not that hard to add new syntax, here is facebooks example how they add => arrow function syntax
https://github.com/facebook/jstransform/blob/master/visitors/es6-arrow-function-visitors.js
Upvotes: 1
Reputation: 97641
You can add pseudo-operators via methods on Number.prototype
:
Object.defineProperty(Number.prototype, 'myOp', {
value: function(that) {
return this + 2 * that;
}
});
Then all of this syntax will work
alert( (2).myOp(2) )
alert( 2 .myOp(2) )
alert( 2..myOp(2) )
alert( 2.0.myOp(2) )
2.myOp(2)
does not work because the period is treated as a decimal point
Upvotes: 5
Reputation: 971
No. JavaScript does not support operator overloading . but you can make a class method for doing this
var mathClass = function(value){
this.value = value;
}
mathClass.prototype.toLaw = function(){
return 2 * this.value;
}
var y = new mathClass(2)
2 + y.toLaw(); //2 + 2 * y
Upvotes: 3
Reputation: 119867
No. You can't do that in JS.
The closest you can have IMO is to implement your own object which has a chainable interface, aka "fluent" syntax. That way you can operate as if you were speaking out in sequence.
var eq = new YourEquationObject();
// Then operate like 1 - 2 * 3
eq.add(1).sub(2).mul(3);
Details are up to you though. Just giving out an idea.
Upvotes: 5