作者: HIDAKA Takahiro
日時: 2002/4/03(10:28)
 ひだかです。

ねこ丸 <QYE07500@...> wrote:

>  ねこ丸です。
> 
>   いや、確かに Ruby の方が読みやすいですね。その規則さえ分かれば。
>   Perl はリファレンスが本当に手放せないです。

 まぁ、引数が2個だかららく、という程度の話なのではありますが。

>   自分も Perl は使いますが、awk を使っていた頃のような気持ちよさがないん
> ですよ。Perl を学ぶ前も(たまに)使う今も変わらず思うのは、Perl は美しく
> ないなぁということです。それは分かりにくさでもあると思います。よほど書き
> 方に気をつけて use English して、それでもどうだか、って感じです。でも正
> 直、そんな書き方は Perl らしくなくて好きじゃないとも思うのですが(^^;(な
> んてこった)
>   awk しか使えなかった頃には心底 Perl に憧れましたが、今思うとどうかなー
> って感じ。Ruby も紅いくせに青く見えているだけなのかもしれませんが。

 これを見て思ったのは、ぼくってスクリプト苦手なのかもってことで(^_^;

 awk も Perl も sh も、読めると思うしちょっとくらい書けたけど、
あんまり実用的に使ったことがなかったです。さーがんばって
書くぞーとおもえば書けるけど、日常の道具というほどには
使いこなしてなかったですね・・

> >  ふたつめの例として多態の例をあげてみましょうか。
>   ごめんなさい、この辺はオブジェクトを実際に作ってみないと感じられないか
> も。関数と関数のインターフェイスをきっちり作りこむこととの違いがいまいち
> 見えてきません。

 インタフェースを作りこむことそのものなんですが、
インタフェースとしてオブジェクトを使うことでより楽になる
例のつもりでした。

 Ruby で言えば、

     def foo(f)
       f.collect { | line | line.split(/:/) }
     end

とやれば、行を読み込んでコロンで分割してリストを作って、
リストのリストとして返せるのですが、

   ex) 
      入力:
        root:*:0:0
        hidaka:*:1001:0
      出力:
        [['root','*','0','0'],['hidaka','*','1001','0']}

このfに、FileオブジェクトでもStringIOオブジェクトでもどちらでも
渡すことができて、同じように動作します。

 File * はC言語標準ライブラリのなかでも最もオブジェクト指向に
近いところだとも思うので例が微妙だったかもしれません。

> >  もうひとつの例として、今作っている(けど全然進まない)スクリプトで、
> > プレーンテキスト解析ライブラリみたいなものを考えています。
> > こっちはクラスを作る話。
>   これも???
>   ただ、Perl のライブラリなんかを使うときは、なんかこう、スマートじゃな
> い感じがすごくするので、例えばもっと‘うまく’書けるというだけでも十分メ
> リットを感じることができます。

 そうですね。頭の中を整理しながら書くのにはオブジェクト指向は
便利かな、という例だと思ってください(^_^;;

> >  あともうひとつのメリットとしては、全てがオブジェクトなので
> > 例えばArrayやHashになんでも入れられて、しかもHashのキーにも
> > できる(共通基底クラスObjectの利点)、というのがあるんだと思う
> > のですが、いい例が思いつきません(^^;
>   いや、これはすごいです。連想配列以上のぶっとびです。連想配列だけでもけ
> っこうな感動でしたが、それをオブジェクトで実現できるってのは…えーと、実
> 際に書いて動かしてみないとアレですが(^^;、かなり便利だと思います。C の構
> 造体に対する感動に近い感じ?  いや、これはすごい。(と思う。)

じゃあこんなのは面白いとおもってもらえるのかな。プログラムとしては
別に役には立たないですし、これだけならawkとかのほうが
短く書けるかもしれないですが・・・

#!/usr/local/bin/ruby

# Range/Integerとファイル名のハッシュをつくる
mapping = {
  0 => 'root',                  # Integer => String
  1...1000 => 'system',         # Range => String
  1000...65536 => 'user',       # Range => String
}

# それぞれファイルを開く
# Hash の値を File オブジェクトに置き換える
mapping.each do | key, name |
  mapping[key] = File.new(name + ".txt", "w")    # File.new は File.open と同じ
end

# ファイルに出力
ARGF.each do | line |
  list = line.split(/:/)
  mapping.each do | key, file |
    if key === list[2].to_i        # === 演算子はマッチングを行う
      file.print line
    end
  end
end

Ruby特有の要素としては、

* Range リテラル

   1...1000 というのは Range クラスのオブジェクトになります。
   1 以上 1000 未満という意味で、整数と === 演算子で比較判定する
   ことができます。

   ex) (1...1000) === 700   # => true
       (1...1000) === 0     # => false

   ちなみに、Integer クラスの === 演算子は単なる等値判定です。

* ARGF

   ARGF は入力ファイルを表すオブジェクトで、起動時にファイルを指定したら
   そこから読み込み、それがなければ標準入力から読み込みます。フィルタ系では
   よく使います。ARGF.each は行単位で読み込みます。

* to_i

   String#split の結果は文字列なので、比較のときに to_i メソッドで
   整数に変換します。

こんなところでしょうか。

-- 
ひだかたかひろ  cv8t-hdk@...-net.or.jp