February 1, 2008
IT戦士amachangのこのエントリーを見てJavaScriptで無限リストをやってみたくなった。amachangのやりたいことをあんまり理解してないので,関係ないかも知れないけど…。
無限リストは先頭要素の値と,n番目の要素の値からn+1番目の要素を計算する関数の組で表現できる。
JSにはタプルはないので,配列でこの組を保持することにして1から始まる自然数の無限列は次のような感じになる。
var nat = [1, function (x) { return x + 1; }];
このnatという無限列の10番目を取り出すには
function next(n) {
return [n[1](n[0]), n[1]];
}
function pos(ix, n) {
for (var i=0;i<ix;i++) {
n = next(n);
}
return n[0];
}
こんな感じのpos関数を作っといて
print(pos(9, nat)); // 10
とかやればいい。
調子にのってHaskellのtakeやmap風のこともやってみる。
function take(n, inflist) {
var ary = [];
for (var i=0;i<n;i++) {
ary.push(inflist[0]);
inflist = next(inflist);
}
return ary;
}
function map(func, inflist) {
var n = inflist;
return [func(n[0]),
function(x) {
n = next(n);
return func(n[0]);
}];
}
var evens = map (function(x) { return x*2; }, nat);
print(take(10, nat)); // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
print(take(10, evens)); // 2, 4, 6, 8, 10, 12, 14, 16, 18, 20
素数の列を
var prime = [2, function (prime) {
prime++;
outloop:
while(true) {
for(var i=2;i<=Math.sqrt(prime);i++) {
if (prime % i == 0) {
prime++;
continue outloop;
}
}
return prime;
}
}];
と作っておけば,
print(pos(99, prime)); // 541 (100番目の素数) print(take(100, prime)); // 100個まで素数を列挙
みたいな感じで遊べる。
プログラミング in OCamlっていう本を参考にしているので,考え方はOCaml風(?).もっとJavaScript風の書き方がありそうだなぁ。
- (no subject)
js風だと
こんな感じ?かなり無理やりな箇所があるけど
Array.prototype.setGeneral=function(func){
this.__gen=func;
return this;
}
Array.prototype.item=function(n){
if(this.__gen!=undefined){
var length=this.length;
for(var i=length-1;i+1<=n;i++){
var copy=eval("["+this.toString()+"]");
this[i+1]=this.__gen.apply(this,copy.reverse());
}
return this[n];
}else{
return this[n];
}
}
var test=[1,2,3].setGeneral(function(x){return x+1;});
var fib=[0,1].setGeneral(function(xn,xn_1){return xn+xn_1;});
- (no subject)
おぉ,なるほど。
Arrayのprototypeにしちゃって,普通の配列っぽくすれば,評価が終わったやつはキャッシュできるのか。n+1番目を計算するのに1からn番目まですべてに依存できるのもいい感じだなぁ。なんかすげー。
ん,てか俺の例だとfibみたいなやつやろうとすると結構無理矢理感漂うことに気づいた…。すべての無限リストカバーできてないじゃん俺...orz

Comment Thanks