Friday, February 21, 2014

A few cool Javascript functions

For me,learning Javascript has been an extra-curricular activity,my work has never required me to use JavaScript at any time.In fact,as an app developer working on native Android apps,I am almost completely sealed off from it.So,I have never been obliged to learn to write code to handle DOM events or use jQuery and some of it's plugins to do cool things.

This left me free to just relax,unwind and experience new levels of puzzlement(http://www.merriam-webster.com/dictionary/puzzlement),bewilderment,embarrasment and frustration while exploring the language using blogs,books and the occasional video as my resources.Although it seems simple to access,the language had hidden layers giving the programmer a billion ways to shoot himself in the foot.And just like Android's million Runtime errors it appealed to me.And finally,the idea that a function isnt set in stone,that you could modify how it is called,who calls it and even what it is called on using other functions.

These are some interesting functions I have learnt about:

1.foreach,map and mapWith:


1:  var foreach=function(arr,fn)  
2:  {  
3:            var i;  
4:            for(i=0;i<arr.length;i++)  
5:            {  
6:                 fn(arr[i]);  
7:            }  
8:  };  
9:  var map=function(fn,arr)  
10:  {  
11:       var res=[];  
12:       foreach(arr,function(elem){  
13:            res.push(fn(elem));  
14:       });       
15:       return res;  
16:  };  
17:  var mapwith=function(fn)  
18:  {  
19:       return function(arr)  
20:       {  
21:            return map(fn,arr);  
22:       }  
23:  };  

The first two functions I encountered in Eloquent Javascript,the third I found in Javascript Allonge.This is the kind of tool that I dreamed of possessing when I first started programming,the ability to take an arbitrarily large array,process it and return the results as an array.I try and use these functions as much as possible.In fact,whenever I see an array in Javascript,I cant help but think of map and mapWith.

I have come to understand that Array.prototype now has a map method which is much simpler to use because it is called like this:


 var numbers = [1, 4, 9];  
 var roots = numbers.map(Math.sqrt);  

2.partial application and flip

Once upon a time,I saw a freaking crazy video featuring libraries and code I had no clue about but the idea was so cool that I decided to learn enough JavaScript to understand how to do it.The video was a talk about how underscore js' partial application,autocurry and certain other functions were not to the liking of the speaker Brian Lonsdorf's liking.This was another tool I wanted when I was learning to program,so it was another dream come true for me.



1:  var autoCurry=function(fn)  
2:  {  
3:       var n=fn.length;  
4:       return function()  
5:       {  
6:            var args=[];  
7:            var _slice=Array.prototype.slice;  
8:            function argsCollector()  
9:            {  
10:                 //if this function were not a named function,it's name would have to be looked up in the enclosing environment   
11:                 //instead of within itself...  
12:                 args=args.concat(_slice.apply(arguments));  
13:                 if(args.length>=n)  
14:                 {  
15:                      return fn.apply(null,args);  
16:                 }  
17:                 return argsCollector;  
18:            }  
19:            return argsCollector.apply(null,_slice.apply(arguments));  
20:       }  
21:  };  

I found this function in a gist on Github(dont exactly remember where).I also understand that the arguments Array-like-object inherits from Array.prototype since ES5 and therfore can have Array method calls performed on it.

Then there is my version,I got stuck on this for a long time because I was not updating the Array after concatenation.



1:  var myCurry=function(fn)  
2:  {  
3:       var len=fn.length;  
4:       var _slice=Array.prototype.slice;  
5:       var args=_slice.call(arguments,1);  
6:       console.log(args.length);  
7:       return function next()  
8:       {  
9:            var rem=_slice.call(arguments,0)  
10:            //args.concat(rem);//concat returns a new Array and returns another Array...  
11:            //Array.prototype.push.call(args,rem);  
12:            args=args.concat(rem);  
13:            console.log(args.length);  
14:            if(len<=args.length)  
15:                 return fn.apply(null,args);  
16:            else  
17:                 return next;  
18:       }  
19:  }  

There are versions of this function in underscorejs and wujs libraries as well,I took a look at the wu js  implementation while reading Angus Croll's blog and it really confused me but they have an interesting idea of calling it with a length parameter which means you can use


 var len=length || fn.length;  


There is also a version of this function written by John  Resig in the book Secrets of the JavaScript Ninja that someone posted on stackoverflow:



1:  Function.prototype.partial = function() {  
2:     var fn = this, args = Array.prototype.slice.call(arguments);  
3:     return function() {  
4:      var arg = 0;  
5:      for (var i = 0; i < args.length && arg < arguments.length; i++) {  
6:       if (args[i] === undefined) {  
7:        args[i] = arguments[arg++]; //This line is where the confusion is  
8:       }  
9:      }  
10:      return fn.apply(this, args);  
11:     };  
12:   };  

This function is called on another function either as a method or using call or apply,the function on which this has been called becomes this and is stored in fn.The interesting part is that if any of the arguments supplied to partial is undefined,it gets replaced by an argument supplied to the function.On the other hand it does not check for function's length.

I also loved the flip function which allows you to flip the arguments of a function,this is another function that I always wanted to do,just because it was cool,not much for practical utility of it.I found an implementation in the excellent Javascript Allonge:


1:  var flip=function(fn)  
2:  {  
3:    return function(first)  
4:    {  
5:      return function(second)  
6:      {  
7:        fn.call(null,second,first);  
8:      }  
9:    }  
10:  };  

This function uses only two parameters,to extend it to have more than two parameters .This is a function I created so that I could flip a function with multiple arguments conveniantly.I decided not to curry till all the arguments of a function are obtained,instead I decided to append undefined to the end of the array representing arguments in case there were fewer arguments than required.But before I could do this I flipped the array representing the arguments so that the function could theoretically run with enough parameters.I am still agonizing over slicing the array to the length specified.



1:  var flip2=function(fn,length)  
2:  {  
3:    var len=length || fn.length;  
4:    var args=Array.prototype.slice.call(arguments,1);  
5:    return function()  
6:    {  
7:     args=args.concat(Array.prototype.slice.call(arguments,0));  
8:     var missingArgs,argPadding;  
9:     if(args.length<=len)  
10:     {  
11:      missingArgs=Math.max(0,len-args.length-1);  
12:      argPadding=new Array(missingArgs);  
13:      args.reverse();  
14:      args=args.concat(argPadding);  
15:     }  
16:     else  
17:      args.reverse();  
18:     fn.apply(null,args);  
19:    }  
20:  };  

This function was also influenced by an implementation of partial application in the first recipes section of Javascript Allonge.

3.serial

I was watching a Node presentation given  by Nick Nisi  at the Nebraska Javascript Group on Youtube,amon other things he was also talking about an npm library called comb which has a function called serial which will take an array of functions as it's input and return(I'm guessing) an array of values(some of which could be functions),I decided to take a stab at writing it.Here is a rather simplistic implementation of serial which I managed to complete before I was again inuandated with work.


