Sunday, August 31, 2008

Graphviz

Rubyのオブジェクト関係のマップを作成するのに検索していたら
Graphvizというダイアグラム作成ソフトを見つけた
オープンソースのdotというプログラムをGUI化したものだ

テキストでダイアグラムの要素を記述するとそれをレンダリングしてくれる
グラフの細かい設定とかはちょっとむずかしそうだけど
簡単に書けて用意に変更できるので
普通に使うには大変良い


Thursday, August 28, 2008

バランスボールってあり?

プログラマーの小野和俊という人が
日経ソフトウェアだったかに連載を書いていて
今日図書館で見たら
バランスボールを椅子の代わりに使って快適プログラミング
というようなことが書いてある

へぇ〜
意外といいかも
インテリア的にどうだろうか
もしかしたらしっぽにもいいかも?
検討の余地あり?


Programming Ruby 3 - New topics

  • RSpec: write rspec first, then implement code
  • Organize project: top/ ./bin ./lib/top ./test
  • Use setup.rb for distributing project
  • RubyGems: open rdoc for library: open $gemdoc/builder/.../rdoc/index.html
  • Encoding: # encoding: utf-8/ over 7bit characters assume the source file encoding
  • Input Output Encoding: File.open("filename", "r:iso-8859-1:utf-8:")
  • irb: load "your ruby file with classes or methods" : you use the classes in irb session. also can edit the file after loaded.
  • irb: use tab completion alot
  • irb: use irb in irb to make a subsession: jobs, fg 0, kill 1
  • irb: use irb with specific class: irb "wombat"

  • Constant: Constant can define from the outside.
  • Module: module_function: makes instance method module method also.
  • Exception: rescue modifier: ["1","2.3",/pattern/].map {|v| Integer(v) rescue Float(v) rescue String(v)}
  • Exception: retry can be used in rescue clause.
  • methods(false): just show methods in the object; exclude superclasses'
  • Duck typing: if you need check types: use obj#respond_to?
  • type conversion: method coersion: 1.coerce(2.3) -> [2.3,1.0];define coerce method in your class correctly, you get arithmetic func with numbers.
  • metaprogramming:module:ruby makes anonymous super class for a class, in which module is mixed in.
  • metaprogramming:extend: when use extend to a obj, the module is included to an anonymous class of the obj.
  • metaprogramming:extend: when use extend in a class, the module method become its class method. that means extend makes singleton method

Wednesday, August 27, 2008

Rubyのクラスはソフトのコーン

みんな大好きソフトクリーム
ソフトとコーンでできている
みんなは最初教えてくれる
コーンは容器と教えてくれる

それに答えてしっかりと
ぼくは正しく記憶する
コーンは容器と記憶する
ソフトの容器と記憶する

でもぼくが
そろそろソフトを食べ終わるとき
それを教えた人たちは
とぼけた顔で白状する
実はコーンも食べれると

そうならば
先にそうだと言ってくれ
コーンもおいしく食べれると
そうすれば
コーンが汚れず済んだのに

みんな大好きRubyのことが
オブジェクトとクラスでできている
みんなは最初教えてくれる
クラスは雛形と教えてくれる

それに答えてしっかりと
ぼくは正しく記憶する
クラスは雛形と記憶する
オブジェクトの雛形と記憶する

でもぼくが
そろそろオブジェクトを理解したとき
それを教えた人たちは
とぼけた顔で白状する
実はクラスもオブジェクトよと

そうならば
先にそうだと言ってくれ
クラスもメソッド呼べるのと
そうすれば
シングルトンとすぐ分かるのに

*だから
Rubyのクラスはソフトのコーン
Rubyのクラスはソフトのコーン
容器のようで容器でない
雛形のようで雛形でない

ぼくの覚えが悪いのは
ぼくだけのせいじゃない*

*繰り返し

みんな大好きRubyのことが
オブジェクトとクラスでできている

Tuesday, August 26, 2008

ソートプログラム

