I'm using dynamic scoping to simulate pointers in JavaScript as follows:
var ptr = (function () {
var ptr = "(" + String(function (value) {
if (value === void 0) return upvalue;
else upvalue = value;
}) + ")";
return function (upvalue) {
return ptr.replace(/upvalue/g, upvalue);
};
}());
function swap(xptr, yptr) {
var t = xptr();
xptr(yptr());
yptr(t);
}
var x = 2;
var y = 3;
alert([x, y]);
swap(eval(ptr("x")), eval(ptr("y")));
alert([x, y]);
Is there any other way to achieve the same results (i.e. without resorting to eval
)? It just seems like too much boilerplate.
Since the only thing you're using the pointer for is to dereference it to access another variable, you can just encapsulate it in a property.
function createPointer(read, write) {
return { get value() { return read(); }, set value(v) { return write(v); } };
}
To create a pointer, pass the accessor methods which read and write the variable being pointed to.
var i;
var p = createPointer(function() { return i; }, function(v) { i = v; });
// p is now a "pointer" to i
To dereference a pointer, access its value. In other words, where in C you would write *p
here you write p.value
.
i = "initial";
alert(p.value); // alerts "initial"
p.value = "update";
alert(i); // alerts "update"
p.value += "2";
alert(i); // alerts "update2"
You can create multiple pointers to the same variable.
var q = createPointer(function() { return i; }, function(v) { i = v; });
// q is also a "pointer" to i
alert(q.value); // alerts "update2"
q.value = "written from q";
alert(p.value); // alerts "written from q"
You can change what a pointer points to by simply overwriting the pointer variable with another pointer.
var j = "other";
q = createPointer(function() { return j; }, function(v) { j = v; });
// q is now a "pointer" to j
You can swap two variables through pointers.
function swap(x, y) {
var t = x.value;
x.value = y.value;
y.value = t;
}
Let's swap the values of i
and j
by using their pointers.
swap(p, q);
alert(i); // alerts "other"
alert(j); // alerts "written from q"
You can create pointers to local variables.
function example() {
var myVar = "myVar as local variable from example";
var r = createPointer(function() { return myVar; }, function(v) { myVar = v; });
swap(p,r);
alert(i); // alerts "myVar as local variable from example"
alert(myVar); // alerts "other"
}
example();
Through the magic of closures, this gives you a way to simulate malloc.
function malloc() {
var i;
return createPointer(function() { return i; }, function(v) { i = v; });
}
var p = malloc(); // p points to a variable we just allocated from the heap
p.value = 2; // write a 2 into it
Your magic trick works too:
var flowers = new Misdirection(
createPointer(function() { return flowers; }, function(v) { flowers = v; }));
flowers.abracadabra();
alert(flowers);
function Misdirection(flowers) {
this.abracadabra = function() {
flowers.value = new Rabbit;
};
}
function Rabbit() {
this.toString = function() { return "Eh... what's up doc?" };
}