1:  var serial = function serial(funcs, params) {  
2:   //it does not execute all the functions unless you have specified enough or more than enough parameters.   
3:   //it would be nice to return all the values as an array.  
4:   //wont work if any of the functions use arguments in their call(ofcourse),so this cannot be used with a lot of stuff  
5:   var i, args, key,  
6:   max = Math.min(funcs.length, params.length),  
7:    res = [];  
8:   for (i = 0; i < max; i++) {  
9:    args = [];  
10:    if (params[i] != null) {  
11:     for (key in params[i]) {  
12:      if (params[i].hasOwnProperty(key)) {  
13:       //would be nice to map values here and parameters in the function...  
14:       console.log(params[i]['' + key]);  
15:       args.push(params[i]['' + key]);  
16:      }  
17:     }  
18:    }  
19:    res.push(funcs[i].apply(null, args));  
20:    args = [];  
21:   }  
22:   return res;  
23:  };  

As specifed in the comments along with the code this function only executes a function if an object consisting of parameters is provided for it.If a function does not have enough arguments the result is not obtained.

I guess we could return the autocurry function in order to ensure that the remaining arguments are passed to the function before it is executed but that would mean that the existing argument set is discarded and not applied to the function,which then has no option but to start anew.The function will return undefined in case it depends entirely upon the arguments array-like-object for it's execution.




