title: 【Ruby】Block/Proc/lambda的区别
date: 2016-03-14 12:38:56
tags: ["Ruby"]
categories: ["程序开发"]
---
在Ruby语言中，Block 与 Proc 是不同的概念。而 Proc 和 lambda 虽然都是 Proc 对象，在进行处理时会有若干差别。

### Block 和 Proc.new
Block 是代码块，而 Proc 是对象。参数列别中最多只能有一个 Block ，但是可以有多个 Proc 或 Lambda。

Block 是指通过 do~end 或 {} 来进行传递的参数，通常与 yield 来搭配进行使用。
例如：
```
def method_block
    yield
end

method_block { p "block" }
#=> "block"
```

将 Block 进行对象化就是 Proc.new 。
Proc 对象一般通过 call 方法来进行调用：

```
def method_block(&block)
    block.call
end

method_block { p "block" }

#=> "block"
```

Proc.new 使用参数的情况：
```
proc = Proc.new{ |a| p a * 2 }
proc.call(2)
#=> 4
```

<!-- more -->

### Proc.new 和 lambda
lambda 函数是用于生成 Proc 对象的函数，与 Proc.new 一样通过 call 来进行调用。

```
def method_lambda
    lambda1 = lambda{ p "lambda" }
    lambda1.call
end

method_lambda

#=> "lambda"
```

但与 Proc.new 相比，两者有两点不通

#### 参数数目
lambda 会检查参数的个数，如果参数个数与规定参数个数不同的情况下，lambda 会报错。而 Proc.new 则不会进行参数检查。
Proc.new的情况：
```
proc = Proc.new{ |a,b,c| p "#{a},#{b},#{c}"  }
proc.call(2, 4)
#=> 2,4,nil
```
lambda的情况下：
```
lambda1 = lambda{ |a,b,c| p "#{a},#{b},#{c}"  }
lambda1.call(2, 4)
#=> wrong number of arguments (2 for 3) (ArgumentError)
```

#### return 与 break 等关键字的执行
Proc.new的情况下：
```
def method_proc
    proc = Proc.new { return p "proc" }
    proc.call
    p "method_proc"
end

#=>"proc"
```

lambda的情况下：
```
def method_lambda
    lambda1 = lambda{ return p "lambda" }
    lambda1.call
    p "method_lambda"
end

method_lambda

#=>"lambda"
#  "method_lambda"
```

在 `Proc.new` 的情况下， `return` 会从函数自身 method_proc 中跳出。而 `lambda` 则会回到 `method_lambda` 中。
