在使用一些有惰性求值特性的语言里,无穷列表一直让我感觉很神奇,能够完美的表达一些无穷的数据(其实有很多数据都是无穷的,要用有限的数组处理无限的数据需要很多额外代码)。所以我就想在js里面实现一个,写完一用发现好刺激,还能递归。。实现了一个简单的列表类型和一些常用方法
var List = require('.');
var assert = require('assert');
var N = new List(1, a => a + 1); //自然数
var ones = new List(1, () => 1);//无穷个1
var Z = List.make(0, () => N); //类似Haskell,可以在前面加元素(什么?能不能在最后加?这是一个无穷列表。。)
assert.deepEqual(N.drop(5).take(5), [6, 7, 8, 9, 10]); //take 是一个比较特殊的方法,相当于把无穷列表转换成有限的
assert.deepEqual(N.filter(a => a % 2 == 0).take(5), [2, 4, 6, 8, 10]);
assert.deepEqual(N.map(a => a + 1).take(3), [2, 3, 4]);
assert.deepEqual(N.zipWith(Z, (n, z) => n * z).take(3), [0, 2, 6]);
//这货居然能实现一个素数列表
var sieve = ls =>
List.make(ls.head, () => sieve(ls.tail().filter(a => a % ls.head != 0)));
var prime = sieve(N.tail());
assert.deepEqual(prime.take(5), [2, 3, 5, 7, 11]);
//斐波那契数列,自己和以前的自己搞在一起
var fibs = List.make(0, () => List.make(1, () => fibs.zipWith(fibs.tail(), (a, b) => a + b)));
assert.deepEqual(fibs.take(6), [0, 1, 1, 2, 3, 5]);
项目在这个地方。。