トップ «前の日記(2008-01-16) 最新 次の日記(2008-01-18)» 編集

Route 477



2008-01-17

[event][scheme] gauche.night 第2夜

http://practical-scheme.net/wiliki/wiliki.cgi?gauche.night

明らかに行くしかない

LTの募集は2/17まで.

[event][javascript] Kanasan.JS Javascript第5版読書会#2 のまとめ

Kanasan.JSサイ本読書会 #2 におじゃましてきました。

今回は読書会としては前代未聞の規模で正直どうなるかと思ったんですが、意外となんとかなって感激。 他言語(Javascript以外)の話題を制限したことも、今回は有利に働いたと思います。

リンク集

記録

以下、読書会のログです。なるべく会場の雰囲気を再現するように心がけてみました。

10:15

全員、順番に自己紹介する。俺到着。(迷ったorz)

10:23

amachang到着!

10:39 LTのターン

LTは、自分のスライドをいじってたりであまり聞けませんでした…_|‾|○ tyoroさんのブログが よくまとまっているので、 そちらを参照すると良いかと思います。

  • 長さん(hoge1e3さん)
    • 関東から
    • Web上でのゲーム製作
  • nanto_viさん
  • amachang
    • JSDeffered
  • 岩田さん
  • AWAWAさん
    • http://stack.nayutaya.jp/user/AWAWA
    • 自己紹介LT :-)
    • 仕事でJava + Javascript
    • 1年目:「Javascript?Javaの簡易版?」
    • 2年目:変数宣言とfunctionくらい
    • 3年目:document.write, innerHTMLを知る。JSで背景色が変更できることも知る
    • 4年目:thisの存在を知る。newでクラスっぽいものが作れることに気付くが、裏技だと思っている
    • 5年目:prototype.jsを知る
    • 6年目:Kanasan.JS ←いまここ!
    • 自作フレームワーク
  • emaさん
  • yhara
    • 非同期処理を同期っぽく書く方法について
    • 20080114#p02
  • ujihisaさん
  • deqさん
    • Flexでリアルタイム音生成
    • Flexの認知度:会場の6〜7割
    • 修論で、人間の喉から音が出る仕組みを物理シュミレーションを使って解析している
    • マシンから「い〜〜い」という声っぽい音がw
    • 秒間36000回くらいの計算をしているが、AS3でこなせてしまう
    • アイデア:ASで初音ミク(笑)
    • アイデア:物理シミュレーションのFLASHに、音もシミュレーションして鳴らす

12:24 休憩

昼飯。近所のラーメン屋へ。

  • amachangからサイボウズラボのここに書けない話を聞く(笑) *1
  • 関東のイベントは学生が少ない気がする。もっと来てほしい
  • JSで書くと使ってもらいやすいのが良い。
  • JSRubyHotRuby。つまり、パーザとVMはあるので、構文木からYARVのバイトコードを生成する部分をjsで書けばPure Javascriptかつ高速実行できるRuby処理系がwww
  • amachangにhttp://stack.nayutaya.jp/を宣伝した
  • amachangに「ふつける」をおすめした

ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門(青木 峰郎/山下 伸夫)

  • 「読書会ってこんな感じなのか」と聞かれたんですが、関西の最近の読書会がこんな感じ(Extreme reading)なだけで、普通の読書会(?)はこうではないかも。
    • 他には、毎回一人が決められた範囲を読んでみんなに説明する輪講形式とか。

13:30ごろ

机を並べ替え、大ーーきな長方形を作った。

…あの、対面がものすごく遠いんですが…w

13:36 読書会のターン

3つの重要なURL:

今回のルール:

  • 他言語トークは控えめに (いつもJavascript以外の言語の話に脱線するのでw)
  • イニシャルトークとかしない、全員で話題を共有する

13:48

ネットワークの設定に時間を取られる。

その間の繋ぎとして、cuzicさんによる自著宣伝のコーナー(笑)。

Rubyist Magazine出張版 Ruby on Windows(cuzic)

naoya_tさんにLTしてもらうか?という案もあったけど、 ネットワークの設定が終わったので幻のLTに。

13:51

iyou.png

13:52

Jashの使い方の説明。ブックマークレットなので、D&Dとか「お気に入りに登録」するのがインストール。

14:03 p81〜p103

しばらく、誰も喋らずチャットのログだけが伸びる異様な雰囲気にw

