gpt4 book ai didi

ruby - 你能为 map 提供参数吗(&:method) syntax in Ruby?

转载 作者:数据小太阳 更新时间:2023-10-29 06:17:56 26 4
gpt4 key购买 nike

您可能熟悉以下 Ruby 速记(a 是一个数组):

a.map(&:method)

例如,在 irb 中尝试以下操作:

>> a=[:a, 'a', 1, 1.0]
=> [:a, "a", 1, 1.0]
>> a.map(&:class)
=> [Symbol, String, Fixnum, Float]

语法 a.map(&:class)a.map {|x| 的简写x.class.

在“What does map(&:name) mean in Ruby?”中阅读有关此语法的更多信息。

通过语法 &:class,您正在为每个数组元素调用方法 class

我的问题是:您可以为方法调用提供参数吗?如果是这样,怎么做到的?

比如下面的语法你怎么转换

a = [1,3,5,7,9]
a.map {|x| x + 2}

&: 语法?

我并不是说 &: 语法更好。我只对使用带参数的 &: 语法的机制感兴趣。

我假设您知道 + 是 Integer 类的一个方法。您可以在 irb 中尝试以下操作:

>> a=1
=> 1
>> a+(1)
=> 2
>> a.send(:+, 1)
=> 2

最佳答案

您可以像这样在 Symbol 上创建一个简单的补丁:

class Symbol
def with(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

这将使您不仅可以做到这一点:

a = [1,3,5,7,9]
a.map(&:+.with(2))
# => [3, 5, 7, 9, 11]

还有很多其他很酷的东西,比如传递多个参数:

arr = ["abc", "babc", "great", "fruit"]
arr.map(&:center.with(20, '*'))
# => ["********abc*********", "********babc********", "*******great********", "*******fruit********"]
arr.map(&:[].with(1, 3))
# => ["bc", "abc", "rea", "rui"]
arr.map(&:[].with(/a(.*)/))
# => ["abc", "abc", "at", nil]
arr.map(&:[].with(/a(.*)/, 1))
# => ["bc", "bc", "t", nil]

甚至可以使用 inject,它将两个参数传递给 block :

%w(abecd ab cd).inject(&:gsub.with('cde'))
# => "cdeeecde"

或者将 [shorthand] block 传递给 shorthand block 时 super 酷的东西:

[['0', '1'], ['2', '3']].map(&:map.with(&:to_i))
# => [[0, 1], [2, 3]]
[%w(a b), %w(c d)].map(&:inject.with(&:+))
# => ["ab", "cd"]
[(1..5), (6..10)].map(&:map.with(&:*.with(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

这是我与@ArupRakshit 的对话,进一步解释了它:
Can you supply arguments to the map(&:method) syntax in Ruby?


正如@amcaplan 在 comment below 中建议的那样,如果将 with 方法重命名为 call,则可以创建更短的语法。在这种情况下,ruby 为这种特殊方法 .() 提供了一个内置的快捷方式。

所以你可以像这样使用上面的内容:

class Symbol
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

这是一个使用 Refinements 的版本(这比全局猴子修补 Symbol 更简单):

module AmpWithArguments

refine Symbol do
def call(*args, &block)
->(caller, *rest) { caller.send(self, *rest, *args, &block) }
end
end

end

using AmpWithArguments

a = [1,3,5,7,9]
a.map(&:+.(2))
# => [3, 5, 7, 9, 11]

[(1..5), (6..10)].map(&:map.(&:*.(2)))
# => [[2, 4, 6, 8, 10], [12, 14, 16, 18, 20]]

关于ruby - 你能为 map 提供参数吗(&:method) syntax in Ruby?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23695653/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com