1:  serial([function()  
2:      {  
3:        return 'Hello world'  
4:      },  
5:      function(x,y)  
6:      {  
7:        return x+y;  
8:      },  
9:      function(x,y,z)  
10:      {  
11:        return x+y+z;  
12:      },  
13:      function()  
14:      {  
15:        var res;  
16:        var args=Array.prototype.slice(arguments,null);  
17:        for(var i=0;i<args.length;i++)  
18:        {  
19:          res+=args[i];  
20:        }  
21:        return res;  
22:      }],  
23:      [null,  
24:       {x:2,y:3},  
25:       {x:2,y:4},  
26:       {x:2,y:3,z:5}  
27:       ]);  

I would also like to map the arguments to the function as they were passed.Now,as you might already have guessed the arguments are passed based on a first-come first-serve,I do not care about your name way but it would just be nice(atleast in my opinion) if we could do mapping of arguments to the function by name.


For that I have discovered this function(thank you Stack Overflow) whose input is a function which it converts to a string and uses a regular expression to isolate the values between ( and ) and splits them based on the , charecter.


1:  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;  
2:  var getParamNames=function getParamNames(func) {  
3:   var fnStr = func.toString().replace(STRIP_COMMENTS, '')  
4:   var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g)  
5:   if (result === null) result = []  
6:   return result  
7:  };  


1:  var serial=function serial(funcs,params)  
2:  {  
3:   var i,args,key,  
4:   max=Math.min(funcs.length,params.length),res=[];  
5:   for(i=0;i<max;i++)  
6:   {  
7:     args=[];  
8:     if(params[i]!=null)  
9:     {  
10:      for(key in params[i])  
11:     {  
12:       if(params[i].hasOwnProperty(key))  
13:       {  
14:         //would be nice to map values here and parameters in the function...  
15:         console.log(params[i][''+key]);  
16:         args.push(params[i][''+key]);  
17:       }  
18:     }  
19:     }  
20:     if(funcs[i].length>args.length)  
21:     {  
22:      //this will start applying the function anew with new arguments  
23:      res.push(mycurry(funcs[i]));  
24:     }  
25:     else  
26:     {  
27:      res.push(funcs[i].apply(null,args));   
28:     }  
29:      args=[];   
30:   }  
31:   return res;  
32:  };  

The only issue I percieve with this function  is that it requires that the arguments be passed anew.Any previous arguments that we might have passed to it before are sent to a deep dark abyss.You could unwind the args arrays and pass it to the autocurry function or you could instead do this horrifyingly tortuously(http://www.thefreedictionary.com/tortuously) which is different from  torturous(lesson learned!!!) chained thing.But hey,it works.

  res.push(mycurry.apply(null,[funcs[i]].concat(args)));  

Some of the functions I represented here might not be the most used or the most useful functions but they are fun ideas and dreams turned into reality.I wanted to write about so many other functions but these were the functions that came to mind when I conceived of this blog post.

Update:

Here is a function that maps the arguments of a function to the properties of an object.If a property matching the parameter name cannot be found,it instead places undefined there.Here is the function:


1:  var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;  
2:  var getParamNames=function getParamNames(func) {  
3:   var fnStr = func.toString().replace(STRIP_COMMENTS, '')  
4:   var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g)  
5:   if (result === null) result = []  
6:   return result  
7:  };  
8:  //pick properties from an object based on a function's arguments  
9:  var chooseArguments=function chooseArguments(fn)  
10:  {  
11:   var fn_args=getParamNames(fn);  
12:   return function(obj)  
13:   {  
14:    var i,res=[],key;  
15:    for(i=0;i<fn_args.length;i++)  
16:    {  
17:     if(obj[fn_args[i]]!=null)  
18:     {  
19:      res.push(obj[fn_args[i]]);  
20:     }  
21:      else  
22:        res.push(void 0);  
23:    }  
24:     return res;  
25:   }  
26:  }  
27:  var checkAdd=chooseArguments(function(x,y){return x+y});  
28:  var args_add=checkAdd({z:10,y:3});  
29:  alert(args_add);  

