七周七语言自习——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 ...

能够将文件、行号、所在行内容都显示出来

相关文章
相关标签/搜索