Implementing operator overloading in Javascript via a transpiler - javascript

One of the problems, for some of us, with Javascript is the lack of operator overloading. This makes writing numeric libraries awkward. For instance, we might want to write something like:
var a = new BigInteger(5);
var b = new BigInteger(10);
var c = a + b;
A possible solution is to transpile a language with operator overloading to Javascript. While feasible -- by replacing operators by function calls and type checks -- the consensus seems to be that this is impossible without killing performance. CoffeeScript has rejected the idea for this reason:
https://github.com/jashkenas/coffee-script/issues/846
But are there really no clever solutions?
For instance, it might be possible hoist type checks out of tight loops or to use some other pipeline where modern JS compilers can optimize away added cruft when the types are numeric.
Ideas?

Are you really sure you need your big numbers to be useable by old functions written with normal numbers in mind (that use the traditional operators)? If you only need the overloading for your own convenience on functions you cave control over you might be able to get by by using a different, custom operator for bignums.
For example, you could write a compiler to safely convert
var d = a <+> b <*> c;
into
var d = (a).add((b).multiply(c));
or perhaps, if you want automatic conversions...
var d = toBignum(a).add(toBignum(b).multiply(toBignum(c)));
I don't really see you being able to force overloading on an existing implementation without a big hassle. While you could teoretically replace all occurences of + with <+> and so on, current Javascript implementations are not optimized for this and I don't even want to start thinking what would happen if you tried to pass a bignum to one of the native C++ functions that are under the hood.
edit: Not needing to override the base integer class is the important point here (note how in the link you gave, overriding is the first thing the guy wants...). I don't think you will be able to find some kind "magic" optimization though as you have no control over which of the many JS implementations is being used by the client.
If you really don't like a custom operator like <+> the only way to distinguish a normal + operator (you shoudln't meddle with) from a fancy + operator (you want to do bignum stuff with) would be forcing some kind of ad-hoc typing system on top of Javascript, perhaps via comments, custom syntax or (as mentioned in a comment) hungarian notation. Just settling for a custom operator name you hate less would be less hackish, IMO.

Have a look how Scala implemented Operator Overloading:
They defined that every operator is a method call on an object, so your example would be:
var c = a["+"](b);
If you stop here, you could trivially implement method overload, the function would have to check the values passed by param. If you want to develop a better solution take Odersky's Programing in Scala book and some time to read all their ideas how they've solved the problem (which is a very nice solution!)

Related

Javascript - Create Own Condition/Control Flow

is it possible to create your own condition/control flow syntax in js? for example:
when( condition ) {
// execute code
}
this would add some sort of listener to a variable/object and execute whenever the condition is true.
I may just have to create my own programming language.
This is actually two questions:
Can syntax be added to JavaScript directly?
Can I set up code that runs when a condition changes?
The answer to the first is no. You can use preprocessing like sweet.js macros to accomplish that but its non-trivial.
The answer to 2 is yes, you can accomplish this in any ES 5 compliant environment (IE 9+):
var condition = {val: null};
Object.defineProperty(condition, "isTrue", {
set: function(val) {
if (val && !this.val) {
runSomeCodeYouWantRun();
}
this.val = val;
},
get: function() {
return this.val;
}
});
So whenever any code changes condition.isTrue the specified code will be run if the change is truthy. But for situations like this I prefer less ad-hoc approach. ES 2015 Proxy traps make this much cleaner (IMHO) but support isn't quite there yet. What you really are looking for here to get the job done today is an Observable.
Also note that writing a language to solve a problem like this is roughly equivalent to building a car out of spare parts to drive to the store for groceries. Just buy a car.
Welcome to the wonderful world of JavaScript transpilers.
JavaScript in and of itself does not have any utilities for creating your own syntax. In response to this, many tools exist online and in the NPM repositories that add just this sort of feature to JS by translating it to browser-compatible JavaScript. Here's a small sampling:
Babel.js adds ES6 syntax to ES5 JavaScript
Browserify adds Node.JS's require() functionality
Uglify.JS compresses JS into the smallest form possible that will still execute the same way
TypeScript (while more technically its own language) adds static type-checking to JavaScript
All of these transpilers, however different, all work the same way: they parse the source file(s) to an abstract syntax tree (or AST), run some transformations on that tree, and then spit out the resulting JavaScript file. If you wanted to create your own special syntax in JavaScript, you would do more or less the same thing. (Uglify.JS stands out as being particularly customizable in this regard).
All of that said, none of these transpilers fundamentally change the way that JavaScript works - you still have to translate whatever fancy syntax you want to use into plain, browser-executable JavaScript. This means that although you will be able to write your when(){} block syntax, the expression inside the parentheses cannot be a simple Boolean expression, but must involve something like an Observable object that inserts a callback (Knockout.JS does have a tool for doing this out of an expression built from its Observables).

