Ruby:在将proc转换为块时提供参数

前端之家收集整理的这篇文章主要介绍了Ruby:在将proc转换为块时提供参数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们可以轻松定义一个方法并将其转换为带有一元&符号的块.
def my_method(arg)
  puts arg*2
end

['foo','bar'].each(&method(:my_method))

# foofoo
# barbar

# or
my_method = ->(arg) { puts arg*2 }
['foo','bar'].each(&my_method)
# same output

正如我们所看到的,当我们使用聚合时,第一个参数会自动传递.但是,如果我们需要传递2个甚至更多的参数呢?

my_method = ->(arg,num) { puts arg*num }
['foo','bar'].each(&my_method)
# ArgumentError: wrong number of arguments (1 for 2)
['foo','bar'].each(&my_method(3))
# NoMethodError: undefined method `foo' for main:Object
['foo','bar'].each do |i,&my_method|
  yield i,3
end
# LocalJumpError: no block given (yield)

在将proc转换为块时,是否可以传递其他参数?

解决方法

关于 your comment

Strange,but it swaps arguments during the performance

实际上,参数顺序是保留的.

curry返回一个新的proc,它有效地收集参数,直到有足够的参数来调用原始方法/ proc(基于它的arity).这是通过返回中间过程来实现的:

def foo(a,b,c)
  { a: a,b: b,c: c }
end

curried_proc = foo.curry  #=> #<Proc:0x007fd09b84e018 (lambda)>
curried_proc[1]           #=> #<Proc:0x007fd09b83e320 (lambda)>
curried_proc[1][2]        #=> #<Proc:0x007fd09b82cfd0 (lambda)>
curried_proc[1][2][3]     #=> {:a=>1,:b=>2,:c=>3}

你可以一次将任意数量的参数传递给curried的proc:

curried_proc[1][2][3]     #=> {:a=>1,:c=>3}
curried_proc[1,2][3]     #=> {:a=>1,:c=>3}
curried_proc[1][2,3]     #=> {:a=>1,2,:c=>3}

空参数被忽略:

curried_proc[1][][2][][3] #=> {:a=>1,:c=>3}

但是,你显然无法改变参数顺序.

currying的替代方法是部分应用程序,它通过修复一个或多个参数来返回具有较低arity的新proc.与咖喱不同,没有内置的部分应用方法,但您可以轻松编写自己的方法

my_proc = -> (arg,num) { arg * num }

def fix_first(proc,arg)
  -> (*args) { proc[arg,*args] }
end

fixed_proc = fix_first(my_proc,'foo')  #=> #<Proc:0x007fa31c2070d0 (lambda)>
fixed_proc[2]  #=> "foofoo"
fixed_proc[3]  #=> "foofoofoo"

[2,3].map(&fixed_proc) #=> ["foofoo","foofoofoo"]

或修复最后一个参数:

def fix_last(proc,arg)
  -> (*args) { proc[*args,arg] }
end

fixed_proc = fix_last(my_proc,2)  #=> #<Proc:0x007fa31c2070d0 (lambda)>
fixed_proc['foo']  #=> "foofoo"
fixed_proc['bar']  #=> "barbar"

['foo','bar'].map(&fixed_proc) #=> ["foofoo","barbar"]

当然,您不仅限于修复单个参数.例如,您可以返回一个采用数组并将其转换为参数列表的proc:

def splat_args(proc)
  -> (array) { proc[*array] }
end

splatting_proc = splat_args(my_proc)
[['foo',1],['bar',2],['baz',3]].map(&splatting_proc)
#=> ["foo","barbar","bazbazbaz"]

猜你在找的Ruby相关文章