Igor Baklan (2016-06-03T15:59:43.000Z)
io.baklan at gmail.com (2016-06-03T16:05:28.660Z)
I think it would be also nice to have some "low level API" that would allow to provide some interceptor object, which will trap all operators invocations in some block of code. (at least for cases when both/some arguments of operation are not primitives). Then if this particular interceptor can't handle given arguments, it should be able to delegate execution of this operation to some "outer scope", assuming that at the out-most level is present some default handler that always executes/evaluates operations as it is specified now in JS. So in code it may look like: ```js const localOperatorsInterceptor = Object.freeze({ __proto__: null, // to prevent scope pollution when using this object with ``with``-statement [Symbol.operatorsInterceptor]: Object.freeze({ ["_+_"]: function(a, b, proceed) { console.log("operation(a+b):", a, b); return proceed(a,b); }, ["+_"]: function(a, proceed) { console.log("operation(+a):", a); return proceed(a); }, ["++_"]: function(a, proceed) { console.log("operation(++a):", a); // returned value will be assigned back to "target" variable/expression // and returned as result of (++_) return proceed(a); }, ["_++"]: function(a, proceed) { console.log("operation(a++):", a); // returned value will be assigned back to "target" variable/expression // former value of "target" variable/expression will become result of (_++) return proceed(a); } // etc }) }); with(localOperatorsInterceptor) { var res = {x:"y"} + {a:"b"}; // this should log: operation(a+b): ({x:"y"}) ({a:"b"}) console.log(res); // res should become NaN since interceptor delegates execution to default operators handler var doInc = function(x) { return ++x; }; res = doInc({foo: "bar"}); // this should log: operation(++a): ({foo: "bar"}) console.log(res); // res should stay equal NaN since interceptor delegates execution to default operators handler } ``` It is proposed to use ``with`` statement to localise block of code to which this interceptor is applied. Interceptor may be organised as frozen object with only one property which name is some "well-known symbol", for an instance ``Symbol.operatorsInterceptor``. Since it is not assumed that interceptor has "normal" (string named) properties (and has ``__proto__ == null``) it should generally not pollute code block scope with some extra names, but only affect how operators are executed/evaluated inside that block of code. Also if interceptor itself and handlers object too will be both frozen, then it should not break engine optimisation capabilities. Meaning that if some function expression is defined inside that ``with``-statement, than all operators inside that function can be resolved at function expression evaluation time (since all "withed" objects contents are final). Also it can be specified that even if interceptor handler object is not frozen, then anyway some snapshot of it state can be taken (and actually that handler snapshot may be used as effective operators handler for ``with``-ed block of code). So if this operators interceptor feature would be available then it would be possible to implement any custom system of symbol to operation mapping in different "third-party" operators overloading libraries, which can be also good at first time - to let people do some experiments in this area. Also for me it looks like a good thing to have possibility to control whether some system of operators will be applied to some code or not. In case of ``with``-based approach it is controlled "very" explicitly - unless you specify some ``with(someOperatorsInterceptor)`` no operators overloading will be applied to your code. An if you want override some operators in some sub-block of code, you can always span that sub-block with some other ``with(anotherOperatorsInterceptor)`` statement and ``anotherOperatorsInterceptor`` interceptor will take precedence over previous/outer one in target sub-block of code. Of course it would be more nice to use something like ``import`` instead of ``with``, like for example in Scala, ``import`` may serve like more convenient form of ``with``: **Scala( ``{ import obj._; /*some code*/ }`` ) <==> Js( ``with (obj) { /*some code*/ }`` )** [[1]](https://en.wikibooks.org/wiki/Scala/Import) [[2]](http://www.scala-lang.org/old/node/119.html) But since ``import`` is reserved for modules I am not sure whether it can be adapted to serve for this purposes too.