Any linter to warn about side-effects in JavaScript?

With the flexibility of JavaScript, we can write code full of side-effects, or just purely functional.
I have been interested in functional JavaScript, and wanting to start a project in this paradigm. And a linter about that can surely help me gathering good practices. Is there any linter to enforce pure functional and side-effect free style?
Purity Analysis is equivalent to Solving the Halting Problem, so any kind of static analysis that can determine whether code is pure or impure is impossible in the general case. There will always be infinitely many programs for which it is undecidable whether or not they are pure; some of those programs will be pure, some impure.
Now, you deliberately used the term "linter" instead of static analyzer (although of course a linter is just a static analyzer), which seems to imply that you are fine with an approximate heuristic result. You can have a linter that will sometimes tell you that your code is pure, sometimes tell you that your code is impure, and most times tell you that it cannot decide whether your code is pure or impure. And you can have a whitelist of operations that are known to be pure (e.g. adding two Numbers using the + operator), and a blacklist of operations that are known to be impure (e.g. anything that can throw an exception, any sort of loops, if statements, Array.prototype.forEach) and do a heuristic scan for those.
But in the end, the results will be too unreliable to do anything serious with them.
I haven't used this myself but I found this plugin for ESLint: https://github.com/jfmengels/eslint-plugin-fp
You cannot use JS commpletely without side effects. Every DOM-access is a side effect, and we could have an argument wether the whole global namespace may also fall under that definition.
The best you can do is, stay reasonable. I'm splitting this logically into two groups:
the work horses (utilities): their purpose is to take some data and to process it somehow. These are (mostly) side effects free. mostly, because somethimes these functions need some state, like a counter or a cache, wich could be argued to be a side effect, but since this is isolated/enclosed into these functions I don't really care. like the functions that you pass to Array#map() or to a promises then(), and similar places.
and the management: these functions rarely do some data-processing on their own, they mostly orchestrate the data flow, from whereever it is created, to whatever processing(-utilities) it has to be run, up to where it ends, like modifying the DOM, or mutating an object.
var theOnesINeed = compose(...);
var theOtherOnesINeed = compose(...);
var intoADifferentFormat = function(value){ return ... }
function(event){
var a = someList.filter(theOnesINeed).map(intoADifferentFormat);
var b = someOtherList.filter(theOtherOnesINeed);
var rows = a.concat(b).map(wrap('<li>', '</li>'));
document.querySelector('#youYesYou').innerHTML = rows.join('\n');
}
so that all functions stay as short and simple as possible. And don't be afraid of descriptive names (not like these way to general ones :))

JavaScript type checking and exceptions in the context of Prototype constructors?

I'm building my first open-source JavaScript library as a node module, it's solving a very simple problem and thus it's a very simple module, specifically, it is a single prototype object.
To offer context, I'm from a purely web-tech background and only in the past year have I started to look into other languages, falling in love with statically typed, truly OOP and class-oriented languages and I'm beginning to see the breadth of pros and cons for the languages on either side of the camp.
As far as I understand, when constructing a class with class-oriented you should return nil to specify that construction has failed allowing a user to check with if(instance === nil) for it's success. Alternatively I've seen return 421 for example to provide an error code, I then also assume some also return string e.t.c. But importantly, I've seen that you shouldn't throw an exception.
Is this correct? Also what are the reasons for that? Is this also a problem with prototype-oriented languages or does javascript's dynamic nature make it acceptable?
This leads onto my next question, I've seen a lot of javascript libraries over the years, had a tinker and whatnot. I've found that it's rare to not only to build prototypes in an OOP-ish pattern but it's also rare to come across any frequently implemented type detection or type checking, many people are relying on the convenience of the dynamic typing to offer that productivity boost, but I'd like to mix up the pros and cons of each type system by starting with dynamically typed but also introduce a more stable architecture using some statically typed patterns and methodologies.
To get to the point, is it an acceptable (or even good?) practice to heavily type check javascript scripts? I would love to add serious type checking code to my prototypes constructor and methods but as it's an open-source project I'm worried how the community will approach it, would they want it to be more dynamically typed? I can only assume many people use dynamically typed languages for their... uhh.. dynamic typing, but its worth a ponder.
DISCLAIMER
I understand have seen that many people say javascript is "untyped" rather than "dynamically" typed, but using dynamic purely for its proliferation.
TLDR-Q1: Can I throw exceptions in constructor methods? What about in javascript prototypes? Why!? How should I handle it?
TLDR-Q2: Can I introduce heavy type checking and throw exceptions to give javascript scripts a poor mans static type? Do developers like this? Am I being ignorant and this a really common thing?
TLDR-Q1: Can I throw exceptions in constructor methods? What about in
javascript prototypes? Why!? How should I handle it?
Yes, you can throw exceptions in a constructor. If truly invalid arguments have been passed, then that is probably the cleanest way to do things.
I, myself, would not generally design an expected path of the code to throw an exception, but would instead reserve it for the type of error that probably signifies bad data or wrong usage by the programmer. Exceptions get logged nice and cleanly in the debug console and are one of the quickest ways to communicate to someone using your constructor that they've messed up as it will get logged and you can put a nice descriptive message in the error object when you throw and the developer gets a stack trace.
Returning null is not such a clean or helpful way and adds code the developer probably doesn't normally need to check for null all the time.
TLDR-Q2: Can I introduce heavy type checking and throw exceptions to
give javascript scripts a poor mans static type? Do developers like
this? Am I being ignorant and this a really common thing?
You can write Javascript type checking as much as you need. IMO, you should only do so when you're trying to determine if an argument passed in is valid or not. If you need a string and the developer passes in a number and a numeric string is a reasonable input for the function, then I don't see why you should not just use Javascript's string conversion automatically and let things go.
Javascript developers like type checking when it helps them identify a mistake they've made. Javascript developers don't like type checking when it's just being pedantic and an auto or explicit type-conversion would have worked just fine.
Also keep in mind that you should rarely insist that a passed object is a particular type of object (say using instanceof) because it should be perfectly valid to pass any object that works like the expected object. For example, a promise in Javascript can pretty much be any object that has the desired methods that follow the proper specification. It does not have to be one particular type of object class with one particular constructor.
Javascript isn't a strongly typed language and there really is no reason to try to make it behave like it is something that it isn't. Check types when that's required for the proper operation of your code, not because you're trying to make Javascript behave as strictly as Java. I wouldn't suggest adding type checking just because you think all languages should have type checking. If that's your line of thinking, then perhaps you should write in TypeScript or something like that that adds type specification to the language.

