Simulating pointers in JavaScript, part 2

In the previous post we saw how we can simulate pointers in JavaScript using closures. When we want to create a pointer to a variable, we actually create a function that references that variable:

    var x;
    // ...
    var xptr = function(val) {
        if (arguments.length > 0) x = val;
        return x;
    }

This scheme works, but it means duplicating the function code every time a pointer is created.

Usually you can prevent code duplication by factoring out the common code. When I considered it, my first thought was to write a function (a pointer constructor) that accepts a variable and returns a pointer to that variable. But this brings us back to the original problem of creating a pointer, since in JavaScript you don’t pass a variable to a function; you only pass its value.

What we need is actually a kind of macro — a function that more or less rewrites part of the source code. The macro would ideally inject the pointer definition shown above, with the correct variable name, whenever we need it. The closest thing to macros in JavaScript is eval(), which accepts a string and executes it as part of the current environment. We’ll just use a function that accepts a variable name and returns a script excerpt that does what we want:

function makePtr(varName) {
    return "(function(_val) {\n" + 
        "    if (arguments.length > 0) " + varName + " = _val;\n" + 
        "    return " + varName + ";\n" +
        "})";
}

function swap(ptr1, ptr2) {
    var t = ptr1();
    ptr1(ptr2());
    ptr2(t);
}

function testit() {
    var x = 1, y = 2;
    print(x,y);
    swap(eval(makePtr("x")), eval(makePtr("y")));
    print(x,y);
}

testit();

The script is identical to the original one, except that function makePtr() writes the code for us — we just need to execute the code with eval(). (Again, if you don’t have a print() function you’ll have to make one yourself).

So now we can create pointers easily. The syntax for using the pointers is still not good enough: for example, assignment doesn’t look like assignment at all. Later I’ll show a possible solution for this.

About these ads
Post a comment or leave a trackback: Trackback URL.

Comments

  • s3mm3l  On May 2, 2013 at 19:37

    My attempt uses the array-like bracket syntax to access the variables:
    function makePtr(parent, propertyName){
    return function(val){
    if (arguments.length > 0){parent[propertyName] = val;}
    return parent[propertyName];
    };}
    Test:
    var x = 1;
    var y = {value: 2};
    var xPtr = makePtr(window, ‘x’);
    var yPtr = makePtr(window, ‘y’);

    function swap(ptr1, ptr2) {
    var t = ptr1();
    ptr1(ptr2());
    ptr2(t);
    }

    swap(xPtr, yPtr);

    // et voila!
    What do you think?

    • Amnon  On May 2, 2013 at 22:27

      It works only if you have a name for the parent scope. For example, I don’t think it would work with local variables.

      • s3mm3l  On May 3, 2013 at 15:47

        Yes you are right, there is now way to get to the function invocation “call object”.
        Therefore my solution with the bracket access works just for properties of the global or some user object.

        However since I’ve been warned about the security of the eval function, I’ll perhaps accept this limitation.
        For example:
        var yPtr = makePtr(‘(function(){console.log(“I could do anything right now”);})()’);

    • Amnon  On May 3, 2013 at 17:08

      eval is only insecure if you give it user-supplied data. There will be no problem if you always use a constant string as a parameter (makePtr(‘x’)). You could also add a check to the function to make it accept only identifiers.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: