JGP 2章の例外処理

JGP読んでてよくわからなかったのが、throwするのはnameとmessageのプロパティを含むオブジェクトリテラルを投げるというところで、

try {
  throw {name:"TestError", message:"oops"}
} catch(e) {
  console.dir(e);
}

のあたり。Errorオブジェクト投げないのはなんでだろか?

var e = new Error("oops");
console.dir(e);

ってやるとnameとmessage(と他に幾つか)のプロパティに値が入ってるから、直接nameにエラーに対応する名前入れるだけでいいじゃんという判断なんだろうか?

そしたらErrorオブジェクトを用意する必要ない気がすんだけど。

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


なんか深い理由があるんだろうかね。

Javascriptで末尾最適化

元ネタはspencertipping / js-in-ten-minutes

Function.prototype.tail = function () {return [this, arguments]};
Function.prototype.call_with_tco = function () {
  var c = [this, arguments];
  var escape = arguments[arguments.length-1];
  while(c[0] !== escape)
    c = c[0].apply(this, c[1]);
  return escape.apply(this,c[1]);
};

// var sum  = function (n,acc) { return n > 0 ? sum(n-1,acc+n) : acc};
var sum2 = function (n,acc,k) { return n > 0 ? sum2.tail (n-1,acc+n,k) : k.tail (acc);};
var id   = function (x) {return x};
console.log(sum2.call_with_tco(100000,0,id));

これはDelimited Continuationになっているらしい。コードの動きは分かるけど継続とDelimited Continuationの違いが良くわからん。

Javascriptのboxedとunboxed

メモリ上に直接のっているような値はunboxedなのでプロパティの設定ができない。数値リテラルとか。

var x = 1;
x.add1 = function () {return this.valueOf() + 1;} // これはだめ
console.log(x.add1());

でもコンストラクタからnewされた場合にはプロパティの追加ができる

var x = new Number(1);
x.add1 = function () {return this.valueOf() + 1;} 
console.log(x.add1());

コンストラクタのprototypeに関数突っ込んでチェインできるようにしてみる。

var x = new Number(1);
Number.prototype.succ = function () {
  var n = new Number(this+1);
  return n;
};

console.log(x.succ().succ().succ().succ().toString());

リテラル表記でもNumberから継承されているので、コンストラクタのprototypeに関数突っ込めばメソッドとして呼び出せる

var x = 1;
x.constructor.prototype.succ = function () {
  var n = new Number(this+1);
  return n;
};

console.log(x.succ().succ().succ().succ().toString());

これはなかなか面白い

javascriptの等値演算子(==)と同値演算子(===)

昨日の読書会で、等値演算子(==)と同値演算子(===)をきちんと理解していないことが判明したので、サイ本を読んでみた。

Javascriptは、数値、文字列、論理値が等しいかどうかを「値により」判定します 一方オブジェクトや配列、関数の場合には「参照により」判定します

オブジェクト、配列、関数の場合には参照により判断されるので

$ ./shell 
V8 version 3.0.6.1
> [1,2,3] == [1,2,3]
false
> [1,2,3] === [1,2,3]
false
> var a = b = [1,2,3]
> a == b
true
> a === b
true

同値演算子は型変換を行わないで値が等しいかどうかを評価するが、等値演算子は2つのオペランドの型が異なる場合には型変換を行う。

同値は演算子は直感に対して素直なのでいいとして、等値は型が異なる場合に次のルールーで型変換をする

  • どちらか一方が数値で他方が文字列の場合、文字列を数値に変換してから比較
  • どちらか一方がtrueの場合trueを1に、falseの場合には0に変換してから比較
  • オブジェクトと数値の比較の場合オブジェクトを基本形に変換してから比較

改めてJGPのB1(p.127)を見てみる。

> '' == '0'
false
> '' == 0 
true
> 0 == '0'   
true

最初の例は文字列の比較なのでfalse。二番目は文字列と数字の比較で型変換されて''はfalseなので数値に変換されると0になるのでtrue。最後は文字列'0'が数値0に変換されて比較されるのでtrueか。

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


ProductName JavaScript 第5版
David Flanagan
オライリー・ジャパン / 4410円 ( 2007-08-14 )


第一回Javascript読書会に参加した

皆様お疲れさまでした。今回から新しく参加した人が結構いたので面白かったですね。

ちなみに資料はluminescenceで作りました。 YAML+MarkDownで記述できるため、バージョン管理システムで管理できて便利。ソースはこれ

おやつはC-DOLPHINのロールケーキ

1297551355

JGPも5章終わったら付録以外は消化する感じになるから、どっちの方向に進むのか考え始めないといけない気がするなぁ。

懇親会はKEIKO。一度前を通ったことはあるが入るのは初めて。

1297551353

ソフトドリンクの器がヤバめ(量が多い)。

1297551350 1297551348

創作パスタが美味かった。

1297551346

