0 Comments

I am not sure if this is of any use or not.  While playing around with trying to find a more elegant syntax for my LINQ-like querying code, I accidentally bumped into this topic.

Say... I want to be able to write something like:

var peoples = [ ... ]; 

function from() {
    // do something with the arguments passed here...
} 

from (a, in, peoples)

This will never work since "a" is undefined and "in" is a JavaScript keyword.  What I wanted to do is cache the arguments that were passed to the "from" function into a local buffer so I can do something with it later inside the function.

There are several problems here that are related to JavaScript global object.

Problem 1: 'a' is undefined will be thrown when the "from" function is called.  Now, how can we possibly remedy this?  Well, we can declare "a" as a global variable and assigned something to it (does not matter what), but that's kind of weird.  Is it possible to inject "a" into global on the fly?  Well, yes, somewhat.  You can use try and catch block and detect the "'a" is undefined" error that was thrown and have the catch block inject the missing variable as a global variable.

Example:

try {
    from(a, inside, people);
} catch(e) {
    var m = e.message.match(/^'(.+)' is undefined$/);
    if  (m) {
        this[m[1]] = {};
    }
}

Well, this will inject variable 'a' into the global object (this). If you need a proof for this, just output 'a' somewhere after the above code. (i.e. WScript.Echo(a)). Unfortunately, this route does not take me to where I want since once the error is caught the function will never complete the call anyway.  Hmm...