これはいったい何ソート?
バブルソートの変形になるの?
  • 先頭から隣り合うデータを比較
  • 大小が逆ならスワップ
  • スワップした時は一つ前に戻ってまた比較
  • これを繰り返す

   1  #!/usr/local/bin/ruby

   2  # encoding: utf-8

   3  class Array

   4    def thought

   5      n = 0

   6      until n == self.length - 1

   7        if comp(n)

   8          swap(n)

   9          n -= 1 unless n < 0

  10          redo unless n < 0

  11        end

  12        n += 1

  13      end

  14      self

  15    end

  16    

  17    private

  18    def comp(n)

  19      self[n] > self[n+1]

  20    end

  21    

  22    def swap(n)

  23      self[n], self[n+1] = self[n+1], self[n]

  24    end

  25  end

  26  

  27  a = [4,3,6,8,1,2,9,5,7,0,12,23,87,13,33,14,56,21,89,100,44,22]

  28  p a.thought

Saturday, August 23, 2008

Ruby1.9

TerminalでRuby1.9と19対応irbをデフォルトにセット
1.8.7は_ruby, _irbで起動する

mail to bloggerがだめだ

数日前からメイルからのブログ投稿ができてないようだ。

Friday, August 22, 2008

Programming Ruby 3rd - new topics

  • IO.foreach('file') {|line| puts line}
  • 'abcdefghi'.scan(/abc(..)(..).*/) # => [[cd],[ef]]
  • StringIO: use string like io
  • Network library: socket, net/http, open-uri
  • Fiber: fiber is like a block object
  • Thread: use thread local variable: Thread.new(arg) {|val| ...}
  • Thread: threads.join can wait all
  • Thread: thread variables: can store current thread to a hash: Thread.current["mycount"] = count

RSpecがいいかもしれない

Rubyの新しいテストフレームワークにRSpecというものがある
このフレームワークは今までのように書いたコードを
後からテストするためのものではなく
先に仕様を書いてそれに合わせてコードを書くような開発方式を強いる
これをBDDとかTDDとかいうようだ

具体的には以下の手順になる
まずこれから書こうとしているコードの期待される出力を仕様として書く
その仕様をこれに関連付けてコードにする
テストしてみる(当然エラーが出る)
エラーがなくなるようにコードを書く
サンプル(階乗計算コード)


require "fact"
describe "Fact", "basic factorial" do
before(:each) do
@ts = Fact.new
end
it "should be 1 when 1!" do
@ts.fact(1).should == 1
end
it "should be 6 when 3!" do
@ts.fact(3).should == 6
end
it "should be 120 when 5!" do
@ts.fact(5).should == 120
end
end

今後なるべくBDDで開発してみよう

RSpec-1.1.4: Overview
http://rspec.info/

Wednesday, August 20, 2008

Programming Ruby 3rd - new topics

  • expressions: method chain: def <<(other); total += other; self end
  • expressions: define []=: def []=(*params);  obj.[]=(1,2) # => [1,2]
  • expressions: backticks also a method of Kernel, that can redefine.
  • parallel assignment: f, *, l = 1,2,3,4,5 # f = 1, l = 5
  • nested assignment: a, (b,c), d = 1,2,3,4 # a = 1, b = 2, c = nil, d = 3
  • flip-flop function with range: while puts line if line=~/third/..line=~/fifth/
  • flip-flop while if (($.==1)||line=~/eig/)..(($.==3)||line=~/nin/); print line
  • redo if line.gsub!(/`(.*?)`/){eval($1)}
  • ary.each do |val; outer-local|
  • block local scope: [1,2,3].each {|a,b|} or {|a;b|}#b is local val of block 

Blog next post will be...

以下についてまとめる
  • ブロック変数
  • パラレルアサインメント
  • ラムダのシンタックスシュガー

Ruby Block local

Ruby1.9で新たなブロックローカルの構文が導入された
垂直バー内で";"の後の変数はブロックの外の変数とダブってもローカルになる
でカンマも数が合えば許されているみたいだな
それとも隠しコマンド?

#!/usr/local/bin/ruby
# encoding: utf-8
s = 'yes'
total = 0
{a: 2, b: 3}.each do |v,k,s|
  s = k**2
  total += s
