From: Kusunoki Kaoru <kusunoki / mbox.kyoto-inet.or.jp>
Subject: [ruby-list:31560] Re: はじめまして AWK から Ruby
Date: Fri, 21 Sep 2001 11:47:11 +0900

るびきちです。

> > #!/usr/bin/env ruby
> > module AwkSplit
> >   def awk_split( arg = ' ' )
> >     while self.gets
> >       f = split( arg )
> >       yield f
> >     end
> >   end
> > end
*1

> > class IO
> >   include AwkSplit
> > end
*2

> > ARGF.extend AwkSplit
*3

> > def awk_split( arg = ' ' )
> >   ARGF.awk_split( arg ) {|args| yield args}
> > end
*4

> > if __FILE__ == $0  # awk-split.rbそのものを実行したときのみ↓のコードが実行されるイディオム。
> >   open( "/etc/passwd" ) do |inf|
> >     inf.awk_split( /:/ ) do |user, pass, uid, gid, group, home, shell|
> >       puts user
> >     end
> >   end
> > end
> 
> 上記プログラムが理解できません。
すみません、説明つけてませんでしたね。

何をしているかというと、
「IO#awk_split(IOのインスタンスメソッドawk_split)」(*2)と
「ARGFの特異メソッドawk_split」(*3)と
「function#awk_split(関数。厳密にはトップレベルのメソッド)」(*4)を定義してします。

冗長に書くと、

class IO
  def awk_split( arg = ' ' )
    while self.gets
      f = split( arg )
      yield f
    end
  end
end

def ARGF.awk_split( arg = ' ' )
  while self.gets
    f = split( arg )
    yield f
  end
end

def awk_split( arg = ' ' )
  while ARGF.gets
    f = split( arg )
    yield f
  end
end

となります。
しかし、同じようなコードが3つもあるのはよくないので、いったん module として定義し、
IOクラスにinclude(インスタンスメソッドを追加)、
ARGFオブジェクトにextend(特異メソッドを追加)しているのです。

よって、

> 1. module 内の awk_split と、 class 定義の下の
> awk_split はどういう関係になるのでしょうか?
IOクラスに AwkSplit が取り込まれてパワーアップしました。

> 2. なぜ、同じ(ような?)ものが2ついるののでしょうか?
IO#getsとfunction#getsがあるのと同じ理由です。

> 3. class の下の awk_split 内の メソッド awk_split
> は、自分自身なのでしょうか?
ARGFの特異メソッドawk_splitが呼ばれます。

> 4.  ARGF.extend AwkSplit ??
ARGFにmodule AwkSplitで定義されているメソッドを特異メソッドとして追加してます。

ARGFやイテレータについてはリファレンスマニュアルなどを参照してください。
include/extendはRubyの柔軟性を示すとてもおもしろいところです。

ただ、わからないうちはこのスクリプトをブラックボックスとして扱って構いません。
> >   open( "/etc/passwd" ) do |inf|
> >     inf.awk_split( /:/ ) do |user, pass, uid, gid, group, home, shell|
> >       puts user
> >     end
> >   end
要はこのように使えるということが大事な点です。
実装がわからなくても、一度定義されたらこんな簡単に使えます。

るびきち☆
http://voo.to/ruby/ ←Ruby大衆化計画(笑)