14:11 if文のカッコ

  • Q. p83のカッコは必要?:
    • カッコなし: if(address == null || address == "") {
    • カッコあり: if((address == null) || (address == "")) {
  • A. 中身が長いときは下の方が読みやすい。
    • 中身がとっても長いときは||のあとに改行入れるよね

14:13 空チェック

  • Q. 「nullまたは""か」のチェックって、ライブラリで提供されてたりしない?(Javaでいう)ApacheCommonのStringUtilみたいな。
  • A. Prototype.jsを使うと str.empty()で""かどうかはチェックできる。nullはチェックできないけど

14:14 caseラベル

  • caseラベルに(リテラルだけでなく)任意の式が書けるのか
    • これはC言語使いから見たら衝撃
    • p87の脚注にそんな話が。
  • switch(true){ case 条件式: ... } みたいに書けて便利、らしい
    • if elseを使えという話もあるが(どちらが綺麗か?)

14:16

shabereyo.png

14:20 式と文について

  • Q. function なんちゃら〜が式になるか、文になるかはどうやって決まる? 関数名が付いてるかどうか?
  • A. いや、関数名が付いてるかどうかは関係ない。function〜の前が文の終わりかどうかによって決まる。(後ろは関係ない)

というamachangとnanto_viさんの議論。

正確なところはnanto_viさんのログに期待^^;;

以降、式と文について喧々諤々。

  • Q. PrimaryExpressionてなに?
  • A. ECMAScriptの文法定義の一部。「リテラルか、変数参照か、式を()で括ったもの」とされている。
  • Q. なんで関数適用はPrimaryExpressionじゃないの?(amachang)

PrimaryExpressionって概念的になんなの?という話。

  • それ以上分割できないexpressionという意味とかではないのかな (hakobe説)
  • 文法の一番小さいやつがPrimaryExpression?? (kanasan説)
  • 実は「Primary」というネーミング自体にそんなに深い意味はないんじゃない? (yhara説)
  • Q. そもそも式と文の違いってなんなの?
  • A. 評価して値になるのが式。値にならないのが文。
    • 例えば、ifの条件のところには値が必要なので、if(式) はOKだけど、if(文)はNG。
    • というようなことは、文法定義を見れば分かる。(英語では、式=expression, 文=statement)

14:40

  • 脱線が元に戻らないので、この話はここで終わりに
  • 文と式が禁止ワードにw

14:44 これはひどい

p91の「こんなこともできます」の例がひどいwww

var o = {x:1, y:2, z:3}
var a = new Array();
var i = o;
for(a[i++] in o)
  ;

これを実行すると a = ["x", "y", "z"] になる(笑)

14:47 ラベル文の話

  • Q. なんか「6.10 ラベル文」がよくわかんないんだけど…
  • A. ラベルは主にbreakとcontinueで使うものだから、「6.11 break文」「6.12 continue文」を先に読むべき。というか章としてこっちが先に来るべき

ちなみに、JavaScript において、break 文は continue 文とは違い指定されるラベル名がループ文のものである必要はない。なので、

(function () {

...

if (shouldExit) return;

...

})();

と書く代わりに、

main: {

...

if (shouldExit) break main;

...

}

と書くこともできる。

[userChrome.js 用スクリプト: Days on the Moonより引用]

  • Q. ここでcontinue main; とするとどうなる?
  • A. p94真ん中 breakと違い、continueはループの中でしか使えない。
  • Q. 初心者的には、入り組んだループの中でどのループに対するbreak/continueなのかを指示するための記述ってことでいいですよね<label
  • A. そうだと個人的にはおもうんですけど、実際はどうなんでしょうね(kanasan)
    • 多重ループのときに使うのが一般的ですな。>ラベル (cuzic)
  • Q. break if(a){ label1 }else{ label2 } みたいに、動的にラベルを変えることはできるか?
  • A.できない。breakのあとにはラベル名のリテラルしか書けない。
  • Q. eval("break " + jumpto ); とかしたら、動的にbreak先を変えられたりしない?
  • A. eval文字列の外には飛べないっぽい。

15:00 functionがどこに書けるかの話

  • Q. Javascript では、最初に function 定義をぜーんぶ拾って、それから実行がはじまるんですか?<P.97
  • A. そうです

下にある関数も呼び出せるよ、という例。そういやRubyは下にある関数は呼び出せないんだっけか。なんかびっくりした。

なぜかAST(抽象構文木)の話に。抽象構文木は、プログラムを解析して木にしたもの(構文木)から余計なカッコとかの情報を取り除いたものらしい。(Wikipedia)

if文で関数定義を切り替えようとして嵌った話。

if(typeof(WScript) == 'object'){ //for cscript.exe(WSH)
  function puts(str){ WScript.Echo(str+"\n") }
}
else{ //for SpiderMonkey 
  function puts(str){ print(str+"\n"); }
}

これで環境によらないputs関数ができたお!!と思いきや、「if文の分岐結果によらず」下のputsの定義が 採用されてしまうという結果に。

そもそも、仕様上はif文の中で関数宣言(名前つき)してはいけない。無名関数ならOK。

if(typeof(WScript) == 'object'){ //for cscript.exe(WSH)
  var puts = function(str){ WScript.Echo(str+"\n") }
}
else{ //for SpiderMonkey 
  var puts = function(str){ print(str+"\n"); }
}
  • Q. じゃあfunction hoge(){}より var hoge = function(){}の方が安全という事ですね?
  • A. そうですね。
    • 後者ならif文の中にも(合法的かつ安全に)書けるので。
    • 名前が重複したときの動作を予測しやすいので。
    • 関数を使えるようになるタイミングが予測しやすいので。

15:13 空文の話

p.102では、空文を書く時はコメント入れましょうという提案がなされている。

  • サイ本方式: for(...) /*空文*/ ;
  • kanasan式: for(...){ ; }
  • tyoro式:
for(...)
  ;

それとは別に、「うっかりセミコロン問題」が紹介されているのだが、こっちは有効な解決策が 提案されていない(「注意しましょう」と書かれているだけ)。

if(...);          //ここにうっかりセミコロンが付いているので
  alert("hoge")   //この行が必ず実行されてしまう!

まあでも、「手がすべってセミコロンが入ってしまった」とか、注意する以外に解決策ないよねw

  • vimやemacsを使っていれば、インデントが狂うのでわかるはず
    • いや、人によってはインデントが狂うのが普通の状態のこともあるので、気付かない可能性も…
    • Q. それってどういう時よ?
    • A. Prototype.jsによるクラス指向など、Javascriptの新しい書き方がどんどん出てきていて、エディタが対応しきれてないのです

端的には、JSDefferedの「行末ドット」とか

行末派:

method.
chain()

行頭派:

method
.chain()
  • nanki: セミコロンをEnterに割り当ててるからそもそも押し間違えないよ派

15:22

あまりに人数が多いため、進捗状況が揃わなくて休憩が取りづらい罠。

でもあくまで全員が読み終わるまで待ちたいkanasan++

15:23 varが式でも…

  • Q. varが式でもいいんじゃない?(amachang)
    • whileの条件文とか三項演算子の中で新しい変数を導入したいときがある。
  • A. while(var a = ...){ ...} で a のスコープをwhileの中に限定するには、やっぱforみたいに特殊な構文で扱わないといけない気がする
  • Q. あれ、でもforにはvarが書けるじゃん。for(a;b;c) のaのところって文が書けるの?
  • A. p90 書けない。式しか書けない。varだけ、特例で許されている

forの構文の定義。まさにvarだけ特別扱いされている!

  • ちなみに "StatementNoIn" なのは、ここに「in」というキーワードが来るとfor〜in文と間違うからでは?という説。 StatementNoIn = 「in」以外の全ての式
  • せめて "StatementWithoutIn" だろ、というツッコミw

15:36

休憩を挟んで、サイ会再開。

nasrin.png

nasrin2.png

7章(p.105〜p.122)に突入。

15:41 配列の生成方法

  • Q. var ary = {} と var ary = new Array(); は同じ?
  • A. amachang: var ary = []; と var ary = new Array(); と var ary = Array(); は同じ

15:43 「.」は演算子か

  • Q. 「.」って「演算子」なのか?(amachang)
    • 日本語のecmascript仕様には演算子とかいてあるけど…、英語では別の表現(accessor)になっている。(演算子は"operator")
  • amachang:演算子ではないと思うよ派
  • nanto_vi:演算子の定義によるよ派
  • ema:「.」は「[]」の別名なので、演算子というよりシンタックスシュガーだよ派
    • シンタックスシュガーとは: 文法上、他の書き方ができるが、簡便のために用意されている構文のこと。
  • hakobe:でも.の後は識別子しか与えられないので厳密にはちがいそうだよ派
  • yhara:君が演算子だと思うものが演算子だよ派 (嘘)

15:58 「.」と「[]」はどっちが速い?

  • Q. x.aとx["a"]はどっちが速い?
  • A.ドットの方が速「そう」ではある。実際にどうなのかはベンチマーク取らないと分からない
    • nanto_vi: spidermonkeyでは、[]の中が単純な文字列なら、どちらも同じ中間コードにコンパイルされるので、速度に違いはない。
    • naoya_t: いやパースが3文字分短くなるからその分だけx.aの方が速い (※ミクロなレベルで)
    • ema: 100000 回ループで参照だけしてみましたが、たしかに差はなかったです @ firebug
    • yhara: あまり話題にならないってことは、あまり差がないんだろうなぁ、と想像。
    • yuya: キータイプ的には「.」の方が断然速い(笑)

16:03 jsインタプリタ

  • Q. 全然関係ないんですけど、jsrun(コンソールでファイルを実行)とかできたりしないですかね?

この質問、本番では拾えなかったんですが、

  • spidermonkey (Cによるjsインタプリタ)
  • rhino (javaによるjsインタプリタ)
  • cscript.exe (windowsのみ)

など、コマンドラインで実行できるjsインタプリタはいくつか存在します。

16:03 カンマだけで値を省略した場合は、未定義の要素が生成されます

p.113

var a = [undefined, undefined, undefined]
var b = [,,,]; //カンマ3つなのに注意!
  • Q. これらは同じか?
  • A. nanto_vi: 厳密には異なる(!)
    • 上の場合a[0]は存在してundefinedが入るが、下の場合b[0]がそもそも存在しない

Operaで試してみました。(Firefoxは挙動が違うかんじ)

 >> a.hasOwnProperty("0")
 false
 >> b.hasOwnProperty("0")
 true

16:04 undefinedとnullの違い

  • Q. undefinedとnullの違いは?
  • A. いろいろあるけど、例えばnullは予約語だが、undefinedは予約語ではない(単なるグローバル変数)。

なので、undefined = 100 みたいなコードも許される! undefinedを扱う時は、上書きされ得ることを想定していないといけないw

ただしundefinedオブジェクト(って言うのかな?)そのものが変更されるわけではないので、

var u = void 0; //参照:p78 void演算子
var u = (function(){})()

とかすることで元のundefinedオブジェクトを取得することができる。

16:08 プロトタイプ

hoge1e3さんの質問:

A=function(){}
A.prototype = {
   get: function() {return this.x*2;}
}
a=new A();
alert(a.constructor==A);

A=function(){}
/*A.prototype = {
   get: function() {return this.x*2;}
}*/
a=new A();
alert(a.constructor==A);

(以降、hoge1e3/amachang/nanto_viの3名による議論が行われたが、会場のほとんどがついていけなかったw)

プロトタイプチェインの話は9章なので、「続きは9章で」ということに。

  • Q. hoge1e3: (最初に意図していた質問) Perlのように、後からクラスを変えることは可能か?
  • A. nanto_vi: できない。

16:17 「0」というプロパティ

  • Q. 7.6.1と7.6.5の「配列の要素」とオブジェクトの話なんですけど「0」というプロパティをオブジェクトに追加したとすると配列の添字としては「0」は使えない、んですかね?
  • A. kanasan: どこかで暗黙の型変換が発生しするため、0という名前のpropartyと配列は同時には使えなかったはずです。
    • ema: 以下はtrueになります。
 var a = [{},{}];
 debug(a[0] === a['0']);

16:19 プロトタイプベースOOPについて

  • Q. 「クラスを実体化したものがインスタンス」としたら、プロトタイプはどう説明する?
  • A. amachang: jsでは「Array」もオブジェクトと同じように扱える。それがプロトタイプベースの世界。と自分は捉えている

参考? プロトタイプベース・オブジェクト指向

  • プロトタイプベースの元祖はSelfという言語らしい。

16:30 勉強会終了!

次回は7.5「配列」から。(既に7.5に入ってる人もいたが、きりが良いため&足並みを揃えるため、復習も兼ねて)

まとめ

ここまで読んだ人++。

Kanasan.JSは初中級者向けを標榜しつつ、実際にはちょくちょく高度な会話が飛び交い、しかし 初心者も上級者も「楽しかった」と言って帰って行くという非常に変わった集まりである。 勉強会における「初心者向けと上級者向けの兼ね合い問題」*2 に対し、一つの理想形を示したと言えそうだ。

もちろん、そのような雰囲気が自動的にできたわけではなく、その裏では 主催であるKanasanの「グループ分けはしない」「質問は全員で共有する」「全員が読み終わるまで待つ」 といった、場の一体感を重視する強い意志が働いていたことをここに記しておく。

Kanasan.JSは関東のイベントへの憧れから始まった勉強会だが、 関東とは別の価値を提示することによって、 いずれは逆に関東の人が来たくなるような勉強会になればいいなぁと思う。

*1 いや、個性的なメンツが多くて事務の人も大変〜みたいな他愛のない話ですけど

*2 Ruby関西も苦労している

本日のツッコミ(全2件) [ツッコミを入れる]
ema (2008-01-18 20:17)

長文まとめお疲れ様です!!<br><br>サイ本 p.113 にも書かれているのですが、[,,].length == 2 だったりするようです。ぎょっとしたのですが、最後のコンマは無視されるようです。<br><br>省略なんて使わないし、些細なことなのですが・・・

yhara (2008-01-19 17:14)

しまった。カンマ3つに直しておきました。どうもです。<br>「省略なんて使わない」には同意w