Skip to content

Commit 3117294

Browse files
committed
Replace dojox functional extensions with underscore.js
Signed-off-by: David Laing <david@davidlaing.com>
1 parent a2c27c0 commit 3117294

21 files changed

+129
-1161
lines changed

KoansRunner.html

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
<script type="text/javascript" src="lib/jasmine/jasmine-html.js"></script>
99
<script type="text/javascript" src="lib/jasmine/jskoans-jasmine-html.js"></script>
1010

11-
<script type="text/javascript" src="lib/dojo-release-1.5.0/dojo/dojo.js"></script>
12-
<script type="text/javascript" src="lib/dojo-release-1.5.0/dojox/lang/functional/lambda.js"></script>
13-
<script type="text/javascript" src="lib/dojo-release-1.5.0/dojox/lang/functional/array.js"></script>
14-
<script type="text/javascript" src="lib/dojo-release-1.5.0/dojox/lang/functional/fold.js"></script>
15-
<script type="text/javascript" src="lib/dojo-release-1.5.0/dojox/lang/functional/sequence.js"></script>
11+
<script type="text/javascript" src="lib/underscore-min.js"></script>
12+
1613
<script type="text/javascript" src="lib/__.js"></script>
1714

1815
<script type="text/javascript" src="koans/AboutExpects.js"></script>
@@ -21,7 +18,7 @@
2118
<script type="text/javascript" src="koans/AboutObjects.js"></script>
2219
<script type="text/javascript" src="koans/AboutMutability.js"></script>
2320
<script type="text/javascript" src="koans/AboutLambda.js"></script>
24-
<script type="text/javascript" src="koans/AboutHigherOrderFunctions.js"></script>
21+
<script type="text/javascript" src="koans/AboutHigherOrderFunctions.js"></script>
2522
<script type="text/javascript" src="koans/AboutInheritance.js"></script>
2623
<script type="text/javascript" src="koans/AboutApplyingWhatWeHaveLearnt.js"></script>
2724

koans/AboutApplyingWhatWeHaveLearnt.js

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,47 @@
1-
var dojox; //globals
2-
var df = dojox.lang.functional;
1+
var _; //globals
32

