\documentclass[a4paper]{jarticle}

\setlength{\textwidth}{160mm}
\setlength{\oddsidemargin}{0mm}
\setlength{\evensidemargin}{0mm}
\setlength{\marginparwidth}{0mm}
\setlength{\marginparsep}{0mm}

\setlength{\textheight}{240mm}
\setlength{\topmargin}{0mm}
\setlength{\headheight}{0mm}
\setlength{\headsep}{0mm}
\setlength{\topskip}{0mm}

\renewcommand\baselinestretch{0.85}

\makeatletter
\def\subsubsection*{\@startsection{subsubsection}{3}%
{\z@}{-2.25ex plus -1ex minus -.2ex}{1.5ex plus .2ex}%
{\edef\@svsec{$B"#(B\hskip 0.5em}\normalsize}}
\makeatother

\begin{document}

\section{$B:#F|$N$M$i$$(B}
Ruby $B$r;H$C$F!V$h$$!W%W%m%0%i%`$r=q$/$3$H!#(B

\subsection{$B$h$$%W%m%0%i%`$H$O$J$K$+!)(B}
\subsubsection*{$B$A$c$s$HF0$/(B}
$BL\E*$r2L$?$5$J$$%W%m%0%i%`$O0UL#$,$J$$!#$=$7$F$A$c$s$HF0$/(B
$B%W%m%0%i%`$H$O!"0U?^DL$j$KJQ$o$k$3$H$,$G$-$k%W%m%0%i%`$N$3$H$@!#(B

\subsubsection*{$B?M4V$N7gE@$K1F6A$5$l$K$/$$(B}
$B%W%m%0%i%_%s%0$K$*$1$k:GBg$N<eE@$O?M4V!#?M4V$N7gE@$rHr$1$k(B
$B%3!<%G%#%s%0$OHs>o$K=EMW$@!#$3$3$+$i$O0J2<$NJ}?K$,F3=P$G$-$k!#(B
    \begin{itemize}
    \item DRY $B86B'(B (Don't Repeat Yourself)
    \item $B>/$7$E$D9M$($k(B
    \item $BCj>]$h$j6q>]!"6qBN(B
    \end{itemize}

\section{$B%*%V%8%'%/%H;X8~%W%m%0%i%`$X(B}
$B$J$K$b0U<1$;$:$K=q$$$F$b$h$$%W%m%0%i%`$O=q$1$J$$!#(B
$B$$$m$$$m$J%*%V%8%'%/%H;X8~5!G=$,$I$N$h$&$K!V$h$$!W%W%m%0%i%`$r(B
$B;Y1g$7$F$/$l$k$N$+8+$F$$$3$&!#(B

\subsection{$B6q>]2=$9$k(B}
$B%*%V%8%'%/%H$G9=@.$5$l$?%W%m%0%i%`$O3($KIA$1$k!#(B
$B$3$l$K$O8=<B46$r@8$_$@$79M$($d$9$/$9$k$H$$$&D9=j$,$"$k!#(B

\subsection{$B0l2s$@$1=q$1(B}
$B%/%i%9$H%b%8%e!<%k$,$3$N5!G=$r2L$?$9$H$$$&$N$O$o$+$j$d$9$$!#(B\\

$B%/%i%9$K$h$k6&M-%Q%?!<%s(B
    \begin{itemize}
    \item $B6&DL$N%3!<%I$r;}$D%*%V%8%'%/%H$r$?$/$5$s:n$k$3$H$,$G$-$k(B
    \item $B%U%#%k%?7?$N%3!<%I6&M-(B
    \item $B%$%s%?!<%U%'%$%9$O2<0L%/%i%9$[$IA}2C798~(B
    \end{itemize}

$B%b%8%e!<%k$K$h$k6&M-%Q%?!<%s(B
    \begin{itemize}
    \item Template Method $B%Q%?!<%s$G%$%s%?!<%U%'%$%9$rDI2C$9$k(B ($BNc!'(BEnumerable)
    \item $B4X?tIw5!G=$N<BAu(B ($BNc!'(BMath)
    \end{itemize}

\subsubsection*{$B$*$^$1!'(B module\_eval}
\texttt{module\_eval} $B$r;H$&$H%F%-%9%H%l%Y%k$G%3!<%I$r6&DL2=$9$k(B
$B$3$H$,$G$-$k!#(B
\begin{quote}
\begin{verbatim}
class C
  def define_print_method( msg )
    module_eval <<"End", __FILE__, __LINE__ + 1
      def #{msg}
        print "#{msg}"
      end
    End
  end

  define_print_method 'hello'
  define_print_method 'goodby'
end
\end{verbatim}
\end{quote}

\subsection{$B>/$7$E$D9M$($k(B}
$B$R$H$D$N%*%V%8%'%/%H$r9M$($F%3!<%G%#%s%0$9$k$3$H$,$G$-$k!#(B
$B$^$?%+%W%;%k2=$K$h$C$F%$%s%?!<%U%'%$%9$H<BAu$,J,N%$5$l$F$$$k$N$G(B
$B%$%s%?!<%U%'%$%9$N:vDj$K@lG0$9$l$P$h$/$J$k!#(B\\

$BEAE}$H3J<0$N%9%?%C%/%/%i%9(B
\begin{quote}
\begin{verbatim}
class Stack
  def initialize
    @data = []
  end

  def push( obj )
    @data.concat [obj]
    self
  end

  def pop
    @data.delete_at(-1)
  end
end
\end{verbatim}
\end{quote}

$BJL$N<BAu(B
\begin{quote}
\begin{verbatim}
class Stack
  Link = Struct.new(:prev, :item)

  def initialize
    @last = nil
  end

  def push( i )
    @last = Link.new(@last, i)
  end

  def pop
    @last or return nil
    ret = @last.item
    @last = @last.prev
    ret
  end
end
\end{verbatim}
\end{quote}

$B$G$b%/%i%$%"%s%H$N%3!<%I$O$I$A$i$bF1$8(B
\begin{quote}
\begin{verbatim}
s = Stack.new
s.push 1
s.push 2
p s.pop   # 2
p s.pop   # 1
p s.pop   # nil
\end{verbatim}
\end{quote}

$B$?$@$7%+%W%;%k2=$O$"$/$^$G!V$&$C$+$jKI;_!W5!G=$G$"$j!"0U?^E*$K$J$i$P(B
$BGK$k$3$H$b5v$5$l$k!#$^$?<BMQ$K$b$J$j$&$k!#(B\\

$B%/%i%9$r$^$?$$$@!VFbIt!W<BAu(B
\begin{quote}
\begin{verbatim}
class A
  def some( b )
    b.__send__ :any
  end
end

class B
  private
  def any
    ....
  end
end
\end{verbatim}
\end{quote}

$BB>$N%*%V%8%'%/%H$N%$%s%9%?%s%9JQ?t$r<h$k(B
\begin{quote}
\begin{verbatim}
val = obj.instance_eval { @ivar }
\end{verbatim}
\end{quote}


\section{$B%W%m%0%i%`$r%*%V%8%'%/%H$KJ,3d$9$k(B}
$B%*%V%8%'%/%H;X8~$O?7$?$JLdBj$b@8$_$@$9!#%*%V%8%'%/%H$KJ,3d$9$l$P(B
$B$$$$$H$O$$$&$b$N$N!"$I$&$$$&J}?K$K=>$C$FJ,3d$9$l$P$h$$$N$@$m$&$+!#(B

$B4pK\E*$K!"%W%m%0%i%`$O%G!<%?$H%3!<%I$N$I$A$i$+$KCmL\$7$F%*%V%8%'%/%H$K(B
$BJ,3d$9$k$3$H$,$G$-$k!#A0<T$O9M$($d$9$$$7$h$/8@5Z$5$l$k$,(B
$B8e<T$OH/A[$7$K$/$$!#$7$+$7%*%V%8%'%/%H;X8~%W%m%0%i%`$N4N$O(B
$B<B$O8e<T$K$"$k!#(B

$B$^$?!V%G%6%$%s%Q%?!<%s!W$O!V$h$$!W%*%V%8%'%/%HJ,3d$N%Q%?!<%s%+%?%m%0(B
$B$H$7$FCN$i$l$F$$$k!#$3$NCf$K$OEvA3%G!<%?%3!<%IN>LL$+$i8+$?(B
$B%*%V%8%'%/%H$N;H$$J}$,4^$^$l$F$$$k!#(B

\subsubsection*{$B%G!<%?Cf?4$GJ,2r$9$k(B}
$B%G%6%$%s%Q%?!<%s$G8@$($P(B Composite $B%Q%?!<%s$d(B Mediator $B$,Hf3SE*(B
$B$3$A$i4s$j$@$,!"$`$7$m$3$N%?%$%W$N%*%V%8%'%/%H$O%Q%?!<%s$K$h$C$F(B
$B7k$S$D$1$i$l$k$Y$-KvC<%*%V%8%'%/%H$d%3%s%F%J7O%*%V%8%'%/%H$N(B
$B$[$&$KB?$$!#$?$H$($PA0%;%/%7%g%s$G5s$2$?%9%?%C%/$J$I!#(B

\subsubsection*{$B%3!<%ICf?4$GJ,2r$9$k(B}
Strategy $B%Q%?!<%s(B + Null $B%Q%?!<%s$NNc(B
\begin{quote}
\begin{verbatim}
def print_object( f )
  f.puts 'This is printed from print_object.'
  f.puts 'Is this printed correctly?'
end

class Tee < File
  def puts( str )
    $stdout.puts str
    super str
  end
end

class NullFile
  def puts( str )
  end
end

print_object File.open('output', 'w')  # $BIaDL$K%U%!%$%k$X(B
print_object Tee.open('output2', 'w')  # $B%U%!%$%k$H(B stdout
print_object NullFile.new              # $B$J$K$b$7$J$$(B
\end{verbatim}
\end{quote}


\section{$B%Q%i%a%?%i%$%:(B}
$B%G%6%$%s%Q%?!<%s$N!V$h$5!W$O!"<B$O$3$l$^$GOC$7$F$-$?$3$H$K(B
$B4T85$G$-$k!#$3$N@a$G$O!V%Q%i%a%?%i%$%:!W$r%F!<%^$K!"%G%6%$%s(B
$B%Q%?!<%s$X$H$D$J$,$kF;$rC5$m$&!#(B

\subsection{$BBh0lCJ3,!'(B $B%G!<%?!&%3!<%IJQ49(B}
$B$^$:!"%3!<%I$,%G!<%?$KJQ49$5$l$&$k$3$H$r8+$k!#$=$7$F%G!<%?$KJQ49$7$?(B
$BItJ,$O8r492DG=!&%+%9%?%^%$%:2DG=$H$J$k$H$$$&%]%$%s%H$r3NG'$7$h$&!#(B\\

$B%3!<%I$r(B \texttt{Array} $B$KJQ49(B
\begin{quote}
\begin{verbatim}
dosomething arg1
dosomething arg2
dosomething arg3
       $B"-(B
[arg1, arg2, arg3].each {|a| dosomething a }
\end{verbatim}
\end{quote}

$BFC$KJ8;zNs$NG[Ns$O$h$/;H$&(B
\begin{quote}
\begin{verbatim}
dosomething 'this'
dosomething 'is'
dosomething 'a_pen'
       $B"-(B
%w( this is a_pen ).each {|s| dosomething s }
\end{verbatim}
\end{quote}

\texttt{\_\_send\_\_} $B$G%G!<%?$r%3!<%I$KJQ49$9$k(B
\begin{quote}
\begin{verbatim}
case str
when 'some' then ....
when 'any'  then ....
end
       $B"-(B
def xxxx
     :
  __send__ 'do_' + str
     :
end
def do_some() .... end
def do_any() .... end
\end{verbatim}
\end{quote}

$B0lBP0lBP1~$H%O%C%7%e(B
\begin{quote}
\begin{verbatim}
case str
when 'some', 'alias_some'
  # do something
when 'any', 'alias_any'
  # do anything
end
       $B"-(B
TABLE = {
  'some'       => 'some',
  'alias_some' => 'some',
  'any'        => 'any',
  'alias_any'  => 'any'
}
def xxxx
     :
  __send__ 'do_' + TABLE[str]
     :
end
def do_some() .... end
def do_any() .... end
\end{verbatim}
\end{quote}

\subsection{$BBhFsCJ3,!'(B $B%$%F%l!<%?(B}
$B%$%F%l!<%?$O%3!<%I$r%3!<%I$N$^$^%Q%i%a%?%i%$%:2DG=$K$7$F$/$l$k!#(B
\begin{quote}
\begin{verbatim}
def method_a
  i = 0
  while i < @array.size do
    puts @array[i]
    i += 1
  end
end

def method_b
  ret = {}
  i = 0
  while i < @array.size do
    ret[ @array[i] ] = true
    i += 1
  end
  ret
end

       $B"-(B

def each
  i = 0
  while i < @array.size do
    yield @array[i]
    i += 1
  end
end  

def parametarized_a
  each do |i|
    print i
  end
end

def parametarized_b
  ret = {}
  each do |i|
    ret[i] = true
  end
  ret
end
\end{verbatim}
\end{quote}

$B!!(B\\
\texttt{Proc} $B$H$NHf3S(B
\begin{itemize}
\item \texttt{Proc} $B$O%G!<%?$J$N$G;}$A1?$Y$k(B
\item $B%a%=%C%I$H@Z$jN%$7$F8F$Y$k(B
\item $B%$%F%l!<%?$N$[$&$,5-=R$,C;$$(B
\end{itemize}

$B!!(B\\
\texttt{Method} $B$H$NHf3S(B
\begin{itemize}
\item \texttt{Method} $B$O%G!<%?$J$N$G;}$A1?$Y$k(B
\item \texttt{Method} $B$O$"$i$+$8$a%a%=%C%I$rDj5A$7$F$*$+$J$$$H;H$($J$$(B
\end{itemize}

$B!!(B\\
$B$^$?%$%F%l!<%?$K$O0J2<$N$h$&$JE57?E*$J;HMQ%Q%?!<%s$,B8:_$9$k!#(B

\subsubsection*{$B%"%/%;%97?(B}
\texttt{Array\#each}$B$KBeI=$5$l$k!"$b$C$H$b%$%F%l!<%?$i$7$$%$%F%l!<%?!#(B
$B%$%F%l!<%?$+$i%V%m%C%/$X0lJ}E*$K%*%V%8%'%/%H$,N.$l$k!#(B
\begin{quote}
\begin{verbatim}
def myeach
  i = 0
  while i < @array.size do               myeach do |item|
    yield @array[i]                        p item
    i += 1                               end
  end
end
\end{verbatim}
\end{quote}

$B$^$?%5%V%Q%?!<%s$H$7$F!V;E;v$NJ,3d!W$N$?$a$K;H$&$3$H$b$G$-$k!#(B

\subsubsection*{$B%U%#%k%?7?(B}
\texttt{Array\#collect}$B!"(B\texttt{delete\_if}$B$J$I!#(B\texttt{Enumerable}$B$N(B
$B%a%=%C%I$O$@$$$?$$$3$N%?%$%W$@$H;W$C$F$$$$!#(B
$B%*%V%8%'%/%H$O%a%=%C%I$H%V%m%C%/$N4V$r=[4D$7!"%V%m%C%/$,(B
$B%U%#%k%?$G$"$k$+$N$h$&$KF/$/!#(BStrategy $B7?!"(BTemplate Method $B7?$H$b(B
$B8@$($k!#(B
\begin{quote}
\begin{verbatim}
def mycollect
  ret = []
  each do |i|                            p mycollect {|i|
    ret.push yield(i)                        i * 2
  end                                    }
end
\end{verbatim}
\end{quote}

\subsubsection*{$BHO0O7?(B}
\texttt{File.open}$B$J$I!#0l2s$7$+7+$jJV$5$J$$%$%F%l!<%?!#(B
\begin{quote}
\begin{verbatim}
def myopen( fname )
  begin
    f = File.open(fname)                 myopen( fname ) {|f|
    yield f                                  print f.read
  ensure                                 }
    f.close if f
  end
end 
\end{verbatim}
\end{quote}

$B$*$^$1!'%a%=%C%I$KJ,3d$9$l$P%V%m%C%/JQ?t$G%O%^$i$J$$(B
\begin{quote}
\begin{verbatim}
def read_all( fname )
  File.open( fname ) {|f|
    return f.read
  }
end
\end{verbatim}
\end{quote}

\subsubsection*{$B@)8f9=B$7?(B}
$BHO0O7?$H;w$F$$$k$N$@$,!"$3$A$i$O7+$jJV$7$,0l2s$H$O8B$i$J$$!#(B
\texttt{catch} $B$d(B \texttt{Hash\#fetch}$B$,$3$N%?%$%W!#(B
\begin{quote}
\begin{verbatim}
def myfetch( key )
  if @hash.key? key then
    @hash[key]
  else                                   val = myfetch('somekey') {
    yield                                    'default value'
  end                                    }
end
\end{verbatim}
\end{quote}

\subsubsection*{$BEPO?7?(B}
\texttt{signal}$B!"(B\texttt{Gtk::Object\#signal\_connect}$B$J$I!#(B
$B$3$N%?%$%W$O;v<B>e(B \texttt{Proc} $B$H6hJL$G$-$J$$$N$G!"(B
$BC1$J$k5-=R>e$N%7%g!<%H%+%C%H$H$7$F;H$&$N$,$$$$$@$m$&!#(B

\subsubsection*{$B%3%s%F%-%9%H7?(B}
\texttt{module\_eval} $B$H(B \texttt{instance\_eval}$B!#(B
$B$?$/$5$s;H$($P;H$&$[$I%W%m%0%i%`$r$o$+$j$K$/$/$G$-$k!#(B
\texttt{module\_eval} $B$O%3!<%I$N%F%-%9%H%l%Y%k$G$N6&M-!"(B
\texttt{instance\_eval} $B$O%$%s%9%?%s%9JQ?t%"%/%;%9$K$N$_(B
$B8BDj$7$F;H$&$N$,$h$$!#(B


\subsection{$BBh;0CJ3,!'(B $B%*%V%8%'%/%H(B}
$B$$$o$f$k%]%j%b!<%U%#%:%`$rMxMQ$7$?%Q%i%a%?%i%$%:!#%*%V%8%'%/%H$O(B
$B%G!<%?$H%3!<%I$N%Q%i%a%?%i%$%:$ND9=j$r7s$MHw$($k!#(B
$B$^$?7Q>5(B / $B%$%s%/%k!<%I$r;H$C$?%3!<%I6&M-$O%a%=%C%IC10L$G$7$+(B
$B$J$+$C$?$,!"$3$N%?%$%W$N%Q%i%a%?%i%$%:$OB>%/%i%9$N%a%=%C%I$N(B
$BFbIt$K$bN)$AF~$C$F6&M-2DG=$G$"$k!#(B\\

$B%G!<%?$K$h$k%Q%i%a%?%i%$%:$HHf$Y$k$H(B
\begin{itemize}
\item $BD>@\E*$K%3!<%I$rH4$-=P$9$3$H$,$G$-$k(B
\item $B30It$+$i3HD%2DG=(B
\end{itemize}

$B%3!<%I$K$h$k%Q%i%a%?%i%$%:(B($B%$%F%l!<%?(B)$B$HHf$Y$k$H(B
\begin{itemize}
\item $B$o$+$j$d$9$$(B
\item $BJ#?t$N%(%s%H%j%]%$%s%H$r;}$F$k(B
\end{itemize}

$B7gE@(B
\begin{itemize}
\item $B%$%F%l!<%?$[$I5$7Z$G$O$J$$(B
\item $B%Q%i%a%?%i%$%:$9$k$[$I%$%K%7%c%i%$%:$OBgJQ$K$J$k(B
\end{itemize}


\section{$B<BCO8!>Z(B}

$B%a!<%k%\%C%/%9$NMWLs%j%9%H$rI=<($9$k;EAH$_$rMM!9$JJ}K!$G<BAu$9$k!#(B\\

$B%P!<%8%g%s(B 0$B!'(B $B$9$Y$F7h$aBG$A%3!<%I(B
\begin{quote}
\begin{verbatim}
  1:  def list_inbox
  2:    $inbox.each do |mail|
  3:      $stdout.printf "%11s %-20s %s\n",
  4:                     mail.date.strftime('%m/%d %H:%M'),
  5:                     mail.from.to_s[0,20],
  6:                     mail.subject
  7:    end
  8:  end
\end{verbatim}
\end{quote}

$B%P!<%8%g%s(B 1$B!'(B $B%G!<%?$K$h$k%Q%i%a%?%i%$%:(B (1)
\begin{quote}
\begin{verbatim}
  1:  def list( mailbox, f )
  2:    mailbox.each do |mail|
  3:      f.printf "%11s %-20s %s\n",
  4:               mail.date.strftime('%m/%d %H:%M'),
  5:               mail.from.to_s[0,20],
  6:               mail.subject
  7:    end
  8:  end
  9:  
 10:  # client 1
 11:  list $inbox, $stdout
 12:  
 13:  # client 2
 14:  open( "| less -S", 'w' ) {|f|
 15:    list $inbox, f
 16:  }
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 1.2$B!'(B $B%G!<%?$K$h$k%Q%i%a%?%i%$%:(B (2)
\begin{quote}
\begin{verbatim}
  1:  def list( mailbox, format, f )
  2:    mailbox.each do |mail|
  3:      f.puts interpret(format, mail)
  4:    end
  5:  end
  6:  
  7:  def interpret( format, mail )
  8:    args = []
  9:    fmt = format.gsub( /(%-?\d*)(\w)/ ) {
 10:      ret = $1 + 's'
 11:      key = $2
 12:      args.push(
 13:        case key
 14:        when 'd' then mail.date.strftime('%m/%d %H:%M')
 15:        when 's' then mail.subject
 16:        when 'f' then mail.from.to_s
 17:        else
 18:          raise ArgumentError, "unknown key '#{key}'"
 19:        end
 20:      )
 21:      ret
 22:    }
 23:    sprintf fmt, *args
 24:  end
 25:  
 26:  # user input
 27:  $format = '%11d %-20f %s'
 28:  
 29:  # client 1
 30:  list $inbox, $format, $stdout
 31:  
 32:  # client 2
 33:  open( "| less -S", 'w' ) {|f|
 34:    list $inbox, $format, f
 35:  }
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 1.3$B!'(B $B%G!<%?$K$h$k%Q%i%a%?%i%$%:(B (3)
\begin{quote}
\begin{verbatim}
  1:  def list( mailbox, format, f )
  2:    mailbox.each do |mail|
  3:      f.puts interpret(format, mail)
  4:    end
  5:  end
  6:  
  7:  TABLE = {
  8:    'd' => lambda {|m| m.date.strftime('%m/%d %H:%M') },
  9:    's' => lambda {|m| m.subject },
 10:    'f' => lambda {|m| m.from.to_s }
 11:  }
 12:  
 13:  def register_action( key, &block )
 14:    TABLE[key] = block
 15:  end
 16:  
 17:  def interpret( format, mail )
 18:    args = []
 19:    fmt = format.gsub( /(%-?\d*)(\w)/ ) {
 20:      ret = $1 + 's'
 21:      key = $2
 22:      args.push TABLE.fetch(key)
 23:      ret
 24:    }
 25:    sprintf fmt, *args
 26:  end
 27:  
 28:  # user input
 29:  $format = '%14D %-20f %s'
 30:  regiter_action( 'D' ) {|m|
 31:    m.date.strftime('%m/%d %H:%M:%S')
 32:  }
 33:  
 34:  # client 1
 35:  list $inbox, $format, $stdout
 36:  
 37:  # client 2
 38:  open( "| less -S", 'w' ) {|f|
 39:    list $inbox, $format, f
 40:  }
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 2$B!'(B $B%3!<%I$K$h$k%Q%i%a%?%i%$%:(B (1)
\begin{quote}
\begin{verbatim}
  1:  def each_list( mailbox, f )
  2:    mailbox.each do |mail|
  3:      yield mail.date.strftime('%m/%d %H:%M'),
  4:            mail.from.to_s,
  5:            mail.subject
  6:    end
  7:  end
  8:  
  9:  # client 1
 10:  open( '| less -S', 'w' ) {|file|
 11:    each_list( $inbox ) do |d,f,s|
 12:      file.printf "%11s %-20s %s\n", d, f[0,20], s
 13:    end
 14:  }
 15:  
 16:  # client 2
 17:  $gui_column_list.freeze
 18:  each_list( $inbox ) do |args|
 19:    $gui_column_list.append_row *args
 20:  end
 21:  $gui_column_list.unfreeze
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 2.2$B!'(B $B%3!<%I$K$h$k%Q%i%a%?%i%$%:(B (2)
\begin{quote}
\begin{verbatim}
  1:  DEFAULT_PROC = lambda {|m| [
  2:      m.date.strftime('%m/%d %H:%M'),
  3:      m.from.to_s,
  4:      m.subject
  5:  ] }
  6:  
  7:  DEFAULT_FORMAT = '%11s %-20s %s'
  8:  
  9:  def c_list( mailbox, fmt )
 10:    open( '| less -S', 'w' ) {|file|
 11:      mailbox.each do |mail|
 12:        file.puts sprintf(fmt, *yield(mail))
 13:      end
 14:    }
 15:  end
 16:  
 17:  def g_list( mailbox, list )
 18:    begin
 19:      list.freeze
 20:      mailbox.each do |mail|
 21:        list.append_row *yield(mail)
 22:      end
 23:    ensure
 24:      list.unfreeze
 25:    end
 26:  end
 27:  
 28:  # client 1
 29:  c_list $inbox, DEFAULT_FORMAT, & DEFAULT_PROC
 30:  
 31:  # client 2
 32:  c_list( $inbox, '%13s %-20s %s' ) {|m| [
 33:      m.date.strftime('%m/%d %H:%M:%S'),
 34:      m.from.to_s,
 35:      m.subject
 36:  ] }
 37:  
 38:  # client 3
 39:  g_list $inbox, $gui_column_list
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 3$B!'(B $B%*%V%8%'%/%H$K$h$k%Q%i%a%?%i%$%:(B (1)
\begin{quote}
\begin{verbatim}
  1:  class Mailbox
  2:    def list
  3:      listing {
  4:        each_mail do |mail|
  5:          append mail.date.strftime('%m/%d %H:%M'),
  6:                 mail.from.to_s,
  7:                 mail.subject
  8:        end
  9:      }
 10:    end
 11:  end
 12:  
 13:  class CUIMailbox < Mailbox
 14:    def initialize( fmt )
 15:      @format = fmt.chomp + "\n"
 16:      @f = nil
 17:    end
 18:  
 19:    def listing
 20:      open( '| less -S', 'w' ) {|f|
 21:        @f = f
 22:        yield
 23:      }
 24:    end
 25:  
 26:    def append( d, f, s )
 27:      @f.printf @format, d, f[0,20], s
 28:    end
 29:  end
 30:  
 31:  class GUIMailbox < Mailbox
 32:    def initialize 
 33:      @list = SomeToolkit::ColumnList.new(3)
 34:    end
 35:  
 36:    def listing
 37:      begin
 38:        @list.freeze
 39:        yield
 40:      ensure
 41:        @list.unfreeze
 42:      end
 43:    end
 44:  
 45:    def append( d, f, s )
 46:      @list.append_row d, f, s
 47:    end
 48:  end
 49:  
 50:  
 51:  # user code
 52:  $cui = true # or false
 53:  
 54:  # client
 55:  mailbox = $cui ? CUIMailbox.new( '%11s %-20s %s' )
 56:                 : GUIMailbox.new
 57:  mailbox.list
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 3.2$B!'(B $B%*%V%8%'%/%H$K$h$k%Q%i%a%?%i%$%:(B (2)
\begin{quote}
\begin{verbatim}
  1:  class Mailbox
  2:    def initialize( g )
  3:      @getters = g
  4:    end
  5:  
  6:    def list
  7:      listing {
  8:        each_mail do |mail|
  9:          append @getters.collect {|g| g.get_item mail }
 10:        end
 11:      }
 12:    end
 13:  end
 14:  
 15:  class CUIMailbox < Mailbox
 16:    def initialize( g, fmt )
 17:      super g
 18:      @format = fmt.chomp + "\n"
 19:      @f = nil
 20:    end
 21:  
 22:    def listing
 23:      open( '| less -S', 'w' ) {|f|
 24:        @f = f
 25:        yield
 26:      }
 27:    end
 28:  
 29:    def append( items )
 30:      @f.printf @format, *items
 31:    end
 32:  end
 33:  
 34:  class GUIMailbox < Mailbox
 35:    def initialize( g )
 36:      super g
 37:      @list = SomeToolkit::ColumnList.new(g.size)
 38:    end
 39:  
 40:    def listing
 41:      begin
 42:        @list.freeze
 43:        yield
 44:      ensure
 45:        @list.unfreeze
 46:      end
 47:    end
 48:  
 49:    def append( items )
 50:      @list.append_row *items
 51:    end
 52:  end
 53:  
 54:  class Getter
 55:    def initialize( &block )
 56:      @block = block
 57:    end
 58:  
 59:    def get_item( m )
 60:      @block.call m
 61:    end
 62:  
 63:    Defaults = {
 64:      'date'    = new {|m| m.date.strftime('%m/%d %H:%M') },
 65:      'from'    = new {|m| m.from.to_s },
 66:      'subject' = new {|m| m.subject }
 67:    }
 68:  end
 69:  
 70:  
 71:  # user code
 72:  $cui = true # or false
 73:  $cui_format = '%11s %-20s %s'
 74:  $getter = %w( date from subject )
 75:  
 76:  # client
 77:  getter = $getter.collect {|n| Getter::Defaults.fetch(n) }
 78:  mailbox = $cui ? MailboxCUI.new( getter, $cui_format )
 79:                 : MailboxGUI.new( getter )
 80:  mailbox.list
\end{verbatim}
\end{quote}

\pagebreak
$B%P!<%8%g%s(B 3.3$B!'(B $B%*%V%8%'%/%H$K$h$k%Q%i%a%?%i%$%:(B (3)
\begin{quote}
\begin{verbatim}
  1:  class Mailbox
  2:    def initialize( g, interf )
  3:      @getters = g
  4:      @interface = interf
  5:    end
  6:  
  7:    def list
  8:      @interf.listing {
  9:        each_mail do |mail|
 10:          @interf.append @getters.collect {|g| g.get_item mail }
 11:        end
 12:      }
 13:    end
 14:  end
 15:  
 16:  class MailboxCUI
 17:    def initialize( fmt )
 18:      @format = fmt.chomp + "\n"
 19:      @f = nil
 20:    end
 21:  
 22:    def listing
 23:      open( '| less -S', 'w' ) {|f|
 24:        @f = f
 25:        yield
 26:      }
 27:    end
 28:  
 29:    def append( items )
 30:      @f.printf @format, *items
 31:    end
 32:  end
 33:  
 34:  class MailboxGUI
 35:    def initialize( size )
 36:      @list = SomeToolkit::ColumnList.new(size)
 37:    end
 38:  
 39:    def listing
 40:      begin
 41:        @list.freeze
 42:        yield
 43:      ensure
 44:        @list.unfreeze
 45:      end
 46:    end
 47:  
 48:    def append( items )
 49:      @list.append_row *items
 50:    end
 51:  end
 52:  
 53:  class Getter
 54:    def initialize( &block )
 55:      @block = block
 56:    end
 57:  
 58:    def get_item( m )
 59:      @block.call m
 60:    end
 61:  
 62:    Defaults = {
 63:      'date'    = new {|m| m.date.strftime('%m/%d %H:%M') },
 64:      'from'    = new {|m| m.from.to_s },
 65:      'subject' = new {|m| m.subject }
 66:    }
 67:  end
 68:  
 69:  
 70:  # user code
 71:  $cui = true # or false
 72:  $cui_format = '%11s %-20s %s'
 73:  $getter = %w( date from subject )
 74:  
 75:  # client
 76:  getter = $getter.collect {|n| Getter::Defaults.fetch(n) }
 77:  interf = $cui ? MailboxCUI.new( $cui_format )
 78:                : MailboxGUI.new( $getter.size )
 79:  mailbox = Mailbox.new( getter, interf )
 80:  mailbox.list
\end{verbatim}
\end{quote}


\pagebreak
\section*{$B;29MJ88%(B}
\paragraph{$B!X%*%V%8%'%/%H;X8~%9%/%j%W%H8@8l(B Ruby$B!Y(B}
$B$^$D$b$H$f$-$R$m!&@PDM7=<y6&Cx!"%"%9%-!<(B\\
$B%G%U%)%k%H$GGc$$!#$=$m$=$mFsHG$,=P$k$H$$$&1=$,!)(B

\paragraph{$B!X(BRuby $B%W%m%0%i%_%s%0F~Lg!Y(B}
$B86?.0lO:Cx!"%*!<%`<R(B\\
$B$3$l$b%G%U%)!#(B

\paragraph{$B!X%G%6%$%s%Q%?!<%s!Y(B}
Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides $B6&Cx!"%=%U%H%P%s%/(B\\
$B$*$9$9$a!"$H$$$&$h$j$OI,FI$N0l:}!#$b$&$9$G$KFI$s$@?M$bB?$$$H;W$&!#(B
$B;}$C$F$J$$?M$O5"$j$,$1$KGc$*$&!#7k>k$5$s$N!X(BJava $B$G3X$V!D!D!Y$J$I$G$b(B
$B$h$$$+$b$7$l$J$$$,FI$s$@$3$H$,$J$$$N$G6/$/$O4+$a$i$l$J$$!#<+J,$G(B
$BFI$s$G7h$a$h$&!#(B

\paragraph{$B!XC#?M%W%m%0%i%^!Y(B}
Andrew Hunt, David Thomas $B6&Cx!"%T%"%=%s%(%G%e%1!<%7%g%s(B\\
$BF3F~Cf$K$H$j$"$2$?!V(BDRY $B86B'!W$N$[$+<B@oE*$JDs8@$,B?!9$J$5$l$F$$$k!#(B
$BCx<T$N(B pragmatic programmers $B$,(B ruby-talk ML $B$K$$$k!D!D$H$$$&$N$O(B
$B$b$&>o<1$+!#%5%$%s$,M_$7$$?M$O(B 10 $B7n$N(B Ruby Conference ($B%U%m%j%@3+:E(B)
$B$K9T$3$&!#Hs>o$K$*$9$9$a$N0l:}!#(B

\paragraph{$B!X%*%V%8%'%/%H;X8~F~Lg!Y(B}
Bertrand Meyer $BCx!"%"%9%-!<(B\\
$B$I$3$,F~Lg$J$s$@!"$H$$$&%D%C%3%_$O$5$F$*$-!"@EE*$J%*%V%8%'%/%H(B
$B;X8~8@8l$N5!G=$K4X$7$F(B($B$?$H$($P(B genericity $B$K4X$9$k5DO@$J$I(B)
$BB?$/F@$k$b$N$,$"$k!#(BEiffel $B$NBeL>;l$H$b8@$($k(B Design by Contract $B$K(B
$B4X$7$F$bEvA3$J$,$i>\$7$$!#%"%9%-!<$N?M$KJ9$$$?$H$3$m$K$h$k$HFsHG$,(B
$BK]LuCf$i$7$$$N$@$,!"(B1000 $B%Z!<%80J>e$"$k$?$a$$$D$K$J$k$+(B
$B$o$+$i$J$$$=$&$@!#(B

\paragraph{$B!X7W;;5!%W%m%0%i%`$N9=B$$H2r<a!Y(B $BBhFsHG(B}
Gerald Jay Sussman, Harold Abelson, Julie Sussman $B6&Cx!"%T%"%=%s%(%G%e%1!<%7%g%s(B\\
MIT $B%W%m%0%i%`2J$N=i5i652J=q$i$7$$$,!"$=$NFq0WEY$O$H$F$b(B
$B=i5i$H$O;W$($J$$!#$*$9$9$a$G$O$J$$$,$?$a$K$J$C$?$N$G:\$;$F$*$/!#(B

\paragraph{Ruby $B%$%s%?%W%j%?%=!<%9%3!<%I(B}
Yukihiro Matsumoto\\
$B!V%=!<%9%3!<%I$,%I%-%e%a%s%H$@!#%P%0$b$9$Y$F5-=R$5$l$F$$$k!W(B\copyright matz \\
$B!V%=!<%9$r;H$(!"%k!<%/!*!WMZ$+1'Ch$NH`J}$+$iEA$o$C$?$i$7$$EA@b$h$j(B \\
$B!V%W%m%0%i%`$O0U?^DL$j$K$OF0$+$J$$!#=q$$$?DL$j$KF0$/!#!W%W%m%0%i%^$KEA$o$kEA>5(B


\vspace{2cm}
\noindent
\begin{flushright}
\obeylines
\copyright 2001 Minero Aoki
\texttt{aamine@loveruby.net}
\texttt{http://www.loveruby.net}
\end{flushright}

\end{document}