This function does not play nicely with the currying function as we always have enough arguments,although some of these arguments are undefined.So,we need a new currying function that can only replaces undefined values in your array of arguments,an initial version looks like this:


1:  var replaceUndefinedArgs=function(arr)  
2:  {  
3:    var i,j=0;  
4:    var args=Array.prototype.slice.call(arguments,1);  
5:    for(i=0;i<arr.length;i++)  
6:    {  
7:      if(arr[i]==null)  
8:      {  
9:        if(j<args.length)  
10:        {  
11:          arr[i]=args[j];  
12:          j++;  
13:        }  
14:      }    
15:    }  
16:  //arr is copied by reference so a mutation to arr ripples through space and time...so no need //to return arr  
17:  };    

I am an unfortunate soul because the word what-if scares me and drives me to do some crazy stuf.So here it is,WHAT IF you did not pass enough arguments to dispel undefined from the array.You must find out how many arguments you need to curry for in the initial array. Ensure that the function keeps returning another function until the exact number of arguments has been reached.

This is a function that keeps querying for more arguments until it has enough arguments to replace all the undefined values in your array,this is a version of the auto-currying function that just uses an array instead of a function,pretty straightforward by now,I guess.We dont return the array,of course because it has copied by reference and need not be returned.

1:  var replaceUndefinedArgs=function(arr)  
2:  {  
3:    var i,len=0;  
4:    for(i=0;i<arr.length;i++)  
5:    {  
6:      if(arr[i]==null)  
7:        len++;  
8:    }    
9:    var args=Array.prototype.slice.call(arguments,1);  
10:    return function next()  
11:    {  
12:      var j=0;  
13:      args=args.concat(Array.prototype.slice.call(arguments,0));  
14:      if(len>0 && args.length<len)  
15:      {  
16:       return next;  
17:      }  
18:      else  
19:      {  
20:       for(i=0;i<arr.length;i++)  
21:       {  
22:         if(arr[i]==null)  
23:         {  
24:          arr[i]=args[j];  
25:          j++;  
26:         }    
27:       }  
28:      }    
29:    }     
30:  };  

So,I guess this is kind of a generic pattern in functional programming to do,return a function,task it with doing something.This function takes care of odd-user behaviour and other environmental factors.When the function has exactly what you need,you can do what you originally intented to to.

Now these functions are ready to be added to serial,so that we can map arguments to values,setting undefined when no value is found,if nessecary we can force these undefined values to have values by currying for them.

Sunday, February 16, 2014

Javascript inheritance:A cautionary tale

I am currently working on a project that uses the Google Maps V3 API as a frontend.I had to create Polygons and display it on the map,sounds simple enough right.I took a look at the samples and did this:
 var polyPoints=[];  
      polyPoints.splice(0,0,new google.maps.LatLng(-34.9290,138.6010),new google.maps.LatLng(-37.8136,144.9631),new google.maps.LatLng(-27.4679,153.0278));  
 var polygon=new google.maps.Polygon({  
   paths: polyPoints,  
   strokeColor: '#FF0000',  
   strokeOpacity: 0.8,  
   strokeWeight: 2,  
   fillColor: '#FF0000',  
   fillOpacity: 0.35  
  });  

I was trying to be clever,see how I take something very simple and twist it around.I had just discovered that you could add items to an Array using slice and I wanted to use it everywhere.In a moment we will see how this tendancy of mine leads me into trouble.

