`

ruby方法

    博客分类:
  • ruby
阅读更多
没事做,写着玩的。不过ruby的block,proc,闭包或lambda还是有些复杂的,主要是以前在java里面没见过这些东西,一时还不能完全理解,就算勉强理解了,一时半会也很难熟练的运用。ruby里面有许多比较怪异的用法,包括API在内,并不能一目了然的让程序员明白其中的意思,因此要想用好这门语言,必须专门花些时间看看其每个API的用法,这是一个很让人郁闷的地方。而且也不一定能记住或理解,这个实践过程就比搞java要痛苦一点了。
ruby可以为参数设定默认值,这样调用方法时就可以省略此参数:

def prefix(s,len=1)
  s[0,len]
end

p prefix("ruby")
p prefix("ruby",4)


也可以传递任意个参数,只需在参数前面加上*即可:
def max(first,*rest)
  max=first
  rest.each{|x| max=x if x>max}
  max
end

data = [1,3,6,4]
p max(*data)  #first=1,rest=[3,6,4] -> 6


代码块也是个比较有意思的东西,

def sequence(n,m,c)
  i=0
  while i<n
    yield i*m+c
    i+=1
  end
end

sequence(5,2,2){|x| puts x}


这种语法也很特别,也没在其它语言里见过,通过yield来调用块里面的代码。

代码块是ruby的一种句法结构,它们不是对象,也不能像对象一样操作,不过可以创建对象来表示一个代码块。根据对象的创建方式,叫做proc或者lambda。proc的行为与代码块类似,而lambda的行为则与方法类似,不过,它们都是Proc类的实例。

用&做前缀的代码块参数把代码块和方法关联起来,如:
def makeproc(&p)
  p
end

adder=makeproc{|x,y| x+y}
p adder.call(1,2)#3


也可以直接用Proc.new创建proc对象,上面的代码等价于

    def makeproc
         Proc.new
    end


另一种创建Proc对象的方式是使用lambda方法,它是Kernel模块的一个方法,所以看不起来像是一个全局函数。就像名字所暗示的,lambda方法返回的Proc对象是一个lambda而非proc。lambda方法不带参数,但是在调用时必须关联一个代码块:

succ=lambda{|x| x+1}
p succ.call(4)


Proc还定义了数组访问操作符,它的工作方式与call一样,这意味可以用与方法调用类似的方式调用proc或lambda:

p succ[5]
p adder[2,3]


从这点说,ruby的确不是很正规,不过比较好玩。

ruby里面也有闭包这个特性,这个在jdk1.7才有可能实现的特性,在ruby中早就有了,闭包的主要特点是能记住其被定义的上下文,并在被调用时使用该上下文。proc与lambda都是闭包。
def multiplier(n)
  lambda{|data| data.collect{|x| x*n}}
end
doubler = multiplier(2)
puts doubler.call([1,2,3]) #打印输出2,4,6


multiplier方法返回一个lambda,这个lambda在定义它的范围外被使用,我们称之为一个闭包,这个闭包封闭(或保持)了所绑定的方法参数n。

Proc定义了一个名为binding的方法,调用这个方法会返回一个Binding对象,它表示该闭包所使用的绑定。
闭包与绑定一起使用,大多数时候变得很简单,Binding对象本身并没有什么值得注意的方法,不过它可以作为全局函数eval的第二个参数,能为eval函数执行给定代码时提供一个上下文环境。在Ruby1.9中,Binding也自带了eval方法,你可能更愿意直接使用它。
使用Binding对象和eval方法可以让我们获得一个操控闭包行为的后门:

def multiplier(n)
  lambda{|data| data.collect{|x| x*n}}
end
doubler = multiplier(2)
puts doubler.call([1,2,3]) #打印输出2,4,6
eval("n=3",doubler.binding)
puts doubler.call([1,2,3]) #打印3,6,9

一种更快捷的方式是直接使用eval方法:eval("n=3",doubler)。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics