开发者

Closures in Ruby

Sample code:

def func(a, &closure)
  return a if a
  closure ||= lambda{ |words| puts "!!! " + words }
  closure.call("1")
  closure.call("2")
end

func(false){ |words| puts "??? " + words }   

Please explain. I can not understand this line:

closure ||= lambda{ |wor开发者_运维知识库ds| puts "!!! " + words }

If you remove || will be permanently displayed as follows: "!!! 1", "!!! 2". Why? And also explain this:

def func(a, &closure)

where did &closure.


def func(a, &closure)
    return a if a
    closure ||= lambda{ |words| puts "!!! " + words }
    closure.call("1")
    closure.call("2")
end

func(false){ |words| puts "??? " + words }   

In "&closure" the ampersand (&) means that the function takes a block as a parameter. What is happening is you are passing a Proc (a block is just a Proc defined with a different syntax) to the func function which is then called with the variable 1 and 2.

The ||= means "or equals." It is used to assign a value to a variable if the current value is nil. It is shorthand for:

closure = lamda{ |words| puts "!!! " + words } if closure.nil

This blog post explains blocks, Procs and lamdas well.


The token closure here does not have any significance at all. It is just a local block variable given as an argument. When func is used with a block, closure will refer to that block. If not, it will initially be nil. What ||= does is, when the variable is nil, it assigns what comes to the right. So if you use func with a block, closure will be that block; if you use it without a block, closure will be lambda{...}. Now, if you replace ||= with =, then closure will always be lambda{...} irrespective of whether you use it with a block. closure.call(1) will substiture 1 to words in closure, and you will get the output !!!1; similarly with closure.call(2), which outputs !!!2.


This is nothing to do with the closures

closure ||= lambda{ |words| puts "!!! " + words }

|| says that, if the variable closure alreay initialized just use it, otherwise initialize the new lambda ambda{ |words| puts "!!! " + words }

since you are passing the lambda already

func(false){ |words| puts "??? " + words } 

default lambda (having !!!) not initialized

But if you remove the ||, it always initialize the new lambda

You can print the !!! without removing ||, just call

   func(false)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