43
describe("About Applying What We Have Learnt", function() {
54

6-
var operations;
5+
var products;
76

87
beforeEach(function () {
9-
operations = [
10-
{ direction: "RT", distance: 200},
11-
{ direction: "FWD", distance: 50},
12-
{ direction: "RT", distance: 100},
13-
{ direction: "RT", distance: 20},
14-
{ direction: "FWD", distance: 200},
15-
{ direction: "RT", distance: 10}
16-
]
8+
products = [
9+
{ name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
10+
{ name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
11+
{ name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
12+
{ name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
13+
{ name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
14+
];
1715
});
1816

1917
/*********************************************************************************/
2018

21-
it("should find a needle in a haystack (imperative)", function () {
22-
23-
var findNeedle = function (ops) {
24-
var hasInvalidOperation = false;
25-
for (var i = 0; i < ops.length; i+=1) {
26-
if (ops[i].direction === "FWD" && ops[i].distance > 100) {
27-
hasInvalidOperation = true;
28-
break;
29-
}
30-
}
19+
it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {
3120

32-
return hasInvalidOperation;
33-
};
34-
35-
expect(findNeedle(operations)).toBe(__);
21+
var i,j,hasMushrooms, productsICanEat = [];
22+
23+
for (i = 0; i < products.length; i+=1) {
24+
if (products[i].containsNuts === false) {
25+
hasMushrooms = false;
26+
for (j = 0; j < products[i].ingredients.length; j+=1) {
27+
if (products[i].ingredients[j] === "mushrooms") {
28+
hasMushrooms = true;
29+
}
30+
}
31+
if (!hasMushrooms) productsICanEat.push(products[i]);
32+
}
33+
}
34+
35+
expect(productsICanEat.length).toBe(__);
3636
});
3737

38-
it("should find needle in a haystack (functional)", function () {
39-
expect(df.some(operations, "x.direction === 'FWD' && x.distance > 100")).toBe(__);
38+
it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {
39+
40+
var productsICanEat = [];
41+
42+
/* solve using filter() & all() / any() */
43+
44+
expect(productsICanEat.length).toBe(__);
4045
});
4146

4247
/*********************************************************************************/
@@ -54,50 +59,31 @@ describe("About Applying What We Have Learnt", function() {
5459
});
5560

5661
it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {
57-
var sumIfMultipleOf3Or5 = function (sum, next) {
58-
if (next % 3 === 0 || next % 5 === 0) {
59-
return sum + next;
60-
}
61-
return sum;
62-
};
63-
var numbers = df.repeat(1000, "+1", 1);
6462

65-
expect(df.reduce(numbers, sumIfMultipleOf3Or5, 0)).toBe(__);
63+
var sum = __; /* try chaining range() and reduce() */
64+
65+
expect(234168).toBe(__);
6666
});
6767

6868
/*********************************************************************************/
69+
it("should count the ingredient occurrence (imperative)", function () {
70+
var ingredientCount = { "{ingredient name}": 0 };
6971

70-
it("should find the sum of all the even valued terms in the fibonacci sequence which do not exceed four million (imperative)", function () {
71-
var sum = 0;
72-
var fib = [0,1,1];
73-
var i = 3;
74-
var currentFib = 0;
75-
76-
do {
77-
currentFib = fib[i] = fib[i-1] + fib[i-2];
78-
if (currentFib % 2 === 0) {
79-
sum += currentFib;
80-
}
81-
i+=1;
82-
} while (currentFib < 4000000);
83-
84-
expect(sum).toBe(__);
72+
for (i = 0; i < products.length; i+=1) {
73+
for (j = 0; j < products[i].ingredients.length; j+=1) {
74+
ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
75+
}
76+
}
77+
78+
expect(ingredientCount['mushrooms']).toBe(__);
8579
});
8680

87-
it("should find the sum of all the even valued terms in the fibonacci sequence which do not exceed four million (functional)", function () {
88-
var calcNextFibTuple = function(item, index, array) {
89-
return [item[1], item[0]+item[1]];
90-
};
91-
var addEven = function(result, item) {
92-
if (item[0] % 2 === 0) {
93-
return result + item[0];
94-
}
95-
return result;
96-
};
97-
var fib = df.until("item[0] > 4000000", calcNextFibTuple, [0,1]);
98-
var sum = df.reduce(fib, addEven, 0);
99-
100-
expect(sum).toBe(__);
81+
it("should count the ingredient occurrence (functional)", function () {
82+
var ingredientCount = { "{ingredient name}": 0 };
83+
84+
/* chain() together map(), flatten() and reduce() */
85+
86+
expect(ingredientCount['mushrooms']).toBe(__);
10187
});
10288

10389
/*********************************************************************************/

koans/AboutHigherOrderFunctions.js

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
var dojox; //globals
2-
var df = dojox.lang.functional;
1+
var _; //globals
32

3+
/* This section uses a functional extension known as Underscore.js - http://documentcloud.github.com/underscore/
4+
"Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support
5+
that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
6+
It's the tie to go along with jQuery's tux."
7+
*/
48
describe("About Higher Order Functions", function () {
59

610
it("should use filter to return array items that meet a criteria", function () {
711
var numbers = [1,2,3];
8-
var odd = df.filter(numbers, "x % 2 !== 0");
12+
var odd = _(numbers).filter(function (x) { return x % 2 !== 0 });
913

1014
expect(odd).toEqual(__);
1115
expect(odd.length).toBe(__);
@@ -14,17 +18,18 @@ describe("About Higher Order Functions", function () {
1418

1519
it("should use 'map' to transform each element", function () {
1620
var numbers = [1, 2, 3];
17-
var numbersPlus1 = df.map(numbers, "x + 1");
21+
var numbersPlus1 = _(numbers).map(function(x) { return x + 1 });
1822

1923
expect(numbersPlus1).toEqual(__);
2024
expect(numbers).toEqual(__);
2125
});
2226

23-
it("should use 'reduce' to update the same result on each iteration ", function () {
27+
it("should use 'reduce' to update the same result on each iteration", function () {
2428
var numbers = [1, 2, 3];
25-
var reduction = df.reduce(numbers, "result + x");
29+
var reduction = _(numbers).reduce(
30+
function(/* result from last call */ memo, /* current */ x) { return memo + x }, /* initial */ 0);
2631

27-
expect(reduction).toBe(__);
32+
expect(reduction).toBe(__);
2833
expect(numbers).toEqual(__);
2934
});
3035

@@ -35,34 +40,51 @@ describe("About Higher Order Functions", function () {
3540
msg += (item % 2) === 0;
3641
};
3742

38-
df.forEach(numbers, isEven);
43+
_(numbers).forEach(isEven);
3944

4045
expect(msg).toEqual(__);
4146
expect(numbers).toEqual(__);
4247
});
4348

44-
it("should use 'some' to apply until true", function () {
45-
var numbers = [1,2,3];
46-
var msg = "";
47-
var isEven = function (item) {
48-
msg += item + ";";
49-
return (item % 2) === 0;
50-
};
51-
52-
expect(numbers.some(isEven)).toBeTruthy();
53-
expect(msg).toEqual(__);
49+
it("should use 'all' to test whether all items pass condition", function () {
50+
var onlyEven = [2,4,6];
51+
var mixedBag = [2,4,5,6];
52+
53+
var isEven = function(x) { return x % 2 === 0 };
54+
55+
expect(_(onlyEven).all(isEven)).toBe(__);
56+
expect(_(mixedBag).all(isEven)).toBe(__);
5457
});
5558

56-
it("should use 'every' to apply until first false" , function () {
57-
var numbers = [1,2,3];
58-
var msg = "";
59-
var isEven = function (item) {
60-
msg += item + ";";
61-
return (item % 2) === 0;
62-
};
63-
64-
expect(numbers.every(isEven)).toBeFalsy();
65-
expect(msg).toBe(__);
59+
it("should use 'any' to test if any items passes condition" , function () {
60+
var onlyEven = [2,4,6];
61+
var mixedBag = [2,4,5,6];
62+
63+
var isEven = function(x) { return x % 2 === 0 };
64+
65+
expect(_(onlyEven).any(isEven)).toBe(__);
66+
expect(_(mixedBag).any(isEven)).toBe(__);
6667
});
68+
69+
it("should use range to generate an array", function() {
70+
expect(_.range(3)).toEqual(__);
71+
expect(_.range(1, 4)).toEqual(__);
72+
expect(_.range(0, -4, -1)).toEqual(__);
73+
});
74+
75+
it("should use flatten to make nested arrays easy to work with", function() {
76+
expect(_([ [1, 2], [3, 4] ]).flatten()).toEqual(__);
77+
});
78+
79+
it("should use chain() ... .value() to use multiple higher order functions", function() {
80+
var result = _([ [0, 1], 2 ]).chain()
81+
.flatten()
82+
.map(function(x) { return x+1 } )
83+
.reduce(function (sum, x) { return sum + x })
84+
.value();
85+
86+
expect(result).toEqual(__);
87+
});
88+
6789
});
6890

lib/dojo-release-1.5.0/dojo/dojo.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)