Re: 第3回 SICP読書会
id:kanouk課長がこの前の読書会のことを書いていたので、
読書会ではこの辺を大雑把に説明してたので
手続きsqrtにあわせてJavaScriptで書き直してみた。
ここはxを各functionに引数として渡していたけど、スコープ内だから
渡さなくてもよくないかいって話のソース。
//average,square,absは定義がある前提っぽいので別につくる。 function average( x, y ){ return (x + y) / 2; } function square( x ){ return x * x; } function abs( x ){ return Math.abs( x ); } //ここからが本題。 var sqrt = function( x ){ var goodEnough = function( guess ){ return abs( (square( guess )) - x ) < 0.001; }; var improve = function( guess ){ return average(guess, (x / guess)); }; var sqrtIter = function ( guess ){ if(goodEnough( guess )){ return guess; }else{ return sqrtIter( improve( guess ) ) } }; return sqrtIter(1.0); }; sqrt(9);//3.00009155413138と出力される
で、書いていて思ったのだが、1.0っての定数化したいよね。
ついでにguessってのも引数で渡さないようにしてみる。
で、できたのが
//average,square,absは上と同じなので省略 var sqrt = function( x ){ var guess = 1.0;//ここにguessを出しておく。 var goodEnough = function(){ return abs( (square( guess )) - x ) < 0.001; }; var improve = function(){ guess = average(guess, (x / guess));//returnせずに変数にセット }; var sqrtIter = function(){ if(goodEnough()){ return guess; }else{ improve();//引数でなく、個別に呼び出す。 return sqrtIter() } }; return sqrtIter(); }; sqrt(9);//3.00009155413138と出力される
やれないことはない。
でも、最初のほうがいい気もするな(^^;
なので、最初のやつを少しすっきりさせてみる。
var sqrt = function( x ){ const GUESS = 1.0;//FF限定だけど、constとして定義しておく var goodEnough = function( guess ){ return abs( (square( guess )) - x ) < 0.001; }; var improve = function( guess ){ return average(guess, (x / guess)); }; //arguments.calleeを使って関数を呼び出すようにして、 //即呼び出しにしてsqrtIterをなくす。 return (function ( guess ){ //if文でなく条件演算子にして1行ですっきりさせる。 return goodEnough( guess ) ? guess : arguments.callee( improve( guess ) ); })(GUESS); };
結構いい感じだなって、すっかり脱線してるじゃんか!!!(゚ロ゚;)