I had just learnt to use functions as constructors and here,standing right before me was a case where this idea could be applied to:

 var configurePolygonOptions=function configurePolygonOptions(strokeColor,strokeWeight,strokeOpacity,fillColor,fillOpacity)  
 {  
      this.strokeColor=strokeColor;  
      this.strokeWeight=strokeWeight;  
      this.strokeOpacity=strokeOpacity;  
      this.fillColor=fillColor;  
      this.fillOpacity=fillOpacity;  
 };  

An object is then instantiated using the new keyword which calls a function using the constructor form and sets this to the object created and  the object's constructor property to be the function itself.However this object can only be used to initialize the Polygon's properties and goes no further than that(as I later found out).By the time this key piece of information reached the evil genius(a movie cliche bound to fail) had decided to go overboard and do this:


 configurePolygonOptions.prototype.setStrokeColor=function setStrokeColor(color)  
 {  
      this.strokeColor=color;  
 };  
 configurePolygonOptions.prototype.setStrokeWeight=function setStrokeWeight(weight)  
 {  
      this.strokeWeight=weight;  
 };  
 configurePolygonOptions.prototype.setStrokeOpacity=function setStrokeOpacity(weight)  
 {  
      this.strokeWeight=strokeWeight;  
 };  
 configurePolygonOptions.prototype.setFillColor=function setFillColor(color)  
 {  
      this.fillColor=color;  
 };  
 configurePolygonOptions.prototype.setFillOpacity=function setFillOpacity(opacity)  
 {  
      this.fillOpacity=opacity;  
 };  
 configurePolygonOptions.prototype.setProperty=function setProperty(prop,value)  
 {  
      this[prop]=value;  
 };  
 configurePolygonOptions.prototype.setPaths=function setPathsForPolygon(paths)   
  {    
    this.paths=paths;   
    console.log('The points have been added to polygon options');   
  };   
  configurePolygonOptions.prototype.setEditable=function(edit)   
  {   
    this.editable=edit;   
  };   
  configurePolygonOptions.prototype.setDraggable=function(drag)   
  {   
    this.draggable=drag;   
  };   

So,all this code is useless,but then I look at the API for drawing a circle and a rectangle and say to myself "How about trying out that inheritance concept you just learnt about?"


 var createRectangle=function createRectangle(strokeColor,strokeWeight,strokeOpacity,fillColor,fillOpacity)  
 {  
           configurePolygonOptions.apply(this,[strokeColor,strokeWeight,strokeOpacity,fillColor,fillOpacity]);  
 };  
 createRectangle.prototype=Object.create(configurePolygonOptions.prototype);  
 createRectangle.prototype.constructor=createRectangle;  
 createRectangle.prototype.setBounds=function(bounds)  
 {  
      console.log('setting bounds');  
      this.bounds=bounds;  
 };  
      var configureCircle=function configureCircle(strokeColor,strokeWeight,strokeOpacity,fillColor,fillOpacity)  
     {  
           configurePolygonOptions.apply(this,[strokeColor,strokeWeight,strokeOpacity,fillColor,fillOpacity]);  
           //configurePolygonOptions.call(this);  
};  
configureCircle.prototype=Object.create(configurePolygonOptions.prototype);  
configureCircle.prototype.constructor=configureCircle;  
configureCircle.prototype.setCenter=function(center)  
{  
     this.center=center;  
};  
configureCircle.prototype.setRadius=function(radius)  
{  
     this.radius=radius;  
};  

There was so much extra code but with no apparent problems,so I had to go create one,I noticed a map parameter within the object used  for Circle and Rectangle,I should have passed it in as an extra parameter and let it slide but I thought what if I could add a setMap method to configurePolygonOptions.prototype  and I would automatically inherit it(just like JAVA)

