「7つの言語 7つの世界」 Ruby 2日目(Jugemより移植)

Posted by johtani on Saturday, September 10, 2011

目次

ということで、Ruby2日目の感想(2日目だけで2日間かかったのは内緒。。。) 今回もセルフスタディの私の回答が最後の方に記載されてます。見たくない人は気をつけてください。 ツッコミ大募集です。コメント欄にどしどしコメントください。そこは違うだろ?こっちのほうがいいのでは?という感じで。

感想:

◎関数の定義:ありゃ、利用するのはダメなんだ、これじゃ。–>単なるタイプミスでした。お恥ずかしい。。。


>> def tell_the_truth
>>   true
>> end
=> nil
>> tell_the_trueth()
NoMethodError: undefined method `tell_the_trueth' for main:Object
     from (irb):4

◎配列:そしてシンタックスシュガー

puts animalsで内容が出力されるのはうれしい。JavaだとHashCodeが出てくるから。出力メソッド書かないといけなくなる。 animals[-1]で最後の要素とかかなり便利。 animals[0..1]はRangeクラスを利用する形。Rangeはやはり便利。substringなどもできそう。 カラ配列の定義は必要。a = [] 1.9と1.8でinclude?の書き方が異なるので注意! 配列(Array)クラスは中はObjectが入る。 多次元配列もOK。popやpushでキューとしても利用可能。

◎ハッシュ:

Mapのようなもの。任意のキーが利用可能。:付きの文字列はシンボルと呼ばれる定数値を簡単に定義する方法。 object_idという属性?関数によりObjectのハッシュコードが取れるらしい。 ブレース=「{}」のカッコのこと。do~endでも代用可能

◎コードブロックとyeild

コードブロック=名前なし関数。習慣では複数行の場合、do/endで、1行は{}みたい。Javaと混同しそう。 コードブロックは引数も指定可能。 「yield」予約語?を利用してコードブロック自体をメソッド内部などで呼び出し可能。 ということで、コードブロックは引数にも指定できると。コードブロック=関数もObjectとして扱われてる感じか? 実行遅延、分岐、共通関数とか?Javaだとabstractメソッドを利用して処理するようなイメージか?ちょっと違うなぁ。 なれると、yieldはコードを読みやすくできそう。また、シンタックスハイライトしてくれるツールがあれば、更に便利。

◎ファイルの実行


ruby ファイル名

vi、Emacs、TextMateなどがあるよ。

◎クラスの定義

※数字で始まる変数は利用できない!Javaと一緒 Tree.rbとログを参考にすること。 &使うとブロックに名前が付けられる。yieldじゃなくてもいい? クラス名はキャメルケース。 変数とメソッド名は「_」アンダーバーつなぎ インスタンス変数の頭は@ クラス変数は@@ 定数は大文字 ※メソッド名、変数名には違和感が。なんでこんな規則?? 判定用関数とメソッドには「?」(if test?)をつける!!Javaでいう「is」か。

◎Mixin(多重継承?モジュールと呼ばれるものを利用)

多重継承のような類似の振る舞いを伝搬する仕組み。 Javaではインタフェースでやること。 Rubyではモジュールといい、関数と定数の集まり。 クラスに機能を盛り込む場合はincludeする ※複数includeして、includeしたものの中に同じメソッドとかあったらどーなる?  –>Overrideされた=includeがあとにあるもので上書きされる Abstractにできないものをモジュール化できるの楽。 javaだとstaticメソッドだらけのUtilクラスを別途起こすイメージだけど、内部で呼ばれるメソッド(コードブロック)が同じインタフェースじゃないと行けないから、インタフェースの記述もしないと行けない。 ただし、同一名のメソッドを持ってるとややこしそう。 ※モジュールからモジュールは呼べる?

◎モジュール、Enumerable、セット

EnumerableとComparable(JavaのCollectionまわりかな。) 宇宙船演算子(<=>)Javaのequalsに似てる any?とかCollectionUtils??に似たのあったな。 ※今利用しているクラスが何をincludeしてるかってのは分かる仕組みあるのかな? ※そういえば、メソッドごとに戻り値があるが、全部newされてインスタンス化されてGCの対象になってるのか?irbだけ? injectはすんなり使うイメージが出にくそう。また、ソースをぱっと見て理解出来ない。なれだろうけど。 ※injectしながらinjectとかあるんだろうな。

(探してみよう:)

○コードブロックを使った場合と使わない場合の両方について、ファイルにアクセスするコードを書く。コードブロックの利点は?
※コードブロックあり。 ```

