Wednesday, December 25, 2013

JavaScript Pearl: Function Properties

Functions in JavaScript are Objects. This we know.
A lesser spotted
 JavaScript function
with Properties 

We pass these objects around as arguments to other functions, we assign them to variables, set them as methods of other objects, and, ultimately, invoke them.
What we tend to forget (at least I do) is that as Objects JavaScript functions can also be the bearers of properties. 
There are a few ways we can use this fact to our advantage and a very cool example is given in Resig and Bibeault's "Secrets of the JavaScript Ninja".

The question they pose is this - if we're storing functions in an object of array, how can we prevent inserting the same function twice?
As Resig and Bibeault point out, one possibility is to simply iterate over the array and test each item to see if it's already part of the collection. There is a more interesting way to accomplish this. Directly below I provide a function that returns what looks like a simple array, but one which both doesn't add objects more than once, and doesn't have to iterate over the entire array. 

1:  function buildCache() {  
2:   var cache = [];  
3:   var cache_current_id = 0;  
4:   var old_push = cache.push;  
5:   cache.push = function() {  
6:    //since we can't actually run a forEach across the "arguments" object (it looks like an array, but it isn't)  
7:    Array.prototype.forEach.call(arguments,function(element) {  
8:     //first we check whether the element has an id - if it does, we skip adding it  
9:     if(element.cache_id === undefined) {  
10:      element.cache_id = cache_current_id;  
11:      logToDiv('adding a new function with the id of ' + cache_current_id);  
12:      cache_current_id++;  
13:      old_push.call(cache,element);  
14:     } else {   
15:      logToDiv('Function already exists with id ' + element.cache_id);  
16:     }  
17:    });  
18:   };  
19:   return cache;  
20:  }  

There are a couple of things going on here.
On line 2 I set up a simple array object - this will act as our function cache.
We then declare (line 3) a variable that will be used to both keep track of, and assign ids to, items that we will be adding to our cache.
On line 3 we save the standard push function attached to the cache array - we then (line 5) overwrite the push method so that for every element we test whether it has yet been assigned a cache_id (line 9) -- this tells us that we've already added this element to our cache. If the cache id is unassigned, we add an id as a property to the element and use the original push function (which we saved in "old_push") to push it on to our cache array. 
If we find a property with the name of "cache_current_id" then we know we've already added this element and we simply skip over it.   
No need to iterate. Pretty great. You can see this code running in a JS Bin here.
Note the log output. In the JS Bin I create two functions, and add them both to the cache twice. With both functions the first time I add them to the cache they are assigned an id and pushed on to the array, but the second time we attempt to push them on to the cache we're informed they're already there.

As a bonus, I've used function properties in my logToDiv function to deal with line numbering. I leave figuring it out as an exercise for the reader.

1:  //simple logger to show what's   
2:  function logToDiv(message) {   
3:   if(logToDiv.line_no === undefined) {  
4:    logToDiv.line_no = 1;   
5:   }  
6:   var message_div = document.createElement('div');  
7:   message_div.innerHTML = logToDiv.line_no++ + ': ' + message;  
8:   var log_div = document.getElementById('content');  
9:   log_div.appendChild(message_div);  
10:  }  


Wednesday, December 18, 2013

JavaScript Pearl: Self-defining Functions

Here's a neat trick that I learned from Stoyan Stefanov's great book JavaScript Patterns.

If you have a function that is called several times during program execution, but that has some prep work that needs to be done only once, we can have our function do whatever upfront work it needs to do and then redefine itself.

Here's a simple example - the prep work that the function will do is to generate and return some random number. Subsequent runs should return the same number as the first run.

var foo = function() {
  var i = Math.floor(Math.random()*100) + 1; //generate some number between 1-100
  foo = function() { return i; }; //here we redefine foo() and fix i in our closure, which is still available in subsequent runs
  return i;
}; 


Here is example output from running the code

> foo(); //should return some random number
   21

> foo(); //should return the same number as the first call
   21



Thursday, December 12, 2013

Working through the common currency talk in Shizgal and Conover (1996)

As I mentioned in my last post, I'm writing up a paper with Prof David Spurrett on the common currency argument. I'm woefully behind on my writing - so I'm going to use this series of blog posts to get my thinking down on paper, as it were, rather than sitting looking at a blinking cursor in LyX.

In this post I want to try and lay out the structure for the common currency argument as it's exemplified in Shizgal and Conover's 1996 paper "The Neural Computation of Utility" (it was published in Current directions in Psychological Science, but you can grab a preprint of it here).

Prof Spurrett has actually written about this paper online before, so this will be - in some sense - a rehash, but it's useful for me. I'm also not as interested in neuroscience as he is, so I'll say less about the actual experiments than he does.

