block
- 作为代码块参数传给 method - calling_methods#Block Argument
- 使用
do ... end
和{ ... }
两种语法,且前者优先级低于后者 - 支持定义参数[也就支持参数默认值],在 method 内部使用 keyword
yield
调用 - methods#Block Arguments; 或 在参数定义时 使用前缀&
把 block 转换成 proc, 再使用.call
等方法调用,且保留 yield 用法 code - 支持 Numbered parameters, 即使用 _1, _2, … 代替;但两种方式不能同时使用;且不支持嵌套使用
- block 内没作用域[scope]; 因此使用变量时,需要在参数后面使用
;
分割定义,比如:|arg1, arg2; foo, bar|
;注意return
的使用 - method 内部使用
block_given?
判定调用是否传递了 block 参数
proc
- Kernel#proc
Proc.new { }
&
+ proc 可转换成 block,从而做参数传给 method; lambda 有特殊语义的 proc, 因此同样支持 & + lambda_proc 转换为 block- proc 的调用时,实参会根据 proc 参数定义决定是否解构。code:
p1 = proc { |a| p a } p2 = proc { |a, b| p a; p b; } p1.call [1, 2] # [1, 2] p2.call [1, 2] # 1 2
- 利用 block 没 scope 性质,实现闭包能力。code
def gen_times(factor) Proc.new {|n| n*factor } end
lambda
- 有属于自己特殊语义[调用时参数检查/return]的 proc
- Kernel#lambda 返回 proc. ex:
pr = lambda {puts "hello"}
- 语法糖:
var_lambda_proc = -> (arg1, arg2) { ... }
. 更像函数定义 - 用
proc_c.lambda?
判定 proc 对象是否有 lambda 语义。比如:l = lambda {|x, y| x }; [[1, 2], [3, 4]].map(&l)
会报异常 code - 把 method 转换到 proc 时,会保留 lambda 语义; 比如:
method(:to_s).to_proc.lambda? # true
; 同样使用 proc 定义的 method,在调用时会检查参数,case
proc 的使用
- #call
- #yield
- #===
- #[]
proc_c[]
,proc_c.[]
,proc_c.send(:[], ...)
- 柯里化 #curry
- #>>, #<< 熟悉 JavaScript 的话可参考 redux.js 里 compose 实现
Binding
- 存储 proc 的上下文数据 - Binding
- 使用 Kernel#binding 返回
胡思乱想
- 怎么区分 Ruby 的 keyword 和 calling methods?!记住有限的 keyword 吗?
- 不清楚为什么要搞出 block,proc,lambda 这三个玩意这里科普的对不对,先放过。