end
puts total
puts s

Tuesday, August 19, 2008

A blog theme candidate

Rubyを使ったオブジェクト指向最初の一歩
  • あるファイル上のデータ、例えば書籍データを読み込んで管理するプログラムを考える。
  • 最初に配列とハッシュを使った例を示す。
  • これらでのアクセスを示す。
  • その問題点を示す。
  • それからオブジェクトモデルを示す。
  • そのアクセスと利点を示す。

Programming Ruby 3rd _new topics for me

  • regexp: \p: encoding-aware
  • regexp: &&: [a-z]&&[^aeiou] means match a to z but vowels
  • regexp: named group: /(?<word>\w)\k<word>/ #repeat same words
  • regexp: named group: /(?<hour>\d\d)/;"Hour is #{hour} #it also can refer after as param
  • regexp: sub can get a hash as the replacement param
  • regexp: 'a\b\b'.gsub(/\\/, '\&\&') # => "a\\b\\c"
  • method: pass all params: def initialize(*); super; end
  • method argument with splat: method_one(*[1,2], 3, *(4..8))

Web Site idea

Blog Post Comparison Site

  • 同じテーマでの投稿をまとめたサイト
  • ユーザによる投稿・評価
  • 評価に応じて報酬
  • あるいは記事をPDFとかにして販売
  • 例えばRubyのブロックについての投稿

これはいけると思う

Monday, August 18, 2008

Programming Ruby 3rd

New topics -p118
  • Hash new idiom: { cell: 'string', clarinet: 'woodwind'}
  • require_relative
  • be capable Comparable: def <=>(other)
  • be capable Enumerable: def each
  • unit test
  • parameters to a block are always local to a block
  • [1,2,3].each {|value; square| square} #square is local
  • inject(:+)
  • external iterator: [1,2,3].to_enum.next
  • enumerator makes objects enumerable
  • enumerator stops loop
  • -> { puts 'hello'}, -> arg, *ary, &block { |e| ... }
  • 3 + 4.im
  • string encoding
  • Song = Struct.new(:title, :name, :length); Song.new('hello', 'John', 3.14)

Sunday, August 17, 2008

Ruby Accessor


アクセッサメソッドの等価コード
attr_rをModuleクラスに書くとうまくいくが
他のクラスやモジュールに書いてもなぜかうまくいかない

   1  #!/usr/local/bin/ruby

   2  # encoding: utf-8

   3  class Module

   4    private

   5    def attr_r(*arg)

   6      arg.each do |key|

   7        class_eval <<-EOS

   8          def #{key}

   9            @#{key}

  10          end

  11        EOS

  12      end

  13    end

  14  end

  15  

  16  class Book

  17    attr_r :isbn, :price

  18    def initialize(isbn, price)

  19      @isbn, @price = isbn, Float(price)

  20    end

  21  end

  22  

  23  b = Book.new(123, '10.45')

  24  p b.isbn

  25  p b.price

  26  # >> 123

  27  # >> 10.45


class_evalに代えてdefine_mothodを使う手もある
まあ結局evalするんだが

   1  #!/usr/local/bin/ruby

   2  # encoding: utf-8

   3  class Module

   4    private

   5    def attr_r(*arg)

   6      arg.each do |key|

   7        define_method("#{key}") do

   8          eval "@#{key}"

   9        end

  10      end

  11    end

  12  end

  13  

  14  class Book

  15    attr_r :isbn, :price

  16    def initialize(isbn, price)

  17      @isbn, @price = isbn, Float(price)

  18    end

  19  end

  20  

  21  b = Book.new(123, '10.45')

  22  p b.isbn

  23  p b.price

  24  # >> 123

  25  # >> 10.45


Wednesday, August 13, 2008

Brooke Waggoner

YouTubeでSubscribeしてるkierstenmhという人が歌っていた
SoSoという曲が良かったのでそのアーティストBrookeWaggonerという人のサイトにいったら
なんと
その曲を含むアルバム全6曲を無料ダウンロードできた
すげー
なかなかいい曲ぞろいだぞ

Tuesday, August 12, 2008

Rubyと私

Yugui著「初めてのRuby」を買ってから
Rubyに対する気合いが更に燃え上がっている
この2週間でRuby関連のブログを3本投稿した
どれもとても長い

1本目はシンボル、2本目はブロック、3本目はevalについて書いた

1本目ははてなのホットエントリーに乗ったらしく
いつも50以下のアクセスが300になってびっくりした
続く2本目にも期待したがアクセス数は
いつもどおりに戻った
3本目を今日投稿したがこれも同様だろう

でもこれらの投稿が自分にとっての最良の勉強となっている
かなり理解が深まった

次は何をしよう
まずはRubyマニュアルの読み込みだな
それでまたネタを探そう

Sunday, August 10, 2008

eval

   1  #!/usr/local/bin/ruby
2 # encoding: utf-8
3 class Array
4 def yield
5 yield self
6 end
7 def ival(s)
8 self.send(s)
9 end
10 end
11
12 [1,2,3].yield do |s|
13 puts s.reverse!
14 end
15
16 [1,2,3].instance_eval do
17 puts self.reverse!
18 end
19
20 a = [1,2,3]
21 a.ival "reverse!"
22 p a

Saturday, August 02, 2008

シンボルは文字列の皮を被った整数だ!

オブジェクト
Ruby空間における操作対象(オペランド)はオブジェクトである
Rubyオペレータはオブジェクトしか取り扱わない
オブジェクトはユーザによって初めてRuby空間に生み出されるが
それはクラスという設計図に従って常に構築される

ユーザは新しいクラスを設計して
それに基づいてオブジェクトを生成することもできるけれども
数字(整数)、文字列、シンボルなどのオペランドは
既にRuby設計者によって設計されたクラスFixnum, String, Symbolに属しているので
簡単にRuby空間に生み出すことができる

'Charlie'
183
:name

文字列
Ruby空間に生み出されたすべてのオブジェクトは
それぞれが固有のID(object_id)を持っていて
RubyオペレータはこのIDで個々のオブジェクトを管理する

一方ユーザはこのIDにアクセスすることはできるけれども
このIDでオブジェクトを管理することはできない
代わりにユーザは
変数(あるいは定数)という名札をオブジェクトに付けてこれを管理する

my_name = 'Charlie'

これが文字列のオブジェクトに名札を付ける方法だ
以降ユーザはmy_nameを呼ぶことによって
Charlieオブジェクトにアクセスできるようになる

me = my_name

このようにして
複数の名札を付けることもできる

世に同名の人が複数存在するように
同名の文字列オブジェクトも複数存在しうる

his_name = 'Charlie'

これをRuby空間に新たに生成したとき
my_nameとhis_nameは同名のオブジェクトを指しているけれども
それらは異なるIDを備えた異なるオブジェクトである

my_name.object_id  # => 8848520
his_name.object_id  # => 8827340

だから僕が逆さの国'napaJ'に引っ越して
名前が変わっても彼の名前はそのままだ

my_name.reverse! # => "eilrahC"
me                        # => "eilrahC"
his_name              # => "Charlie"

変数はユーザが文字列オブジェクトを管理するための唯一の方法だ
だから対象の文字列オブジェクトが名札である変数を失うと
ユーザはそれを見失いもう管理できなくなる

his_name = 'Fox'

このようにCharlieに割り当てた変数his_nameをFoxに割り当て直すと
元のCharlieオブジェクトからはhis_nameの名札が外れる
結果ユーザはCharlieオブジェクトに対するアクセス手段を失う
Charlieオブジェクトのその後を知っているのはRubyオペレータのみとなり
そのようなオブジェクトは彼が後に破棄する

数字
整数のオブジェクトに名札を付ける方法も
文字列の場合と変わらない

my_number = 183
his_number = 183

だけど文字列の場合と異なって
これらのオブジェクトのIDは同じになる(Fixnumのみ)

my_number.object_id  # => 367
his_number.object_id  # => 367

つまりmy_numberもhis_numberも
一つの183という整数オブジェクトを指している
これはつまり一つのRuby空間には
整数183というオブジェクトは一つしか存在しないということを意味している

数字は文字列のような個性を持たず
それ自体が変化することは期待されない
だからIDが同じでも問題は生じないということなんだろう

そうすると本来整数には名札を付ける必要すらない
整数に対するオブジェクトは一意であり
ユーザは文字列の場合とは異なって
名札がなくても希望するオブジェクトにアクセスできるからだ
つまりユーザにとって
整数自体がそのオブジェクトの名札の役割を担う

Rubyでは数字にも名札を付けることができるけれども
これは対象オブジェクトの管理のためではなく
もっぱら代数演算の結果を格納する容器としての役割を担っている

a = 10
b = a * 3

シンボル
シンボルは文字列と一対一で対応する記号である
文字列'Charlie'に対応するシンボルは:Charlieとなる
文字列のところで説明したように

my_name = 'Charlie'
his_name = 'Charlie'

とした場合
2つの異なるオブジェクトがRuby空間に生成される

my_name.object_id  # => 8848520
his_name.object_id  # => 8827340

これらのシンボルは以下により得られる

my_name.intern # => :Charlie
his_name.intern # => :Charlie

当然に異なるオブジェクトのシンボルは
異なるオブジェクトであることが期待される
しかしそうはならない

my_name.intern.object_id # => 314378
his_name.intern.object_id # => 314378

つまり同一記号のシンボルは同じオブジェクトである
これはつまり一つのRuby空間には無数の"Charlie"が存在しうるけれども
これに対応する:Charlieというシンボルオブジェクトは
ただ一つしか存在しないということを意味している

そうこれはまるで整数だ

整数と同様にシンボルには名札を付ける必要はない
シンボル記号に対するオブジェクトは一意であり
ユーザは名札がなくても希望するオブジェクトにアクセスできる
つまりシンボル記号自体がそのオブジェクトの名札の役割を担う

ここまで来ればシンボルの正体ははっきりする
文字列のような顔をして
数字のようにそれ自体が名札として機能する

そうシンボルとは…

文字列の皮を被った整数だったんだ!

シンボルの出番
Rubyには複数の関連するオブジェクトを
ユーザがまとめて管理できるようにするオブジェクトがある
配列とハッシュである

our_name = [ 'Charlie', 'Fox', 'Henry' ]

これでRuby空間に3つの文字列オブジェクトを管理する1つの配列オブジェクトが生成され
それにour_nameの名札が付けられる
配列で管理されるオブジェクトへのアクセスは
その位置を表す数字で行なえる

our_name[1] # => "Fox"

でも数字には個性がないので
1と"Fox"との間にはその位置以上の関連性はない
できればもっと関連性を持たせて意味付けをしたい
そのような場合シンボルが使える

our_name = { :my_name => 'Charlie', :his_name => :my_nephew => 'Henry' }

これでRuby空間に3つの文字列オブジェクトを管理する1つのハッシュオブジェクトが生成され
それにour_nameの名札がつけられる
ハッシュで管理されるオブジェクトへのアクセスは
そのキー値を使って行う

our_name[:his_name] # => "Fox"

なおRuby空間では:his_nameは"his_name"に対応しているが
それらは別のオブジェクトなので

our_name["his_name"] # => nil

となる
Rails空間では事情が異なるようだ

シンボルの特性をまとめてみよう
(1)文字列と一対一に対応した記号である
(2)同一記号のシンボルはRuby空間に唯一つ存在する(整数と同様、文字列と相違)
(3)シンボル記号自体が意味付けを表象できる(文字列と同様、整数と相違)

(2)(3)の特性を考えれば
そのオブジェクトの変更が予定されない場合
無駄なオブジェクトが生成されないシンボルは
速度の点で文字列オブジェクトよりも有利であり
またその記号の可読性を高めたい場合
整数オブジェクトよりも有利である
(1)の特性を活用したシンボルの使い方を僕は知らない