Problem 2: Ignoring the 'in' Syntax error, the second thing that bugs me is how to get the function parameter variable name (in this example, I want to be able to get the name of the people object (which is "people").  So, how can you reflect over JavaScript global object to get this value?

After a little experimentation, I finally found the answer.  Take a look at the code below:

function GetGlobalObjectName(aGlobalMember) {
    var global = this; //when the function is called as a function, "this" will point to global object
    for (var object in global) {
        if (global[object] === aGlobalMember) {
           return object;
         }
    }
    return null;
}

now I can modify my "from" function as follow:

function from() {
    for (var x = 0, a = arguments, k = a.length; x < k; x++) {
        var v = a[x];
        if (typeof(v) === "object") {
           WScript.Echo(GetGlobalObjectName(v);
        }
    }
}

Now I can pass any object to my "from" function and if it detects that the argument type is "object" it will get the name of that object as defined in the global.  Afterward I can use that name string to do whatever I want.  In this example, perhaps use it to construct dynamic JavaScript statement from all the arguments being passed and do an eval() on it.

Hmm... with all these problems, I doubt I can get the syntax structure to anywhere close to C# LINQ... alternatively, mixing string into the function call might work, but that's just messy Sad smile.

from("a", "in", people)

Hmm... frankly I like the current syntax that I have, minus the orderby array part that is still in string.

from(people)
    .where(function(n) { n.Age > 19 && n.Age < 31) })
    .select(function(n) { return { FullName : n.FirstName + " " + n.LastName }; });

To me that seems a little bit a elegant than mixing string substitutions into the function argument. 

I don't anticipate that I'll get anywhere far with this in regard of finding a more elegant way to write my query syntax, but this is sure is one fun trip into JavaScript internals.  I learnt something new today Smile .  It's all good.

0 Comments

One thing I hate about Jakarta is its traffic. Driving from home to the office, vice versa, usually take me about 1 hour or more depending on the traffic on average. For a while, I survived the trip by listening to radio stations, playing Pocket Sudoku or reading e-books on Windows Mobile device.  But sometimes, the radio stations do not broadcast anything that is suitable to my taste.  Reading or playing Sudoku / any game while driving is just too much of a distraction and really only doable while waiting in line on the traffic light stops, especially when you don't have a driver. Listening to CD quickly become a boring thing since you know you already heard the song for x amount of times before.  So what am I to do? Who me? Isn't there a better way to commute that at least can be useful in the long run?

I knew for a long time I wanted to download podcasts relating to development / IT stuffs and listen to them while commuting.  About two months ago I finally upgraded my faithful Nokia 6600 with a Sony Ericsson K800i equipped with 1 GB of memory and starting from that day forward, I got my wish.  I downloaded a bunch of podcasts from DotNetRocks,HanselMinutes, etc. and they always accompany me wherever I travel now.  I know, I know, I can do better w/ an iPod, but the cellphone works just fine for my need, beside I don't have to carry lots of gadgets.

How about you?  What do you do while you are commuting to make it better?

0 Comments

Just coding for coding sake, I decided to try implement a LINQ-like query in JavaScript.  And the result is as follow:

(function() {
    'use strict';
    
/**
 * Javascript LINQ-like query proof of concept
 * Jimmy Chandra - 16 July 2007
 * Updated on 2015-02-22
 */
 
/*
 * Quicksort implementation for JavaScript Array (based on 
 * http://en.literateprograms.org/Quicksort_(JavaScript)),
 * modified to pass a function delegate for the comparison function.
 */
Array.prototype.swap = function(i, j) {
    var a = this, 
        t = a[i];
    a[i] = a[j];
    a[j] = t;
};
 
function partition(a, s, e, p, l) {
    var v = a[p],
        t = s,
        i;
    a.swap(p, e - 1);
    for (i = s; i < e - 1; i++) {
        if (l(a[i], v)) {
            a.swap(t, i);
            t++;
        }
    }
    a.swap(e - 1, t);
    return t;
}
 
function qsort(a, s, e, l) {
    var p;
    if (e - 1 > s) {
        p = s + Math.floor((e - s) / 2);        
        p = partition(a, s, e, p, l);
         
        qsort(a, s, p, l);
        qsort(a, p + 1, e, l);
    }
}
 
Array.prototype.quicksort = function (l) {
    qsort(this, 0, this.length, l);
};
 
 
/*
 * JavaScript LINQ-like query engine sample implementation
 */
function _each(o, l, a) {
    var r = [],
        m = o.length,
        i;
         
    if (l) {
        for (i = 0; i < m; i++) {
            if (l(o[i])) {
                a(r, o, i);
            }
        }
    } else {
        for (i = 0; i < m; i++) {
            a(r, o, i);
        }
    }
    return r;   
}
  
function from(o) {
    return new From(o);
}
 
function From(o) {
    /*jshint validthis: true */
    this.items = o; 
}
  
From.prototype.where = function(l) {
    return new Where(
        _each(this.items, l, 
            function(r, o, i) {
                r.push(o[i]);
            }));
};
  
function _select(l) {
    /*jshint validthis: true */
    return _each(this.items, l, 
        function(r, o, i) {
            r.push(l(o[i]));
        });
}
  
From.prototype.select = _select;
 
function Where(o) {
    /*jshint validthis: true */
    this.items = o;
}
  
Where.prototype.select = _select;
Where.prototype.orderby = function(a) {
    var f, 
        k = a.length,
        r = _each(this.items, null,
        function(r, o, i) {
            r.push(o[i]);
        });
     
    if (k === 1 && a[0] === "") {
        f = function(i, j) { return i <= j; };
    } else {
        f = function(i, j) {
            var l = "", 
                r = "";
            for (var n = 0; n < k; n++) {
                l += i[a[n]];
                r += j[a[n]];
            }
            return l <= r;
        };
    }
     
    r.quicksort(f);
     
    return new Orderby(r);
};
  
function Orderby(o) {
    /*jshint validthis: true */
    this.items = o;
}
 
Orderby.prototype.select = _select;
  
/*
 * Javascript LINQ-like querying example
 */
 
var numbers = [17, 6, 12, 14, 20, 13, 10];
  
var b = 
    from (numbers).
    where (function(n) { return n > 9 && n < 20; }).
    orderby ([ "" ]).
    select (function(n) { return n; });
     
 
for (var x = 0, l = b.length; x < l; x++) {
    console.log(b[x]);
}
 
 
var peoples = [ 
    { FirstName : "John", LastName : "Doe", Age : 29 },
    { FirstName : "Jane", LastName : "Doe", Age : 33 },
    { FirstName : "Mary", LastName : "White", Age : 31 },
    { FirstName : "Barry", LastName : "White", Age : 31 },
    { FirstName : "Kevin", LastName : "Black", Age : 31 },
    { FirstName : "Anna", LastName : "Smith", Age : 1 }];
     
 
var p =
    from (peoples).
    where (function(n) { return n.LastName === "Doe" || n.LastName === "White"; }).
    orderby([ "Age", "LastName", "FirstName" ]).
    select(function(n) { return { FullName : n.FirstName + " " + n.LastName, Age : n.Age }; });
     
 
for (x = 0, l = p.length; x < l; x++) {
    console.log(p[x].FullName + ":" + p[x].Age);
}
}());

Run it on jsfiddle: http://jsfiddle.net/jchandra/6ugyxc2s/

Fun :)

0 Comments

Came across this site while reading AJAXIAN.
Basically, it's a benchmark on different AJAX method.  It measures the usage of bandwidth and execution time.
So far, for pure AJAX, looks like it's AJAX using JSON serialization is the best choice.
For those using FLEX, FLEX using AMF3 serialization is your best bet.

0 Comments
  • Posted in:
  • Fun

Hmm... A co-worker of mine shared a video from YouTube and it's just too funny not to share it.  Don't worry, it's safe for the workplace…. But you are laughing and crying at the same time will certainly draw attention… You’ve been warned. LOL

Well… that one was okay…

 

But then I followed the link to this one….

And all hell breaks loose…ROFL