Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

not actually readable #1

Open
BlackCapCoder opened this issue Sep 5, 2018 · 0 comments
Open

not actually readable #1

BlackCapCoder opened this issue Sep 5, 2018 · 0 comments

Comments

@BlackCapCoder
Copy link

BlackCapCoder commented Sep 5, 2018

I am sad to say, but I don't think that your readable-operators are actually readable 馃樋. You see, operator to me means inline function call, but that is in fact the opposite of what your library does:

Inline:

x + y * z

Readable-operators:

applyOperator(ro.add, x, applyOperator(ro.multiply, y z));

Judging by the name, what I actually thought that your library would do was to give me a way to define my own inline operators.

You might not be aware of this, but it is actually possible to redefine the built in operators in javascript! Here are a couple of ways to do so:


valueOf

Whenever you use one of the operators + - * / % & | ^ << >> >>> < <= > >= on an object, javascript will call the valueOf function on your object. Here I exploit this to redefine + to mean *:

function Mul (x) {
  this.val = x;
  this.valueOf = function () {
    if (Mul.others === undefined) Mul.others = [];

    let sum = 0, prod = 1;
    for (let x of Mul.others) {
      sum += x; prod *= x;
    }

    Mul.others.push(this.val);

    return prod * this.val - sum;
  };
}

const a = new Mul (2);
const b = new Mul (3);

// Jokes on you javascript- addition is now multiplication!
console.log(a + b); // prints 6 (2*3), not 5 (2+3)

Proxies

Proxies let you intercept has, get and set, which is used to look for members of your object when you do obj.member, so you can use it to redefine ., = and things like += and *=! Here I redefine . to mean function-composition:

let pfree = ctx => f => new Proxy (f, {
  has: (t, p) => p in t || p in ctx
, get: (t, p) => {
    let k = p in t? t[p]: ctx[p];

    if (k instanceof Function) return (
      function fetch (_k) {
        return pfree (ctx) ( x => ( q => q instanceof Function
                                       ? fetch (q)
                                       : t (q)
                                  ) ( _k(x) )
                           )
      })(k);

    return k;
  }
});


with (pfree (global) (x => x)) {
  add = x => y => x + y;
  inc = add (1);

  addTwo = inc . inc
  addSix = addTwo . add (3) . inc

  console.log(addTwo(3)); // Prints 5, same as inc(inc(3))
  console.log(addSix(2)); // Prints 8, same as addTwo(add(3, inc(2)))
}

Detecting operators

In the example where I redefined + to mean *, I also redefined all the other operators too! How do we find out which operator was used when javascript only calls valueOf (This also applies to proxies when you do += and similar.)? Why you look at the answer that javascript produces of course!

function Mul (x) {
  this.val = x;

  this.valueOf = function () {
    if (Mul.prod === undefined) Mul.prod = 1;
    if (Mul.sum  === undefined) Mul.sum  = 0;
    Mul.prod *= this.val;
    Mul.sum  += this.val;
    return 1;
  };
}

Mul.answ = function (witness) {
  let sum = Mul.sum, prod = Mul.prod;
  Mul.sum = 0; Mul.prod = 1;

  if (witness == 1) return sum;   // * was used, return sum!
  if (witness != 1) return prod ; // + was used, return product!
};


const a = new Mul (2);
const b = new Mul (3);

console.log(Mul.answ(a + b)); // Prints 6 (a*b)
console.log(Mul.answ(a * b)); // Prints 5 (a+b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant