|
|
|
describe("Lists", function(){ |
|
|
|
"use strict"; |
|
|
|
var listA = cons('a', emptyList); |
|
var listBA = cons('b', listA); |
|
var listCBA = cons('c', listBA); |
|
|
|
it("can use cons, head and tail", function() { |
|
|
|
expect(head(listCBA)).toBe('c'); |
|
expect(head(tail(listCBA))).toBe('b'); |
|
expect(head(tail(tail(listCBA)))).toBe('a'); |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it("can convert to an array", function() { |
|
|
|
var listCBA = cons('c', cons('b', cons('a', emptyList))); |
|
|
|
expect( listAsArray(listCBA) ).toEqual( ['c','b','a'] ); |
|
}); |
|
|
|
it("can convert empty list to an array", function(){ |
|
expect( listAsArray(emptyList) ).toEqual([]); |
|
}); |
|
|
|
it("can reverse the order of a list", function() { |
|
var listCBA = cons('c', cons('b', cons('a', emptyList))); |
|
|
|
expect( listAsArray(reverseList(listCBA)) ).toEqual( ['a','b','c'] ); |
|
}); |
|
|
|
it("can map over a list", function() { |
|
var naturals = cons(1, cons(2, cons(3, emptyList))); |
|
var evens = cons(2, cons(4, cons(6, emptyList))); |
|
|
|
function doubleit(n){return n * 2} |
|
|
|
expect( map(doubleit, naturals) ).toEqual( evens ); |
|
}); |
|
|
|
describe('without', function(){ |
|
|
|
function equalTo(val){ |
|
return function(candidate){ |
|
return candidate == val; |
|
} |
|
} |
|
|
|
|
|
it("can remove from the middle of a list", function() { |
|
var naturals = list(1, 2, 3); |
|
|
|
expect( without(naturals, equalTo(2)) ).toEqual( list(1, 3) ); |
|
}); |
|
|
|
it("can remove from the end of a list", function() { |
|
var naturals = list(1, 2, 3); |
|
|
|
expect( without(naturals, equalTo(3)) ).toEqual( list(1, 2) ); |
|
}); |
|
|
|
it("can not remove", function() { |
|
var naturals = list(1, 2, 3); |
|
|
|
expect( without(naturals, equalTo(4)) ).toEqual( list(1, 2, 3) ); |
|
}); |
|
|
|
it("works with the empty list", function() { |
|
|
|
expect( without(emptyList, equalTo(4)) ).toEqual( emptyList ); |
|
}); |
|
|
|
it("can give removed item to a callback", function() { |
|
var callback = jasmine.createSpy(); |
|
var naturals = list(1, 2, 3); |
|
|
|
without(naturals, equalTo(2), callback) |
|
expect( callback ).toHaveBeenCalledWith( 2 ); |
|
}); |
|
|
|
|
|
}); |
|
|
|
it("can convert non empty list to an array", function(){ |
|
|
|
expect( listAsArray( list('a','b','c') ) ).toEqual( ['a','b','c'] ); |
|
}); |
|
|
|
it("can convert empty array to list", function() { |
|
|
|
expect( listAsArray( arrayAsList([]) ) ).toEqual( [] ); |
|
}); |
|
|
|
it("can assert every xitem in a list holds for a given test", function(){ |
|
var l = list(1,2,3,4,5,6,7,8,9,10); |
|
|
|
function isANumber(n) { |
|
return typeof n == 'number'; |
|
} |
|
|
|
function isOdd(n) { |
|
return n % 2 == 0; |
|
} |
|
|
|
function isLessThanTen(n) { |
|
return n < 10; |
|
} |
|
|
|
function isLessThanOrEqualToTen(n) { |
|
return n <= 10; |
|
} |
|
|
|
expect( all(isANumber, l )).toBe(true); |
|
expect( all(isOdd, l )).toBe(false); |
|
expect( all(isLessThanTen, l )).toBe(false); |
|
expect( all(isLessThanOrEqualToTen, l )).toBe(true); |
|
}); |
|
|
|
describe('foldR', function(){ |
|
|
|
it("can fold list where order doesnt matter", function(){ |
|
function add(n, m){ return n+m } |
|
|
|
var sum = foldR(add, 0, list(1,2,3,4)); |
|
|
|
expect( sum ).toEqual( 1 + 2 + 3 + 4 ); |
|
}); |
|
|
|
it("can fold list where start value matters", function(){ |
|
function divide(n, m){ return n / m } |
|
|
|
var result = foldR(divide, 100, list(2, 2)); |
|
|
|
expect( result ).toBe( 25 ); |
|
}); |
|
|
|
it("can fold list in the correct order", function(){ |
|
function functionString(param, fnName){ return fnName + '(' + param + ')' } |
|
|
|
var functionStringResult = foldR(functionString, 'x', list('a', 'b', 'c')); |
|
|
|
|
|
|
|
expect( functionStringResult ).toEqual( 'a(b(c(x)))' ); |
|
}); |
|
}); |
|
|
|
describe('foldR1', function(){ |
|
|
|
it("can fold list where order doesnt matter", function(){ |
|
function add(n, m){ return n+m } |
|
|
|
var sum = foldR1(add, list(1,2,3,4)); |
|
|
|
expect( sum ).toEqual( 1 + 2 + 3 + 4 ); |
|
}); |
|
|
|
|
|
it("can fold list in the correct order", function(){ |
|
function functionString(param, fnName){ return fnName + '(' + param + ')' } |
|
|
|
var functionStringResult = foldR1(functionString, list('a', 'b', 'c')); |
|
|
|
|
|
|
|
expect( functionStringResult ).toEqual( 'a(b(c))' ); |
|
}); |
|
}); |
|
|
|
it('may apply a function with side effects to each item of a list', function(){ |
|
|
|
var callback1 = jasmine.createSpy(), |
|
callback2 = jasmine.createSpy(), |
|
callback3 = jasmine.createSpy(), |
|
callback4 = jasmine.createSpy(), |
|
functions = list(callback1, callback2, callback3, callback4); |
|
|
|
applyEach( functions, ['a','b','c','d'] ); |
|
|
|
expect(callback1).toHaveBeenCalledWith('a','b','c','d'); |
|
expect(callback2).toHaveBeenCalledWith('a','b','c','d'); |
|
expect(callback3).toHaveBeenCalledWith('a','b','c','d'); |
|
expect(callback4).toHaveBeenCalledWith('a','b','c','d'); |
|
}); |
|
|
|
it('may apply a list of zero functions with side effects', function(){ |
|
|
|
expect(function(){ |
|
applyEach( list(), ['a','b','c','d'] ); |
|
}).not.toThrow(); |
|
}); |
|
|
|
beforeEach(function(){ |
|
this.addMatchers({ |
|
toBeFrozen: function(){ |
|
var obj = this.actual; |
|
|
|
return Object.isFrozen(obj); |
|
} |
|
}); |
|
}); |
|
}); |
|
|