Re: 第3回 SICP読書会

ノログ 第3回 SICP読書会
http://kanolog.jp/2008/07/3-sicp-ee80.html

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);
};

結構いい感じだなって、すっかり脱線してるじゃんか!!!(゚ロ゚;)