分享 <Ruby 元编程> 思维导图 4 (代码块)

flingjie · May 04, 2014 · Last by flingjie replied at May 06, 2014 · 3455 hits

块继承自“函数式编程语言 (functional programming languages)”的世界。

  • 注 1: 在一个方法中,可以向 Ruby 询问当前的方法调用是否包含块。这可以通 过 Kernel#block_given?() 方法来做到。

  • 注 2: 如果在一个扁平作用域中定义了多个方法,这这些方法可以用一个作用 域们进行保护,并共享绑定,这种技术称为共享作用域。

  • 注 3: 传递给 instance_eval() 方法的块称为一个上下文探针,因为它就像是一 个深入到对象中的代码片段,对其操作。

    class C
    def initialize
    @x="a private instance variable"
    end
    end
    

obj=C.new obj.instance_eval(@x) #=>"a private instance variable"


 * 注4: 有时,你会创建一个对象,仅仅是为了在其中执行块。这样的对象称为洁净室。洁净室仅仅是一个用来执行块的环境,它通常还会暴露若干有用的方法供块调用。
``` ruby
class CleanRoom
  def a_useful_method(x);x*2;end
end

CleanRoom.new.instance_eval{a_useful_method(3)}  #=>6
  • 注 5: 1.return 方式不同。lambda 从可调用对象中返回,而 proc 从原始上下文中返回。 2.参数检查方式不同。如果 lambda 的产生数量不对,这它会失败,同时抛出一个 ArgumentError 错误;而 proc 则会自动调整传递进来的参数,通过忽略多余的参 数以及为未赋值参数置 nil。

  • 注 6: Method 对象类似于 lambda,但是有一个重要的区别:lambda 在它的作用域中执行 (它是一个闭包),而 Method 对象会在它自身所在对象的作用域中执行。

块知识补充 块是 Ruby 中的一等公民,本质上,它只是一段代码,相当于一个匿名函数。 可以说,块是 Ruby 中最酷、最有用的特性之一。块可以消除重复和临时变量,使代码更加简洁和紧凑,从而更易阅读和维护。块特性整理如下: 1.提高代码简洁性

# 枚举一行搞定
[1, 2, 3].each {|i| puts i}

结果:

1
2
3

2.消除重复,发挥类似回调的作用

def callBlock
  yield
  yield
end

callBlock {puts "It is a block"}

结果:

It is a block
It is a block

3.迭代

"This is a string".instance_eval do
    "HaHa, easy to reverse => #{reverse}."
end

4.简化资源操作

File.open(filename) do |file|
   do someting with file
end
# 文件自动关闭,无需手动执行

5.块中本地变量 (从 1.9 开始,;开头)

x = 'outer'
2.times do |;x|
  x = 'inner'
  puts x
end

结果:

inner
inner

不足之处,欢迎指正补充^_^

注 3 的代码里有点小问题 obj.instance_eval(@x}

@sunday35034 thx,已修正。

很好,matz 在七语言访谈中说块是他最喜欢的,可以重点介绍

@chenge 谢谢,我也觉得块是最酷的特性之一,另外,新补充了块的使用,欢迎指点

#4 楼 @flingjie 3 是迭代么?5 我还是第一次见,不知道有什么用,我是 1.9.3 元编程是目前估计最好的中文书了。

@chenge 3 我觉得是迭代字符串,不知这个描述是否准确? 5 我也是在查找块资料是发现的。这里再参考别人的代码对比下

# 1.9之前
current = "2012"
1.upto(10) do |i|
  current = i
  succ = current + 1
  print "#{current}, #{succ}"
end
print current #=> 10
# 1.9以后
current = "2012"
1.upto(10) do |i ;current|
  current = i
  succ = current + 1
  print "#{current}, #{succ}"
end
puts current #=> 2012

Block variable scope in Ruby is pretty intuitive – especially for those of us who are familiar with similar functionality in JavaScript. The newer block-local functionality in Ruby 1.9 is nice, but it’s only going to be useful in some niche scenarios. I would rather use more descriptive variable names to avoid overriding variables by accident. 原文http://www.jacopretorius.net/2012/01/block-variable-scope-in-ruby.html

You need to Sign in before reply, if you don't have an account, please Sign up first.