ふつうのLisp

一講目は yuumi3による Lisp初心者セッション

ふつうのLisp、 @yuumi3 http://bit.ly/4wJSim #railstokyo
1:31 PM Nov 15th webで

事前情報http://ey-office.net/redmine/wiki/gauche/ShibuyaLisp4
当日資料LispPrimer.pdf - Gauche 関連情報 - EY-Office

「rlwrap gosh」で起動するとreadlineがうれしい #railstokyo
1:37 PM Nov 15th webで

対話的 gosh、終るには「(exit)」ここにも括弧が要るの!

「(quote c)」シンボルのような、記法「'c」も同等。だから「('c)」は違うもの、というかえらーになる #railstokyo
1:41 PM Nov 15th webで
Lispは純粋関数型言語じゃないけど、リスパーは函数型が好み、代入文「set!」はなるたけ使わない #railstokyo
1:52 PM Nov 15th webで
「`」バッククォート構文、「,<何がし>」は実行されない、変数扱い。分かり易いという理念はわかるが、「,」(カンマ)が見慣れない。「%」とかなら良いのにと言ったら笑われた #railstokyo
2:05 PM Nov 15th webで
マクロ、文字列をいろいろ連結したりして、eval してメソッド作ってくれる、みたいな #railstokyo
2:07 PM Nov 15th webで
Lispは処理系作り易い、パーサも括弧見てけばいいのでシンプルにできるし、いろいろあって。なので処理系乱立したり、common lisp 出来たし、そしてそれは凄く大きいし #railstokyo
2:14 PM Nov 15th webで
Lispっていうのは処理系がシンプルだから、(言語の)詳しい話をするときは処理系の実装説明するのがいいと思う」 @yuumi3 さん #railstokyo
2:22 PM Nov 15th webで

Debian で Scalaインストール

Debian GNU/Linux 6.0 「Squeeze」testing (Debian -- Debian “buster” Release Informationこの時点で) をインストールして Scalaパッケージを入れてみる。

Squeezeのインストール

大過なし。

  • console-setup っていうのでちょっと何か聞かれる
    • キーボードとか、カーネル選択とか、initrdドライバとか
  • ソフトウェア選択で前見なかったものも
    • グラフィカル環境的な何か
    • SSH server
      • 暫く前に sshクライアントと sshdがパッケージ分離したけど、そのサーバの方がここに出てきたという事かな。これ選んでおいたらインストール直後から sshd 動いてた。
  • SQL データベースで入るの PostreSQL 8.4

Scalaパッケージあります

そして入るのは 2.7.5final

hs9587@vmw05:~$ scala
Welcome to Scala version 2.7.5final (OpenJDK Client VM, Java 1.6.0_0).
Type in expressions to have them evaluated.
Type :help for more information.

scala>
hs9587@vmw05:~$ aptitude show scala
パッケージ: scala
状態: インストール済み
自動的にインストールされた: no
バージョン: 2.7.5.dfsg-2
優先度: 任意
セクション: devel
メンテナ: Debian Scala Maintainers 
展開サイズ: 6,402k
依存: scala-library (= 2.7.5.dfsg-2), openjdk-6-jre | java-virtual-machine
説明: The Scala programming language
 Scala is a Java-compatible programming language with many modern language
 features.  It is Java-compatible in that Scala and Java classes can directly
 reference each other and subclass each other with no glue code needed.  It
 includes modern language features such as closures, pattern-matching,
 parametric types, and virtual type members.

 This package includes the various tools used to develop code written in Scala.
 It includes a compiler (scalac), an interpreter and script runner (scala), the
 offline compiler (fsc), and source-scanning documentation generator (scaladoc).
ホームページ: http://www.scala-lang.org/

OpenJDK 1.6.0 で動いています。

取り敢えず入ったよと、だけ。

Scalaで学ぶ関数型プログラミング

Rails' Wiki - RailsMeetingTokyo-0044出席、前半は Scala おおかゆかさん

その時のスライドの記事「http://ja.verbmode.net/2009/10/20/introduction_to_functional_programming_with_scala

前回Ruby使いのためのScalaのススメ - Rubyとか Illustratorとか SFとか折紙とかの続きでもある。

下記、ツイッター(志村 (hs9587) on Twitter)書き込み見ながら /10/24 書き起こしています。一週間近く経ってしまった。

  Rails勉強会東京44、前半は Scala #railstokyo
1:22 PM Oct 18th webで 
  Ruby使いのための Scala で学ぶ関数型言語 #railstokyo
1:29 PM Oct 18th webで   
  よりよい Ruby使いになるために、Lisp しよう、でも難しい。そこで Scala ですよ Scala #railstokyo
1:33 PM Oct 18th webで   
  Scala はもっとも Ruby に似た関数型言語Scala #railstokyo
1:34 PM Oct 18th webで   
  魔法少女Scalaちゃん @2009 熊ジェット Scala #railstokyo
1:35 PM Oct 18th webで   

個別「20090701122032」の写真、画像 - kumajet's fotolifeと言うことでいいのかな、元絵。

文法の基礎

  変数の定義、二種ある。val(値)型(推奨)、var(変数)型(使ったら負け) Scala #railstokyo
1:36 PM Oct 18th webで   
  var 変数名:型=値 (使ったら負け、普通の変数の感覚で使える) Scala #railstokyo
1:37 PM Oct 18th webで   
  val 変数名:型=値宣言は同じ描き方、再代入できない。
1:39 PM Oct 18th webで   
  純粋関数型言語(Haskel)とかは val型しかない、Scalaはvar型もある、非純粋型 Scala #railstokyo
1:40 PM Oct 18th webで   
  代表的な型、数値、文字列、シンボル、リスト Scala #railstokyo
1:41 PM Oct 18th webで   
  数値 val n:Int = 1、文字列 val str: String = "hoge"、シンボル val sym: Symbol = 'piyo。Scala #railstokyo
1:43 PM Oct 18th webで   
  リスト val (なんだっけ) Scala #railstokyo
1:45 PM Oct 18th webで   
  リスト val l: List[Int] = List(1, 2, 3)。 Scala #railstokyo
1:48 PM Oct 18th webで   
  Nil 空のリスト Scala #railstokyo
1:45 PM Oct 18th webで   
  1::2::3::Nil => List[Int] = +ist[1, 2, 3] Scala #railstokyo
1:46 PM Oct 18th webで   
  1 + 3 => Int4、これは、(1).+(3)、Rubyといっしょ? Scala #railstokyo
1:47 PM Oct 18th webで   
  関数の定義 def 関数名(引数名:型, …):返り値の型={ 処理内容(値を返す) } Scala #railstokyo
1:49 PM Oct 18th webで   
  関数、値を返す、処理内容の最後の処理の値が返る Scala #railstokyo
1:50 PM Oct 18th webで   
  型推論、Haskelとかモダンな関数型言語にはある。変数や関数の返り値の型宣言はコンパイラが推測できる限りにおいて、省略できる Scala #railstokyo
1:52 PM Oct 18th webで   
  型推論、省略できないもの: 引数の型 Scala #railstokyo
1:54 PM Oct 18th webで   
  List(1, 2, 3) は、Liat.apply(1, 2, 3) の事、applyメソッドは特別 Scala #railstokyo
1:56 PM Oct 18th webで   
  制御構文、少ない、4つか5つ、whileなんかは Rubyと一緒なんで省略 Scala #railstokyo
1:57 PM Oct 18th webで   
  制御構文 if。if (条件文1) 値1 else if (条件文2)値2 else 値3。 必ず値を返す Scala #railstokyo
2:00 PM Oct 18th webで   
  三公演算子はない、if文がそうだから。 Scala #railstokyo
1:59 PM Oct 18th webで   

三項演算子」だよね

  制御構文 for。大変奥深いものである Scala #railstokyo
2:01 PM Oct 18th webで   
  for (ブロック引数 <- コレクション; …) 処理内容。値を返さない Scala #railstokyo
2:02 PM Oct 18th webで   
  for (ブロック引数 <- コレクション; …) yield 値。値を返す Scala #railstokyo
2:03 PM Oct 18th webで   
  <- ブロック引数 Ruby なら縦棒二つを表現する記法 Scala #railstokyo
2:04 PM Oct 18th webで   
  <- ブロック引数 Ruby なら縦棒二つを表現する記法「←」と書いても良い Scala #railstokyo
2:04 PM Oct 18th webで   
  関数名とか引数名にマルチバイト使っても良い Scala #railstokyo
2:05 PM Oct 18th webで   

Ruby も使えるよ、無保証だったけど

  for の説明の中の「;…」、多重ループをなす、「; j <- リスト」とか続ける、さらに続ければ更に多重ループ Scala #railstokyo
2:07 PM Oct 18th webで   
  for(i <- 1 to 10 if i % 2 == 0) print i、246810。 Scala #railstokyo
2:10 PM Oct 18th webで   

関数型プログラミング

  そして関数型言語高階関数 map とか filter とかScala #railstokyo
2:12 PM Oct 18th webで   
  List(2,3,4).map(n => n +1) Scala #railstokyo
2:12 PM Oct 18th webで   
  n 二つ書くの面倒。List(1,2,3,4).map(_*2) => List(2,4,6,8) 魔法の記法、アンダースコア、まあ分かるよね Scala #railstokyo
2:13 PM Oct 18th webで   
  クロージャ、無名関数、関数を引数にとる関数。 val sq = (n: Int) =>Math.pow(n, 2).toInt。二乗を計算する関数 sq Scala #railstokyo
2:15 PM Oct 18th webで   
  Math はなんかそんなモジュール Scala #railstokyo
2:17 PM Oct 18th webで   
  関数と変数は等価 Scala #railstokyo
2:17 PM Oct 18th webで   
  def quartize(n: Int) = n / 4 val quarter = quartize _ これで quarter が関数 quartizeの処理内容のものになる。魔法のアンダースコア重要 Scala #railstokyo
2:22 PM Oct 18th webで   
  パターンマッチング。モダンな関数型言語ではあるよね、いいよね Scala #railstokyo
2:24 PM Oct 18th webで   
  パターンマッチングと値の束縛 Scala #railstokyo
2:24 PM Oct 18th webで   
  パターンマッチングとか一行呟きでメモるの難しい、あきらめ Scala #railstokyo
2:25 PM Oct 18th webで   
引数 match {
| case パターン => 処理1 or 値1
                …
| case _ => その他の場合(_)の 処理 or 値
}

こんな感じ、スライド参照

  再帰関数 Scala #railstokyo
2:26 PM Oct 18th webで   
  再帰関数は返り値の型宣言が必要 Scala #railstokyo
2:29 PM Oct 18th webで   
  カリー化、ハスケル・カリーさんの名前より Scala #railstokyo
2:32 PM Oct 18th webで   

ハスケル・カリー - Wikipedia

  カリー化。複数の引数を取る関数を、引数が最初の引数で、返り値が残りの引数を引数とする関数、とする、ようなものに化する。 Scala #railstokyo
2:34 PM Oct 18th webで   
  遅延評価、オブジェクトのフィールふぉの評価を、初期化時ではなく参照時に行うようにする、キーワード「lazy」を付ける。Haskelは全部遅延評価だったり。 Scala #railstokyo
2:38 PM Oct 18th webで   
  関数型言語、以上 Scala #railstokyo
2:41 PM Oct 18th webで   

Rubyっぽく

  せめて、Rubyっぽく Scala #railstokyo
2:42 PM Oct 18th webで   
  Implicit Conversion、暗黙の型変換。Rubyならオープンクラスでいろいろしてたり。静的型付けのScalaで同じ事は出来ない、が、暗黙の型変換を使えば結構なんとかなる Scala #railstokyo
2:44 PM Oct 18th webで   
  型が違うメソッド呼び出しとか、暗黙の型変換を宣言しておくとうまくいったり Scala #railstokyo
2:46 PM Oct 18th webで   
  Ruby の数値演算の coerce のような?、暗黙の型変換 Scala #railstokyo
2:48 PM Oct 18th webで   
  Structual Subtyping。Scala でダックタイピングっぽいことをやるための仕組み。 Scala #railstokyo
2:49 PM Oct 18th webで   
  Structual Subtyping。決められたメソッド名のメソッドを持っていれば受け入れて処理するような関数。 Scala #railstokyo
2:52 PM Oct 18th webで   
  というわけで、ひと通り。拍手。 Scala #railstokyo
2:55 PM Oct 18th webで   

面白かった、おおかさん有難うございます。大変興味を惹かれました、早く手元に動作環境整えたいです。

おまけ、後半は高橋さん

  MVCの話し、高橋さん #railstokyo
3:29 PM Oct 18th API
  ゼロ年代後半のMVCとしては、Web2.0は欠かせないわけですよ #railstokyo
4:28 PM Oct 18th API
  そろそろ話題も尽き、 #railstokyo
4:42 PM Oct 18th API
だいたい五時になりました、感想、振り返り #railstokyo
5:00 PM Oct 18th API

ペアプロ実習 LRUHash

今回の Rails勉強会@東京(タグ「railstokyo」 を検索 - はてなブックマーク)では、ペアプロ、TDD(BDD)/RSpec 実習(指導 akasaka.rb) がありました。

お題は LUR な Hash っぽいもの。サイズ制限があったりしてそれを超えると古い物からなくなってくようなもの。

取り敢えずその時のソース

かなり問題ありと思うのですが取り敢えずその時のソースを掲げます。

スペック

require 'lruhash'
#$VERBOSE = true

describe LRUHash do
  before(:each) do
    @lruh = LRUHash.new(2)
    @var = nil
  end # before(:each) do
  
  it 'should new by new(size)' do
    lambda{ LRUHash.new }.should_not raise_error
    lambda{ LRUHash.new(5) }.should_not raise_error
    lambda{ LRUHash.new(5, nil) }.should raise_error ArgumentError
  end # it 'should new by new(size)' do
  
  it 'should be Hash like []=' do
    var = nil
    lambda{ var = LRUHash.new }.should_not raise_error
    lambda{ var[:key] = 'value' }.should_not raise_error
    var[:key].should == 'value'
  end # it 'should be Hash like []=' do
  
  it 'should be respond to size' do
    @lruh.size.should == 0
    @lruh[0] = 1
    @lruh.size.should == 1
    @lruh[1] = 2
    @lruh.size.should == 2
    @lruh[2] = 3
    @lruh.size.should == 2
    @lruh[3] = 4
    @lruh.size.should == 2
    @lruh[4] = 5
    @lruh.size.should == 2
  end # it 'should be respond to size' do
  
  it 'should be get and add some key-value s' do
    @lruh.size.should == 0
    @lruh[0] = 1
    @lruh.size.should == 1
    @lruh[1] = 2
    @lruh.size.should == 2
    @lruh[2] = 3
    @lruh.size.should == 2
    @lruh[0].should be_nil
    @lruh[1].should == 2
    @lruh[3] = 4
    @lruh.size.should == 2
    @lruh[2].should be_nil
  end # it 'should be get and add some key-value s' do
  
  it 'should be get and add some key-value s' do
    @lruh.size.should == 0
    @lruh[0] = 1
    @lruh.size.should == 1
    @lruh[1] = 2
    @lruh.size.should == 2
    @lruh.delete(1)
    @lruh.size.should == 1
    @lruh.instance_variable_get(:@updated).should == [0,1]
    @lruh.instance_variable_get(:@updated).should_not == [0]
    
    @lruh[2] = 3
    @lruh.instance_variable_get(:@updated).should == [0,2]
  end # it 'should be get and add some key-value s' do
end

実装

class LRUHash < Hash
  def initialize(max_size = 3)
    @max_size = max_size
    @updated = []
  end # def initialize(max_size = 3)
  
  alias :add []=
  def []=(key, value)
    #@updated.delete key
    @updated << key
    puts "u:#{@updated}, k+:#{self.keys + [key]}"
    @updated = @updated - (@updated - (self.keys + [key]))
    if self.size >= @max_size
      #self.keys.include? @updated[0]
      self.delete(@updated[0])
      @updated.shift
    end # if self.size > max_size
    p @updated if $VERBOSE
    add(key, value)
  end # def []=
  
  alias :get []
  def [](key)
    @updated.delete key
    @updated << key
    p @updated if $VERBOSE
    get key
  end # def [](key)
end # class LRUHash

ちょっと問題点

なんでメソッドエイリアスチェイン、そこは super でしょ

実装の事

  alias :add []=
  def []=(key, value)
    <云々>
  alias :get []
  def [](key)
    <云々>

Hashオープンクラスのメソッドを変更するんじゃなくて、ちゃんと継承 LRUHash < Hash してるんだから、そこは super でしょう。
何考えてたんだろう。

数値を使うのはセンス悪いよ

スペック

    @lruh.size.should == 0
    @lruh[0] = 1
    @lruh.size.should == 1
    @lruh[1] = 2
    @lruh.size.should == 2

「@lruh[0] = 1」とか。key と value で値をずらしてるのはなんか意図を感じるけど、ここで整数値を使うのはよくないでしょう、誤解を招きやすい(配列参照とか)し。key はシンボルにしようよ。値はまあ、数値でもいいから。

このシナリオっぽいスペックの書き方

スペック

  it 'should be get and add some key-value s' do
    @lruh.size.should == 0

    # 一つ登録
    @lruh[0] = 1
    @lruh.size.should == 1

    # 二つ登録
    @lruh[1] = 2
    @lruh.size.should == 2

    # 三つ登録しても
    @lruh[2] = 3
    # サイズは増えなくて
    @lruh.size.should == 2
    # 最初に登録したのが無くなってる
    @lruh[0].should be_nil
    # 二つ目に登録したのは残ってる、そんでアクセスして順番繰上げ
    @lruh[1].should == 2

    # 四つ登録して
    @lruh[3] = 4
    # サイズは増えなくて
    @lruh.size.should == 2
    # 三つ目に登録したのが無くなってる
    @lruh[2].should be_nil
  end # it 'should be get and add some key-value s' do

スペック

  it 'should be get, delete, and add some key-value s' do
    @lruh.size.should == 0
    # 一つ登録
    @lruh[0] = 1
    @lruh.size.should == 1
    # 二つ登録
    @lruh[1] = 2
    @lruh.size.should == 2

    # そこで二つ目に登録したのを削除
    @lruh.delete(1)
    @lruh.size.should == 1
    # でもキーリストからそのキーは消えてない
    @lruh.instance_variable_get(:@updated).should == [0,1]
    # 本当はキーリストはこうなるべきなんじゃないの、なってないけど
    @lruh.instance_variable_get(:@updated).should_not == [0]
    
    # また登録
    @lruh[2] = 3
    # 登録のときにお掃除してちゃんとなるのさ
    @lruh.instance_variable_get(:@updated).should == [0,2]
  end # it 'should be get and add some key-value s' do

順次状態を作りながら(変えながら)、should してくのも問題(一つの it に should は一つが原則っぽい、せめてなるたけ少なく)だが、コメントがないと何を確かめてるか分からないのはもっと問題。コメントを補えば良いというものでもない。it の引数文字列とか変数名メソッド名で自然と分かるようになってなくちゃ。

ちょっとだけ直す

今になって「かなり問題あり」という部分だけ修正したのがこちら

スペック

require 'lruhash'
#$VERBOSE = true

describe LRUHash do
  before(:each) do
    @lruh = LRUHash.new(2)
    @var = nil
  end # before(:each) do
  
  it 'should new by new(size)' do
    lambda{ LRUHash.new }.should_not raise_error
    lambda{ LRUHash.new(5) }.should_not raise_error
    lambda{ LRUHash.new(5, nil) }.should raise_error ArgumentError
  end # it 'should new by new(size)' do
  
  it 'should be Hash like []=' do
    var = nil
    lambda{ var = LRUHash.new }.should_not raise_error
    lambda{ var[:key] = 'value' }.should_not raise_error
    var[:key].should == 'value'
  end # it 'should be Hash like []=' do
  
  it 'should be respond to size' do
    @lruh.size.should == 0
    
    # 一つ登録
    @lruh[:a] = 'a'
    @lruh.size.should == 1
    
    # 二つ登録
    @lruh[:b] = 'b'
    @lruh.size.should == 2
    
    # 三つ登録しても
    @lruh[:c] = 'c'
    # サイズは最大値の儘
    @lruh.size.should == 2
    
    # 四つ登録しても
    @lruh[:d] = 'd'
    @lruh.size.should == 2
    # 五つ登録しても
    @lruh[:e] = 'e'
    @lruh.size.should == 2
  end # it 'should be respond to size' do
  
  it 'should be get and add some key-value s' do
    @lruh.size.should == 0
    @lruh[:a] = 'a'
    @lruh.size.should == 1
    @lruh[:b] = 'b'
    @lruh.size.should == 2
    @lruh[:c] = 'c'
    @lruh.size.should == 2
    # 順に三つ登録すると
    
    # 一つ目に登録したのはもうない
    @lruh[:a].should be_nil
    # 二つ目に登録したのはある、そしてアクセスして順序繰り上げ
    @lruh[:b].should == 'b'
    
    # 四つ登録
    @lruh[:d] = 'd'
    @lruh.size.should == 2
    # さっき繰り上げといたので、二つ目は残ってる
    @lruh[:b].should_not be_nil
    # 三つ目が消えてる
    @lruh[:c].should be_nil
  end # it 'should be get and add some key-value s' do
  
  it 'should be get and add some key-value s' do
    @lruh.size.should == 0
    @lruh[:a] = 'a'
    @lruh.size.should == 1
    @lruh[:b] = 'b'
    @lruh.size.should == 2
    # 順に三つ登録すると
    
    # 二つ目に登録したのを削除
    @lruh.delete(:b)
    @lruh.size.should == 1
    # でもキーリストからそのキーは消えてない
    @lruh.instance_variable_get(:@updated).should == [:a, :b]
    # 本当はキーリストはこうなるべきなんじゃないの、なってないけど
    @lruh.instance_variable_get(:@updated).should_not == [:a]
    
    # また登録
    @lruh[:c] = 'c'
    # 登録のときにお掃除してちゃんとなるのさ
    @lruh.instance_variable_get(:@updated).should == [:a, :c]
  end # it 'should be get and add some key-value s' do
end

実装

class LRUHash < Hash
  def initialize(max_size = 3)
    @max_size = max_size
    @updated = []
  end # def initialize(max_size = 3)
  
  def []=(key, value)
    @updated.delete key
    @updated << key
    puts "u:#{@updated}, k+:#{self.keys + [key]}"
    @updated = @updated - (@updated - (self.keys + [key]))
    if self.size >= @max_size
      #self.keys.include? @updated[0]
      self.delete(@updated[0])
      @updated.shift
    end # if self.size > max_size
    p @updated if $VERBOSE
    super
  end # def []=
  
  def [](key)
    @updated.delete key
    @updated << key
    p @updated if $VERBOSE
    super
  end # def [](key)
end # class LRUHash

個別のコメントや当日の感想、更に直すべき所とか、また後で追記します(/6/22 24:40)。

個別のコメントの前に列の伸び方、方向

(/6/23 追記)
みなアクセス順にキーを貯える配列を使っていた。t-wadaさんのヒントもあって、1.9系でその必要のないペアを除いて、みんなアクセス順をみるキーの配列を作っていた。
それでレビューの時にちょっと疑問が出たのできいてみたわけです。

「みんな新しいキーを配列の後ろから追加して、古いのを前から削除してる。なぜ」

はじめ偶然じゃないか、たまたまみんなそうだっただけだよという声でしたが、良くきいてみると感覚的にみんなそうしてるみたい。

配列の操作はまず shift、push、pop の組みで考えてるから、とか。待ちキューのつもりだから新しいのは列の後ろに追加してって、先頭で順次処理してく、処理が今の場合削除なだけ、とか。後ろから消すって pop ってことだけど、pop はスタック処理で縦に積んでるという感覚で、今回の列に並べる感じに合わない、とか。
なんか感覚的にそんな感じというのがあって面白かった。

僕自身は、それらの感覚ももっともなんだけど、列というのが後ろの方に行くにつれてよく分かんなくなっていって、後ろの末で忘れられてなくなってくというイメージもあって、後ろに伸びてくようにするか前にずれてくようにするか、実はちょっと随分迷うところあります。
そして、Array に要素追加するのに「<<」が一番楽だという実装感覚で前にずれてくように作ります、作りました。
僕の個人的な感覚です。

NetBeans とか IDE

(/6/27追記)
ペアプログラミングとしては、はじめパートナーの NetBeans 環境でやってみた。RSpec は初めてということで、そのインストールから。で、IDEIDEなりに便利。それで RSpec(付き)プロジェクト作れるようになってるし、少し作るとスペックファイルまで自動生成してくれる、before(:esch)ブロックで取り敢えずテスト用のインスタンス変数 new する所まで。
ただ、require のパスが通らなかったり、始めちょっとそれなり設定必要みたいで、そこで時間かけても仕方ないのでその辺で環境こちらのものに変えました。

IDEIDE なりに良いですね。リードに従ってると凄く楽っぽい。


(/6/27 なんかばたばたしてるうちに一週間経ってしまった。もう個別のコメントはなしで、ソース見て下さい。)

Amazon EC2 関連

ちょっと覚書き

サービスコンソール

ここから、「Amazon EC2」のタブを開く。そしてログインしてEC2の個コンソールへ。

支払い情報はコンソール内ではなく、右上の Navigationメニューの Your Account の Account Activity にあるの注意。そっちに行こうとするともう一度パスワード認証がある。

コンソール自体の使い勝手はまあ良いんだけど、ちょっと横に長い。コントロールが右端にあって、しかもはみ出してると操作不能になるので注意。はみ出しているためそもそも気が付かないとか注意。

キーペア

起動した EC2インスタンス(仮想マシン)への sshアクセスにはコンソールで Key Pairs を作成しておく必要がある。作るとプライベートキー(.pemファイル)がその場でダウンロードしてくるので大切に保存する。クライアント側の ssh の為にアクセス権限注意「chmod 600」とか。

WindowsPuTTY 使うときはそのファイルを PuTTYgen(PuTTY Key Generator)を使って専用形式に変換する必要がある。「Load」釦を押して「.pem」ファイルを選択、必要ならパスフレーズを設定して、「Save private key」して「.ppk(Putty Private Key Files)」ファイルを作る。PuTTY起動時に認証のためのプライベートキーファイルに指定する

(最初の)ログインは取り敢えず rootユーザなの注意。「root@<インスタンスの Public DNS: ec2-<IPっぽい-数字->云々>」コンソールでインスタンスを選んでおいて Public DNS 欄をコピーしてくる。

最初のインスタンス

最終的には自前で AMI (Amazon Machine Image) を用意した方が良いだろうけど最初様子見て Amazonさん自身が用意した FedoraRuby on Rails イメージを使うことにする。smallマシーン

起動時点で http://<ec2-<IPっぽい-数字->云々> に行くと Rails の Welcome aboard が動いている。最初から。

ログインしてみた

root で入ってみる。噂に聞くとおり確かに ssh のレスポンスに一拍おくような感覚がある。まあ、慣れれば問題ないレベル。

この機械のハードディスクの様子はこんな感じ

[root@domU-12-31-38-00-28-D2 ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             9.9G  1.3G  8.2G  13% /
/dev/sda2             147G  188M  140G   1% /mnt
none                  854M     0  854M   0% /dev/shm
[root@domU-12-31-38-00-28-D2 ~]# mount
/dev/sda1 on / type ext3 (rw)
none on /proc type proc (rw)
none on /sys type sysfs (rw)
none on /dev/pts type devpts (rw,gid=5,mode=620)
/dev/sda2 on /mnt type ext3 (rw)
none on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
fusectl on /sys/fs/fuse/connections type fusectl (rw)
[root@domU-12-31-38-00-28-D2 ~]# cat /etc/fstab
/dev/sda1               /                       ext3    defaults 1 1
/dev/sda2               /mnt                     ext3    defaults 0 0
/dev/sda3               swap                    swap    defaults 0 0
none                    /dev/pts                devpts  gid=5,mode=620 0 0
none                    /dev/shm                tmpfs   defaults 0 0
none                    /proc                   proc    defaults 0 0
none                    /sys                    sysfs   defaults 0 0

fdiskで夫々の領域をみる

Disk /dev/sda1: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xa68331d3
Disk /dev/sda2: 160.1 GB, 160104972288 bytes
255 heads, 63 sectors/track, 19464 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x3177e8d0
Disk /dev/sda3: 939 MB, 939524096 bytes
255 heads, 63 sectors/track, 114 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0xdd33fe4e

CPU とメモリ

[root@domU-12-31-38-00-28-D2 ~]# cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 15
model           : 65
model name      : Dual-Core AMD Opteron(tm) Processor 2218 HE
stepping        : 3
cpu MHz         : 2599.998
cache size      : 1024 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 1
wp              : yes
flags           : fpu tsc msr pae mce cx8 apic mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow up pni cx16 lahf_lm cmp_legacy svm extapic cr8legacy ts fid vid ttp tm stc
bogomips        : 6502.57
clflush size    : 64
 root@domU-12-31-38-00-28-D2 ~]# free
             total       used       free     shared    buffers     cached
Mem:       1747764     301228    1446536          0      34156     178896
  • /+ buffers/cache: 88176 1659588
Swap: 917496 0 917496
Railsの起動スクリプト

root の contab から起動していた

[root@domU-12-31-38-00-28-D2 ~]# crontab -l
# restart your mongrel server
@reboot /bin/sh /home/webuser/helloworld/restart.sh
@reboot /bin/sh /etc/init.d/mysqld start
[root@domU-12-31-38-00-28-D2 ~]# cat /home/webuser/helloworld/restart.sh
#!/bin/sh
cd /home/webuser/helloworld/log && rm mongrel.pid -f
pkill -9 mongrel_rails -u root
cd /home/webuser/helloworld && /usr/bin/mongrel_rails start -e development -p 80 -d
useradd

「groupadd」「useradd」してみる。作ったユーザの authenticated_keys に適当な公開鍵をセット。
それはそれで ssh接続可能になる。一度ここまでくれば、EC2コンソールで作るキーペアじゃなくても大丈夫と言うことだ。

shutdown

そして「/sbin/shutdown -h now」暫くするとEC2コンソールのインスタンス状態も terminated になる。もう復活は出来ない。

『Javaの掟・Rubyの掟 〜寝ても起きてもプログラミング〜』出席

『Javaの掟・Rubyの掟 〜寝ても起きてもプログラミング〜』
arton(著者)×宇野るいも(著者)×高井直人(著者)×高橋征義(日本Rubyの会会長)
■2009年2月5日(木)19時〜
http://www.junkudo.co.jp/newevent/talk-ikebukuro.html#talk-ikebukuro-top
行って来た、リンクはトークセッション最新情報で、旧情報はでて来ないの注意。過去ログはどこにあるのかな。
話題の本は 4冊3種

トークショーを聞いて、どれもみんな読みたくなる買いたくなる(既に買ってるものもあったけど)のであった。
個人的に読みたくなった点を挙げる。

コーディングの掟(最強作法) 現場でよく見る不可解なJavaコードを一掃せよ! (開発の現場セレクション)

ちょうど Java についての基本的な常識に欠けるなあと思っている所だったので読まねばならないなあと思わされた。僕はまだまだ文法事項を知ってるだけで(それも半可通)、Java の理念を分かってない。
この本自体は、開発のちょっと上流のかた向けという事で、それでもコーディングのいろいろな所、問題点を意識して欲しいという事のようだ。
そこで扱われてる諸問題のうち、スレッドのはなし(二章を割いてる)、最近スレッド関連でちょっとあったので特に読みたい。「マルチスレッドを理解しよう」

プログラミング学習シリーズRuby

プログラミング自体のはじめ、初級からの学習であって、言語としては Ruby を用いる。というものだという事です。

プログラミング学習シリーズ Ruby 1 はじめてのプログラミング

コンピュータとはなにか、二進数とかからはじめている。でもエンディアンの説明もしている。

そしてソースはその後どう扱われるのか、語句解析と構文木の説明もしている(簡単だけど)。artonさんが過去入門書でこの辺の説明を受けたことが無くて不満だったとか。
最近 Racc を触り始めて特に実感する、そういえば僕も大分後になってからスキャナ、パーサ、構文木の事を知ったなあ。

Ruby 2 さまざまなデータとアルゴリズム (CD-ROM付) (プログラミング学習シリーズ)

二巻の初めの方で画像を操作する(ビットマップ画像を作る、バイナリ)。すごい。

あと状態遷移と正規表現。状態遷移の話しもちょっと興味ある。

第3巻(近刊)

クラスと継承と設計の事などだそうだ。全くのはじめてからこのレベルまで達するの、凄いなあ。どういう説明をするのか興味津々。

JavaプログラマのためのRuby入門

artonさんは、4,5章、オブジェクトの拡張のいろいろな Ruby手法とその方針を書きたかったとのこと。
モジュール、Mix-in、継承、オープンクラス、ダックタイピング、リフレクションとかいろいろやり方があるんだけど、どういう場面どういう手法を使うのがいいのかまとまってる文書がなかったので書きたかったとのこと。
それは確かに知りたい、読んでみたい。

でも 後で読み返すとその前の章の if の説明とか非常に面白かったそうだ。

そしてこの本は Rubyist のための Java の書き方という本にもなってるかもしれない(どこまで?)
基本的に Ruby のソースと Javaならどう書くかのソースがペアになってる(実は書けないとかもあったりするそうだ)
それは大変参考になる、読みたい。

あとJruby の章重要
全般的な注意、ちょっとつらい所の回避(添付ライブラリ大変だったよね)、(J)RubyJavaAPIを(ライブラリ)を使うとか。

付記

話題は他にもいろいろありました。以上は聞いていて僕が読みたくなったポイントです、全然全てではありません。
という事で、全部ちゃんと読みたくなった、時間あるかな。

標準エラー出力とパイプ「|&」(zsh)

zsh標準エラー出力をパイプに送る(そして lv で見る)には「|&」で繋ぐ、略記をしないなら「2>&1 |」でも良い。標準出力も同時に(同時ではないか、合わせて)パイプに繋がれる。

標準出力なし、標準エラー出力のみというのは無いみたい。