Right, so we're focusing on an argument that S&C make about how the mechanisms by which choices are made have to be in order for agents to make certain kinds of choices.

Let's look at what they say
for orderly choice to be possible, the utility of all competing resources must be represented on a single, common dimension
There's a lot in this line, so let's try and unpack it a little.

I think it helps to point out that the words "orderly choice"  can (to keep us thinking straight) be replaced with "certain kinds of choices" - so, "for certain kinds of choices to be possible, the utility of all competing resources must be represented on a single, common dimension".
I think this helps because the way that it's phrased in the paper makes it seem that "orderly" is a property of all choices for some agent (at least it seemed that way to me).
This isn't necessarily the case - so I like rephrasing it to highlight the fact that an agent actually needs all choices available to it to be represented in some scalar value (the common currency) that's able to be compared and ranked.

Shizgal and Conover themselves point out that only certain kinds of choices need to be represented on a common scale - in particular, you don't need a common scale of evaluation if choices are made by using some kind of categorical rule such as "if offered a choice between cheese and ham, always choose the cheese, no matter how much ham you're offered".
Following this rule I will always choose cheese, even if I'm offered one tiny crumb of Camembert versus  enough ham to make me the king of the world, I'll choose the cheese, no matter what. Note that there need not be any kind of weighing of options in this case. We see the cheese, we choose the cheese. Period.
No common currency needed.
Making choices like this seems irrational in the case of ham and cheese, but in some cases it might make perfect sense. More on this later.

So, if not all choices require a common currency, which do?

Shizgal and Conover suggest at least two kinds

First, a common currency seems to be required when the choice is between different kinds of things.
If I'm presented with a choice between 5 slices of ham on the one hand, and 10 slices of ham on the other - then assuming that more is better (an assumption that S&C make explicitly), then the choice is simple - mo ham fo' sure. But if it's between 5 slices of ham and two slices of cheese (assuming we're not choosing according to our categorical rule above), then the choice is more difficult. Cheese and ham differ from each other in many different ways and, ultimately, when we make our choice between them we'll have to compare them along some common dimension (say, which one is saltier, or has the highest energy yield) or reduce a number of those dimensions to some single comparable number.

Second, a common currency seems to be required when the options themselves are "complex". For instance, if we were to choose between a Ham and Cheese on rye bread and a chicken and mayo toasted panini. Each of the elements that make up the two sandwiches contribute to its overall level of enjoyment or aversiveness (we can speak in terms of utility here if we like, right now we keep it loose). Not only are we comparing between two different kinds, but we're faced with options made of different kinds and then having to choose between them. This requires not only a way of reducing different kinds to a comparable scale but also a way of summing the values of the items that make up an option for a choice.

In both of these choice situations it's rational (in an economic sense) to always choose the higher ranked of the two options. This, it seems to me, is what S&C mean when they speak about ordered choice - the choosing of the higher valued option in a choice situation that includes (potentially) different kinds of goods and where (potentially) the choices available are complex in the sense sketched above.

So, let's quickly recap. Although common currencies are not necessary for choices based on a categorical rule, S&C assert that they are necessary for ordered choices.

So what's the big deal about ordered choice? Well, two things (at least).

Firstly, it seems that certain kinds of animals (like rats, and humans) seem to be able to make ordered choices, and if S&C are right it seems that there would need to be some place in the brain where the reduction to and comparison of the common currency / unidimensional representation of value actually happens. In their paper they lay out their experiments that show that there is good reason to believe this is happening in the mid-forebrain of rats.

Second, and more generally, if the common currency represents or tracks the contribution of a choice option's contribution to the chooser's fitness, then any agent that whose goal is to maximize fitness will need the kind of computational machinery that is able to perform - at the very least - the following operations

  1.  reducing multidimensional representations of objects to a single value (reduction of options to a common currency)
  2. the ability to rank options according to this common currency (in order to pick the highest ranked)
  3. the ability to add up the values of several items that make up an option in a complex choice situation.
So where to from here?
Well, for me there are two interesting questions. 
Firstly, and this I really don't know, I wonder if there's a proof that for these kinds of choices one require a common scale of representation? Can we find a counterexample to S&C's claim? 

Secondly, could an agent that couldn't do the kinds of subtle calculations required of ordered choice still behave or choose (near? ) optimally?

My gut tells me that the answer to the first question will probably be "yes, you need a common scale of representation for ordered choice", but also, to the second, that "some things can get along just fine - and close to optimally - without having to make these kinds of choices and, therefore, have no need for the kind of computational machinery required to make ordered choices".