それからPythonに興味ある人が多かったのでいい流れかも。GAEと絡めてなんかやりたいですね。「みんなのPython」は良いんだけど今読んでるJGPと被るような気がするからなぁ、どうなんでしょう?

JavaScript: The Good Parts読書会の資料はもちろんJavascriptで作るわけですが

1章だけ作ってみた。

Javascript読書会(第一回)

yaml+markdown形式のHTMLプレゼンテーションをgitで管理すると幸せになれるし、githubとかでシェアもしやすくなるんじゃないかなぁ。スライドシェアはスライドのシェアだけど、yamlのシェアはもっとソースに近いところのシェアだよね。

HTMLスライドってかなり表現力が豊かになる気がする。ニコニコスライドみたいなスライドにコメントを残せるような表現方法あればもっといいのに。まぁ論文にも必要だけどね。

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


2章の鉄道ダイアグラムって丁寧に見ていくと新たな発見がどんどん出てきて深い。

今回は3章までやる予定ですが、まだ、若干名空きがあるようです。今回が初参加のヒトが何人かいるみたいなので静岡東部あたりで「どうしよっかなー」と迷っているヒトは参加されるといいと思う。僕も一年くらい前に「お、静岡で関数型言語の読書会やるのかー!」と参加してみたわけですが色々刺激があって楽しいです。地域グループってのは東京までノソノソ出かけていくのとは違った面白さがあると思っている。

第1回JavaScript読書会

「弱い紐帯」ってのは自分の人生に置いて強い影響力を持つのかなぁと思う今日この頃。

luminescenceでjavascriptを埋め込んだプレゼン資料をつくる

機能がちょっとシンプルすぎて、凝ったことするのは大変かもしれないけど、yaml+markdownでスライドを作れるluminescenceが便利。

luminescence input(yaml) output(html) [template(html)]

でスライド用のhtmlが出力される、こんだけ。

yamlのソースのほうにjavascript埋め込めるのでスライド中に表示したソースコードを直接実行したりできるし、jQuery Growl使えばハッシュタグ付きのtweetをプレゼンにストリーム表示させたりできる。

それから、このブログシステムもMarkdownでコンテンツ書いているので、過去のエントリから使いたいコードをコピペするとそのままスライドでも動くことが多いために自分の作業環境との相性がいい。

なにより、プレゼン資料が単なる資料作りではなく、javascriptの学習も兼ねるので時間の使い方的に非常によいだろうと。ソースをGitで管理できるので心理的にも安心(重要)。

とりあえず、最初の資料にgoogle maps埋め込んでおいた

js読書会

第1回JavaScript読書会

JGP読みます

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


FlaskとXDMつかってgooglemapとtwitterを連動させるサンプル

HTML5 APIガイドブック コミュニケーション系API編が面白い。ひと通り読んだので、コード書いてみてる。

2章のサンプルコードをFlaskで。サンプルコードは3つのHTMLファイルが必要だけどFlask使えば一つのファイルに全部押し込めるので管理が楽。

gmap2twitter

初期値は富士市役所のあたりから半径5キロ以内のtweetを探すようにした。で地図をドラッグすると、それに伴いtweetも連動して表示されるので、ほーこんなユーザーいるのか!と新たな発見もあった。

この本は入門書として最適かもしれん。

ProductName 徹底解説 HTML5 APIガイドブック コミュニケーション系API編
小松 健作
秀和システム / 2730円 ( 2010-12 )


Flaskコード

#!/usr/bin/env python
# -*- encoding:utf-8 -*-

from flask import Flask

app = Flask(__name__)

@app.route("/")
def processing():
    response = """
<!doctype html>
<html lnag=ja>
<head>
<meta charset="utf-8">
<style type="text/css">
.page { margin: 0px auto; border: 0px; padding: 0px; text-align: center;}
</style>
</head>
<body>
<div class=page>
<h1>gmap2tweet</h1>
<iframe src="/googlemap" id=gmap width="500px" height="500px"></iframe>
<iframe src="/twitter" id=twitter width="500px" height="500px"></iframe>
<div id=mesg></div>
</div>
<script>
  var initialize = function(){
    var origin = location.protocol + "//" + location.host;
    var iframes = document.querySelectorAll('iframe');

    for(var i = 0; i < iframes.length; i++){
      iframes[i].contentWindow.postMessage('init', origin);
    }

    window.addEventListener('message', function(e){
        if (e.origin == origin) {
          document.getElementById('mesg').innerHTML = "receive data via xdm::" + e.data;
          document.getElementById('twitter').contentWindow.postMessage(e.data, origin);
        }
    }, false);
  }
  window.onload = function(){ initialize(); }
</script>
</body>
</html>
"""
    return response