Implementing prototype method

If I implemented a method x on a String like :
String.prototype.x = function (a) {...}
And then the new version of javascript actually implements the x method, but on the another way, either returning something different than my implementation or function with more/less arguments than my implementation. Will this break my implementation and override it?
You'll overwrite the default implementation.
Any code that uses it will use yours instead.
There was a proposal for scoped extension methods and it was rejected because it was too expensive computationally to implement in JS engines. There is talk about a new proposal (protocols) to address the issue. ES6 symbols will also give you a way around that (but with ugly syntax).
However, that's not the punch - here's a fun fact no one is going to tell you.
No one is ever going to implement a method called x on String.prototype
You can implement it and get away with it. Seriously, prollyfilling and polyfilling is a viable, expressive and interesting solution to many use cases. If you're not writing a library I think it's acceptable.
No, you'll be overriding the default implementation of said function, from the point at which you've declared/defined it. The "new" implementation will function in its native behavior, until your implementation's defined.
var foo = 'some arbitrary string';
console.log(foo.indexOf('s')); // logs [0]
String.prototype.indexOf = function(foo, bar) { return 'foo'; };
console.log(foo.indexOf()); // logs [foo]
Illustration: http://jsfiddle.net/Z4Fq9/
Your code will be overriding the default implementation.
However if the interface of your method is not compatible with the standard one the libraries you may use could depend on the standard behavior so the program as a whole could break anyway with newer versions of the libraries.
In general is a bad idea doing something that could break if others do the same: what if another library thinks it's a good idea to add a method x to the standard string object prototype? Trying to avoid conflicts is a must for libraries but it's also good for applications (and if an application is written nicely then a lot of its code is probably quite similar to a library, and may evolve in a library later).
This kind of "patching" makes sense only to provide the a standard method for broken or old javascript implementations where that method is absent. Patching standard prototypes just because you can is a bad idea and will make your code a bad neighbor with which is difficult to share a page.
If the implementation of x is from a new version of Javascript, it's part of the core, therefore when you write String.prototype.x... it will be already there, and you will overwrite it.
Best practice in this kind of things is to write
if( !String.prototype.x ){
String.prototype.x = function ...
//your

Assigning dynamic variables through JavaScript functions

I've been working on a pet project where I've been creating a functions only JS framework... and wasn't sure if there was any way to simplify the following... in this case Dynamic variable assignment...
String.prototype.is = function(x) {window[this]=window[this]||x;}
"a".is(42);
alert(a); // window.alert shows 42
Is there any simpler way to do this with functions? This is for the sole purpose of achieving a functions-only framework... so using "a = 42;" is not permitted... I want this to be usable for not just numbers, but strings, arrays, booleans, dates, etc.
There's a problem in your idea, it's not a good practice to change the prototype of native types. This can result in an unexpected (and sometimes almost impossible to debug) behavior when using with third-party code.
No problem in your main idea, but I suggest you to wrap the objects you want to manipulate with another under your full control and so decorate these objects with the additional behavior provided by your wrapper. This is the jQuery approach, a lot safer.
You can use new ES 5 getters and setters.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/get

Categories