And here it is,after adding this code in,I found that Polygons would not be rendered on the map:



 configurePolygonOptions.prototype.setMap=function(map)  
 {  
      this.map=map;  
 };  
 var createPolygon=function createPolygon(options)  
 {  
      var pgon= new google.maps.Polygon(options);  
      console.log('created a polygon based on options provided');  
      return pgon;  
 };  
 var addPolygonToMap=function addPolygonToMap(poly)  
 {  
      poly.setMap(map);  
      console.log('added polygon to map');  
 };  

After trying a few different things like putting console.log methods evrywhere regardless of their relative,yelling at the computer,I posted a question on stackoverflow.When you create an instance of the Google Maps v3 API's Polygon object using an object you pass it,instead of protecting it's private members it instead allows overriding any properties the object has.(Yeah,blame the API and not yourself for not using the API the way you were meant to) and I had overridden the setMap method of Polygon which Circle and Rectangle did not have.

Should Google's API have protected the properties inside their object and only offer them for modification using methods like say,they would in Java?I do not know the answer to that,coming from a OO background,I would like that but...is it for everyone?

Lessons learned:

1.Keep your code simple,dont show off.
2.Use an API how it is meant to be.
3.Inheritance is evil.Use with care.(Are mixins evil too?)

Please comment and let me know what you think.

Saturday, February 15, 2014

Why I started a blog?Described in excruciating and painful detail just like 12 years a slave

Today morning,a series of loud,verbal slaps were delivered to mutinuous neurons inside my head.It all started when one or a team of my neurons(a minion of my brain but capable of revealing all manner of insecurities and unconformatable thoughts,sometimes I think they do me more harm than good) said you should start a blog.You could share all your ideas and experiences.This idea sent my mind into an overdrive,throwing everything into chaos.I am not creative or interesting,I retorted,I might be a terrible writer and other people might read what I write prompting groups of Grammer Nazis to send me(or my blog) to their version of Auschwitz(I had to look the spelling up,see...).The neuron(s) replied,we understand that you prefer not to share much with other people because you are afraid of how they will perceive(perspective/perception are mind altering drugs that causes  your boss to appear sleazier than he is and the cute girl to appear friendlier than she is) you,this could your way of communicating openly and freely...
two slaps were delivered to the neurons and the sound of the slap started echoing through my head while the idea of writing something reverberated through my brain along with it.

But what would I write about,a post that looks like this is not rewarding or fulfilling either to the unfortunate reader(unless they like to gleefully read and share blogs based on how bad they are) or to the  writer:

Hey,went to the office today.Worked till evening on hocus-pocus.Returned home.The END.

But there are some interesting things about you,other neuron(s) said,you could tell them about some of your obsessions like watching good movies,reading books,some of the experiences you have as a programmer.Your effort to learn JavaScript using only legally free resources or your attempts to not use products that are pirated,those would atleast be mildly interesting...a mental slap was bestowed upon them for their efforts to prop me up instead of talking me out of this crazy idea or telling me to write fake stories about how I climbed the dubiously named Olympus Mons(it turns that this is Mount Olympus too) the tallest mountain on Mars.However,by now the idea had taken hold of me and I wrack my brain trying to think of something to write and ofcourse nothing funny or interesting comes to mind.
Other groups of neurons were bold enough to suggest that I write about the thought process of why I decieded to write a blog and voila you have this blog post.For their idea and for making the effort of composing this article,I reward them with a mental lashing and now my head hurts.

So before,I go away to my deep,dark and dank corner,I would like to introduce myself:

I am Vamsi,a programmer,a movie buff and a reader and as my friends tell me a terrible photographer.I am what a smartass or a Bitsian would call a gult(translated to an individual whose mothertounge is Telugu and probably hails from what is currently known as the state of Andhra Pradesh).This blog is my way of sharing and not caring.I have tried to do this before but crippling fear and insecurity kept me from clicking on Blogger's create blog button.I would like to note that although I will go away from time to time,I will be back(just like the Terminator)I have done so in a moment of madness and I would like to click Publish before I come to my senses and abort this endeavour.