@app.route("/twitter")
def twitter_processing():
    response = """
<!doctype html>
<html lang=ja>
<head>
<meta charset="utf-8">
</head>
<body>
<div id=mesg></div>
<div id=results></div>
<script>
var origin = location.protocol+"//"+location.host;
var parentWin = null;
var api="http://search.twitter.com/search.json?callback=show&rpp=50&geocode=";
var jsonpObj =null;

var sendJsonp = function(latlng, radius){
  if(jsonpObj)
    document.body.removeChild(jsonpObj);
  var scr = document.createElement('script');
  scr.src = api+encodeURIComponent(latlng+","+radius+"km");
  scr.type = "text/javascript";
  jsonpObj = document.body.appendChild(scr);
};

var show = function(obj){
  var results = obj.results;
  var out = '';
  var template = '<img src="#{img}"> <a href="http://twitter.com/\
#{from_user}" target="_blank"><b>#{from_user}</b></a> #{text}<br />\
#{created_at}<hr />';

  for(var i = 0; i < results.length; i++){
    var res = results[i];
    var tmp = template.replace("#{img}", res.profile_image_url) \
.replace("#{from_user}", res.from_user) \
.replace("#{from_user}", res.from_user);
    tmp = tmp.replace("#{text}", res.text) \
.replace("#{created_at}", res.created_at);
    out += tmp;
  }

  document.getElementById('results').innerHTML = out;
};

window.addEventListener('message', function(e){
  if(e.origin == origin) {
    if (e.data == 'init') {
      parentWin = e.source;
    } else {
      document.getElementById('mesg').innerHTML = e.data;
      document.getElementById('results').innerHTML = "読み込み中";
      sendJsonp(e.data, 5);
    }
  }
}, false);
</script>
</body>
</html>
"""
    return response

@app.route("/googlemap")
def google_processing():
    response = """
<!doctype html>
<html lang=ja>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body style="padding:0;margin:0;height:500px">
<div id=map_canvas style="width: 100%; height: 100%; border: 0px"></div>

<script>
var parentWin = null;
var origin = location.protocol + "//" + location.host;

var start = function() {
  var latlng = new google.maps.LatLng(35.164190, 138.678609);
  var myOptions = {zoom: 13, center: latlng, mapTypeId: google.maps.MapTypeId.ROADMAP};

  var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

  var getCenter = function(){
    var center = map.getCenter();
    var lat = center.lat(); 
    var lng = center.lng();
    if(parentWin) {
      parentWin.postMessage(lat+","+lng, origin);
    }
  };

  window.addEventListener('message', function(e){
    if(e.origin == origin) {
      if(e.data == 'init') {
        parentWin = e.source;
        getCenter();
      }
    } else {
      alert("illegal message from " + e.origin);
    }
  }, false);

  google.maps.event.addListener(map, 'dragend', function(e){getCenter();});
  google.maps.event.addListener(map, 'zoom_changed', function(e){getCenter();});

};

window.onload = function(){start();};
</script>
</body>
</html>
"""
    return response

if __name__ == "__main__":
    app.run()

javascriptの対話環境を入れた

昔、jsっていう対話環境入れてた気がするんだけど、覚えてないのでv8のやつをおもむろに入れてみたという話。

sconsを入れるために

sudo port install scons

って打ったら、opensslは入れるわ、pythonのバージョン上げるわでやたら時間がかかった。

scons入れたら

svn checkout http://v8.googlecode.com/svn/trunk/ v8
cd v8
scons
scons sample=shell

で対話環境が手に入る。

$ ./shell
V8 version 3.0.6.1
> (function (x,y){return x+y})(3,4)
7

ついでにnode.jsも入れた

wget http://nodejs.org/dist/node-v0.2.6.tar.gz
tar xvfz node-v0.2.6.tar.gz
cd node-v0.2.6
./configure
make
sudo make install

ProductName 徹底解説 HTML5 APIガイドブック コミュニケーション系API編
小松 健作
秀和システム / 2730円 ( 2010-12 )


来月からJavaScript: The Good Partsを読んでいきます

去年はHaskellの本を読んできたけど、この関数型プログラミングの技法はPythonでもPerlでもJavasriptでも役に立つことが多い。

しかも、静岡といえばλと言われるように、我々はラムダ式をより分かりやすい形でまちおこしに活用していかなければならないわけです(静岡県民として)。

というわけで(?!)、来月から半年くらいかけてJGPを読んでいきます。初回はあっさりした章が続くので3章くらい読み進める予定。それでも時間が余ると思うので、LT用のネタなど仕込んでくるといいと思います。

なお、本書は関数型プログラミングを薦める本ではなくて、良いjavascriptプログラミングをしましょうっていう本です。

第1回JavaScript読書会

  • 日 時 : 2011年2月12日(土) 13:00~17:30
  • 場 所 :富士市民活動センター・コミュニティF ( http://com-f.net/index.html )
  • 地 図 : http://com-f.net/access.html
  • 定 員 : 15名
  • 費 用 : 1,000円 (学生・未成年無料)
  • 持ち物 : パソコン、課題図書
  • 課題図書: JavaScript: The Good Parts (ISBN-10: 4873113911)
  • 環境  : JavaScriptのコーディング用エディタ及び動作確認用webブラウザ

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


参考