Skip to content

Commit

Permalink
Merge branch 'lazy'
Browse files Browse the repository at this point in the history
  • Loading branch information
qiao committed Jul 14, 2014
2 parents 2c0f437 + 34ad015 commit 938cbd6
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 20 deletions.
89 changes: 74 additions & 15 deletions src/fingertree.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,21 @@
for (var i = 0, len = items.length; i < len; ++i) {
m = measurer.sum(m, measurer.measure(items[i]));
}
this.measure = m;

/**
* @private
*/
this.measure_ = m;
}

/**
* Get the measure of the digit.
* @return {*}
*/
Digit.prototype.measure = function () {
return this.measure_;
};

/**
* Get the first element stored in the digit.
* @return {*}
Expand Down Expand Up @@ -171,15 +183,27 @@
*/
function Node(measurer, items) {
this.items = items;

this.measurer = measurer;

var m = measurer.identity();
for (var i = 0, len = items.length; i < len; ++i) {
m = measurer.sum(m, measurer.measure(items[i]));
}
this.measure = m;
this.measurer = measurer;

/**
* @private
*/
this.measure_ = m;
}

/**
* Get the measure of the node.
* @return {*}
*/
Node.prototype.measure = function () {
return this.measure_;
};

/**
* Convert the node to a digit.
* @return {Node}
Expand Down Expand Up @@ -208,6 +232,12 @@

FingerTree.fromArray = fromArray;

/**
* Get the measure of the tree.
* @return {*}
*/
FingerTree.prototype.measure = notImplemented;

/**
* Check whether the tree is empty.
* @return {boolean} True if the tree is empty.
Expand Down Expand Up @@ -284,11 +314,19 @@
*/
function Empty(measurer) {
this.measurer = measurer;
this.measure = measurer.identity();
this.measure_ = measurer.identity();
}

Empty.prototype = create(FingerTree.prototype);

/**
* @inheritDoc
*/
Empty.prototype.measure = function () {
return this.measure_;
};


/**
* @inheritDoc
*/
Expand Down Expand Up @@ -357,11 +395,18 @@
function Single(measurer, value) {
this.value = value;
this.measurer = measurer;
this.measure = measurer.measure(value);
this.measure_ = measurer.measure(value);
}

Single.prototype = create(FingerTree.prototype);

/**
* @inheritDoc
*/
Single.prototype.measure = function () {
return this.measure_;
};

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -466,7 +511,7 @@
/**
* A finger-tree which contains two or more elements.
* @constructor
* @implements FingerTree
* @implements {FingerTree}
*/
function Deep(measurer, left, mid, right) {
/**
Expand All @@ -486,13 +531,27 @@

this.measurer = measurer;

this.measure = measurer.sum(
measurer.sum(this.left.measure, this.mid.measure),
this.right.measure);
/**
* @private
*/
this.measure_ = null;
}

Deep.prototype = create(FingerTree.prototype);

/**
* @inheritDoc
*/
Deep.prototype.measure = function () {
if (this.measure_ === null) {
var measurer = this.measurer;
this.measure_ = measurer.sum(
measurer.sum(this.left.measure(), this.mid.measure()),
this.right.measure());
}
return this.measure_;
};

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -631,7 +690,7 @@
var measurer = this.measurer;

// see if the split point is inside the left tree
var leftMeasure = measurer.sum(initial, left.measure);
var leftMeasure = measurer.sum(initial, left.measure());
if (predicate(leftMeasure)) {
var split = left.split(predicate, initial);
return new Split(fromArray(split.left, measurer),
Expand All @@ -640,10 +699,10 @@
}

// see if the split point is inside the mid tree
var midMeasure = measurer.sum(leftMeasure, mid.measure);
var midMeasure = measurer.sum(leftMeasure, mid.measure());
if (predicate(midMeasure)) {
var midSplit = mid.splitTree(predicate, leftMeasure);
var split = midSplit.mid.toDigit().split(predicate, measurer.sum(leftMeasure, midSplit.left.measure));
var split = midSplit.mid.toDigit().split(predicate, measurer.sum(leftMeasure, midSplit.left.measure()));
return new Split(deepRight(measurer, left, midSplit.left, split.left),
split.mid,
deepLeft(measurer, split.right, midSplit.right, right));
Expand All @@ -660,7 +719,7 @@
* @inheritDoc
*/
Deep.prototype.split = function (predicate) {
if (predicate(this.measure)) {
if (predicate(this.measure())) {
var split = this.splitTree(predicate, this.measurer.identity());
return [split.left, split.right.addFirst(split.mid)];
}
Expand Down Expand Up @@ -782,7 +841,7 @@
return {
identity: measurer.identity,
measure: function (n) {
return n.measure;
return n.measure();
},
sum: measurer.sum
};
Expand Down
10 changes: 5 additions & 5 deletions test/fingertree.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,19 @@ describe('Finger Tree', function () {

it('should be annotated with default measurer', function () {
var tree = FingerTree.fromArray([1, 2, 3]);
tree.measure.should.eql(3);
tree.measure().should.eql(3);

tree = FingerTree.fromArray(range(1000));
tree.measure.should.eql(1000);
tree.measure().should.eql(1000);
});

it('should be able to be split into two halves given a predicate', function () {
var tree = FingerTree.fromArray(range(100));
var split = tree.split(function (x) {
return x > 50;
});
split[0].measure.should.eql(50);
split[1].measure.should.eql(50);
split[0].measure().should.eql(50);
split[1].measure().should.eql(50);
});

it('should be able to be annotated with custom measurer', function () {
Expand All @@ -103,6 +103,6 @@ describe('Finger Tree', function () {
}
};
var tree = FingerTree.fromArray([1, 4, 3, 5, 2, 9], measurer);
tree.measure.should.eql(9);
tree.measure().should.eql(9);
});
});

0 comments on commit 938cbd6

Please sign in to comment.