File.open(“tree.rb”, ‘r’) {|f| f.each {|line| puts “#{f.lineno} : #{line}”}}

※コードブロックなし

f = File.open(“tree.rb”, ‘r’) while line = f.gets puts “#{f.lineno} : #{line}” end

コードブロックの利点:
 見通しの良さ。行数が少なくてすむ。繰り返し処理が簡単に記述できる。
 ※うーん、まだきちんと理解できてないか?
</dd>
<dt>○ハッシュを配列に変換するにはどうすればよいか?また、逆に配列をハッシュに変換する方法は?</dt>
<dd>
※間違えた。。。

h = [:key1 => “hoge”, :key2 => “boke”, :key3 => “fuga”] h.each {|key, value| puts “#{key} is #{value}”} =>key1hogekey2bokekey3fuga is


ハッシュ-&gt;配列変換

h.to_a


配列-&gt;ハッシュ変換

a = [“value1”, “valu2”, “value3”] h = {} a.each {|i| h.store(a.index(i),i) }

※また間違い?なんでそうなる?

a.inject(h2) {|hoge, i| hoge[a.index(i).to_s] = i}

こっちならいいみたい。まだinjectがわかってない。

a.inject(h2) {|hoge, i| hoge[a.index(i).to_s] = i;puts “#{i}”; hoge}


</dd>
<dt>○ハッシュの各要素について繰り返すにはどうすればよいか?</dt>
<dd>

h.each {|key, value| puts “#{key} is #{value}”}

</dd>
<dt>○Rubyの配列はスタックとしても使える。スタック以外に配列で実現可能なよくあるデータ構造体を挙げよ。</dt>
<dd>キュー。
他にある?Treeとか?Treeはハッシュじゃないか?Set?順番が関係ないけど。</dd>
</dl>


### **(試してみよう:)**
<dl>
<dt>○最初に、eachだけを用いて、16個の数値と4個の数値の配列の中身を同時に出力せよ。次に、同じ事をEnumerableのeach_sliceを用いて実行せよ。</dt>
<dd>
<span style="color:#FF0000"><em>※これ日本語がわからないんだが、4個ずつ出せってことか??</em></span>ということで、「16個の数字の配列の中身を4個ずつ同時に出力せよ。」と解釈して実装してみた
※each利用版

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] s = [] a.each do |b| unless s.length < 4 puts s.inspect s.clear end s « b end


※each_slice

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] a.each_slice(4) {|b| puts b.inspect}

また、えらい違いだな。
</dd>
<dt>○Treeクラスは面白いクラスだったが、きれいなインタフェースを用いて新しいツリーを指定することは出来なかった。そこで、initializerにハッシュと配列が入れ子になった構造体を指定できるようにせよ。具体的には、次のようなツリーを指定できるようにしたい。{'grandpa' =&gt; { 'dad' =&gt; {'child 1' =&gt; [], 'child 2' =&gt; [] }, 'uncle' =&gt; {'child 3' =&gt; [], 'child 4' =< [] } } }</dt>
<dd><span style="color:#FF0000">※root(ここではgrandpaレベル)が複数あると破綻しないのか?</span>

class Tree attr_accessor :children, :node_name

def initialize(name, children=[]) @children = children @node_name = name end

def initialize(hash) hash.each do |key, value| @node_name = key @children = value.inject([]) do |array, (child_key, child_val)| puts “inject! #{key}” [Tree.new({child_key => child_val})] + array end end end

def visit_all(&block) visit &block children.each {|c| c.visit_all &block} end

def visit(&block) block.call self end end


残念ながらちょっとカンニングしてしまいました。。。
</dd>
<dt> ○ファイル内で、あるフレーズを含む全ての行を出力する簡単なgrepをかけ。簡単な正規表現でマッチングを行い、ファイルから行を読み出す必要がある(この処理はRubyでは驚くほど簡単にかける)。必要なら行番号も出力してみると良い。</dt>
<dd>※メソッドだけでいいな。<span style="color:#0000FF">ファイルクローズはこの記述の場合はコーディングブロックのendのタイミングでクローズされるのか?</span>

class RegGrep def grep(filename, regexp) File.open(filename, ‘r’) do |f| f.each do |line| puts “#{f.lineno} : #{line}” if line.match(regexp) end end end end

</dd>
</dl>

ということで、2日目終了。
恥ずかしいコードだらけだけど、ぜひツッコミ入れてもらえると助かります。

数年前までは、恥ずかしいからとか見せられるレベルじゃないからと、ほとんどアウトプットしなかったのですが、
最近はそれではものすごく損をしていると思っています。
ホントは発表するとか議論するとかする場もあればいいのですが。
アウトプットすることで、フィードバックが貰えて、いろんなかたの考えが参考になり、糧となり成長していけるのかと。
(これじゃ成長できないレベルだよという話でなければいいのだが。。。)

一度、Rubyのプロフェッショナル各位に見てもらいたいなぁw

comments powered by Disqus

See Also by Hugo


Related by prelims-cli