Sunday, March 9, 2014

Bird Watching with JavaScript -- The Kestrel

"I will entertain Bardolph; he shall draw, he shall tap."
-- Shakespeare, The Merry Wives of Windsor
Act I, Scene III, Line 10

The Forest


In the Combinator Forest we hear the repeating call of the Kestrel.  As we sing out DO RE, we hear the Kestrel sing back DO.  We sing out LA but the Kestrel is still singing back DO.  We try again by singing out DO RE MI FA SO LA TI DO, but the Kestrel sings back DO DO DO DO DO DO DO DO.

Kestrel


The kestrel or K combinator is written as Kxy.x.  Meaning that no matter what value is given as y we always get x back from K.



We see that we always get the first argument back from the combinator K.

Kestrel in Haskell


In the package Data.Aviary.Birds we see the kestrel has the following definition:

kestrel :: a -> b -> a

We find that it is implement in the following way:

-- | K combinator - kestrel - Haskell 'const'.
-- Corresponds to the encoding of @true@ in the lambda calculus.
kestrel :: a -> b -> a
kestrel = const

see also: http://hackage.haskell.org/package/data-aviary-0.2.3/docs/src/Data-Aviary-Birds.html#kestrel

We see that this is calling nothing more than the const function in Prelude, which is implement in the following way:

-- | Constant function.
const                   :: a -> b -> a
const x _               =  x

see also: http://hackage.haskell.org/package/base-4.3.0.0/docs/src/GHC-Base.html#const

This means no matter what we pass as a second argument to const the pattern matching will match it and will simply just return the first argument.  Let's play with this on tryhaskell.org:


λ const 42 "another value"
42
:: Num a => a
λ let only42 = const 42 in only42 [1..5]
42
:: Num a => a
λ let onlyChickens = const "Chicken" in 
map onlyChickens ["Hen", "Rooster", "Cow"]
["Chicken","Chicken","Chicken"]
:: [[Char]]
λ  

We see when we call const no matter what the second argument is only the first argument is returned.

Underscore.js' constant

The K combinator is one of the newly added function in the popular Underscore.js library.  It has been implement as constant.

Here is what the implementation looks like:

  _.constant = function(value) {
    return function () {
      return value;
    };
  };

We see that constant will return a function which always returns value no matter what we call that function with.

Let's do some characterization testing on Underscore's constant.


Is a function

it("Constat will return a function", function(){
expect(_.constant("Hello world")).to.be.a("function");
})

We see that result of calling constant is a function no matter what we call it with.


Always returns the first value given to it


it("Given two values constant will return the first", function(){
var alwaysFirst = _.constant("First");
expect(alwaysFirst("Second")).to.be.equal("First");
})

We also see that when we call the function which constant returns we always get the same value which we initially called constant with.

In fact we can call constant with another function and have that function always returned from the function which constant returns (it is functions all the way down!).

it("Given a function constant will return that function", function(){
var theTruth = function(){return true;},
nothingButTheTruth = _.constant(theTruth);
expect(nothingButTheTruth()).to.be.a("function");
expect(nothingButTheTruth(false)()).to.be.ok();
expect(nothingButTheTruth(_.identity(42))()).to.be.equal(true);
});

Tap


Constant is a very simple implementation of the K combinator, but it has limit uses.  Tap is another way to implement the K combinator, but unlike constant it has a ton of uses.  In fact it is included in many languages core libraries including Ruby's.

Underscore.js' tap


"The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain."
-- tap, Underscore.js documentation

Underscore has an implementation of tap which looks like this.

  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

Looking at the code above we see that if we call tap with a function we will pass the value through the function before we return the value.



Let's play around with the tap function to see what it is like to work with.



Can be used like constant


We see that give a value and a function which does nothing, the value is returned.

it("Give a string and a function which does nothing the string will be the same", function(){
expect(_.tap("Mr. Jack", function(){})).to.be.equal("Mr. Jack");
}),

and

var array = [1, 2, 3, 4, 5];
beforeEach(function(done){
array = [1, 2, 3, 4, 5]; // to reset before each test case
done();
});
it("Given an array and a function which does nothing array will be the same", function(){
expect(_.tap(array, function(){})).to.be.eql(array);
}),

Can have side effects


We see that we can attach a function to the value so that we have an effect take place when we access it.

it("Given a value and a function which increments ...", function(){
var counter = 0,
increment = function(){counter++;},
peek = function(){return _.tap("Look here", increment);};
expect(counter).to.be.equal(0);
expect(peek()).to.be.equal("Look here");
expect(counter).to.be.equal(1);
peek();
expect(counter).to.be.equal(2);
});

This is very interesting, in fact the most common use of tap is for logging which is very similar to what we have above.

Ciao


It may seem odd to work with a function which "only" returns the same value on each call but we find in fact that the Kestrel is a very useful function.