如何传递闭包以将 Ruby 作为参数发送

How to pass a closure to send in Ruby as an argument

我这样使用send

[:last, :first].map { |sym| [0,1,2].send(sym) }
#=> [2, 0]

我正在尝试向 send 传递一个 index 和 rindex 的符号,以及一个用于执行它们的闭包:

[:rindex, :index].map { |sym| [0,1,2].send(sym, { |x| x %2 == 0  }) }

我收到一条错误消息:

SyntaxError: (irb):4: syntax error, unexpected '|', expecting '}'
...p { |sym| [0,1,2].send(sym, { |x| x %2 == 0  }) }

我做错了什么?

没有火箭科学选项:

%i(rindex index).map { |meth| [0,1,2].public_send(meth) { |x| x % 2 == 0  } }
#=> [2, 0]

短一点(使用Integer#even?):

%i(rindex index).map { |meth| [0,1,2].public_send(meth, &:even?) }
#=> [2, 0]

要传递闭包,应该使用 & 符号指示 ruby 解析器它是一个块:

[ :rindex, :index ].map do |sym|
  [0,1,2].send(sym, &->(x){ x % 2 == 0  })
end
#⇒ [2, 0]

What am I doing wrong?

在 Ruby 中,块被传递 参数列表之后而不是 在它里面 :

foo(1, { puts 'Hello' }) # wrong
foo(1) { puts 'Hello' }  # right

因此,您的代码应如下所示:

[:rindex, :index].map {|sym| [0, 1, 2].send(sym) {|x| x %2 == 0 }}

注意:您应该始终更喜欢 public_send 而不是 sendsend 同时做两件事:允许消息的名称是动态的,并打破封装。如果您使用 send,阅读您代码的人永远无法确定您实际使用的是这两个功能中的哪一个。在这种情况下,您根本没有破坏封装,您只是在使用动态消息名称。这正是 public_send 所做的。

%i[rindex index].map {|meth| [0, 1, 2].public_send(meth, &:even?)}

这将是一种更惯用的代码编写方式。