七週七語言自習——Ruby次日

次日的主要內容包括定義函數、數組和散列表、代碼塊和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 ...

能夠將文件、行號、所在行內容都顯示出來

相關文章
相關標籤/搜索