次日的主要內容包括定義函數、數組和散列表、代碼塊和yield、類的定義和Mixin。node
Ruby容許在類外定義函數,和Ruby中的其餘一切同樣,函數也是對象。數組和散列表提供了豐富的API,能夠在各類場合使用。代碼塊(block)和yield是最具Ruby風格的閉包方式。Ruby的類使用單繼承,能夠使用模塊的方式集成其餘方法。數組
練習ruby
1.有一個數組,包含16個數字,僅用each方法打印數組中的內容,一次打印4個數字。而後用可枚舉模塊的each_slice方法重作一遍。 閉包
僅用each這種表述可能有歧義,好像必須得使用條件語句才能實現。函數
A = (1..16).to_a #使用each i = 1 A.each do |a| if i % 4 == 0 puts a else print "#{a} " end i += 1 end #使用each_slice A.each_slice(4) do |g| puts g.join(" ") end
2.前面書中實現了一個有趣的樹類Tree,有着簡潔的用戶接口,如今要改寫一個新的初始化方法,接受散列表和數組嵌套的結構。寫好後你能夠接受這樣的樹:測試
{ "grandpa" => { "dad" => { "child1" => {}, "child2" => {} }, "uncle" => { "child3" => {}, "child4" => {} } } }
原文中的類是這樣的:spa
class Tree attr_accessor :children, :node_name def initialize(name, children=[]) @children = children @node_name = name end def visit_all(&block) visit &block children.each { |c| c.visit_all &block } end def visit(&block) block.call self end end
因爲下面訪問方法中代碼塊中調用的格式爲數組的調用方法,因此顯然必須得將輸入的散列表轉化爲數組,這就要每次遞歸調用初始化函數。改寫以後的方法以下:code
class Tree attr_accessor :children, :node_name def initialize(tree={}) @node_name = tree.keys()[0] @children = [] tree[@node_name].each do |key, value| @children.push( Tree.new( { key => value } ) ) end end def visit_all(&block) visit &block children.each { |c| c.visit_all &block } end def visit(&block) block.call self end end
測試用的代碼:對象
load 'Tree.rb' tree = Tree.new( { "grandpa" => { "dad" => { "child1" => {}, "child2" => {} }, "uncle" => { "child3" => {}, "child4" => {} } } } ) puts "Visiting a node" tree.visit { |node| puts node.node_name } puts puts "Visiting entire tree" tree.visit_all { |node| puts node.node_name }
我的感受用散列表初始化不如保持散列表的格式,改寫訪問方法。繼承
3.寫一個簡單的grep程序。
拖Ruby超強大的ARGF的福,這個實現起來易如反掌,兩行:
tar = ARGV.shift ARGF.each_with_index { |l, i| puts "#{ARGF.filename} #{i} : #{l}" if /#{tar}/.match(l) }
運行的時候使用
ruby grep.rb tar file1 file2 ...
能夠將文件、行號、所在行內容都顯示出來