I';我在学Ruby,我不';我不清楚:*在inject(:*)中的含义
我正在写一个计算数字阶乘的方法,我在搜索中发现了类似的东西I';我在学Ruby,我不';我不清楚:*在inject(:*)中的含义,ruby,Ruby,我正在写一个计算数字阶乘的方法,我在搜索中发现了类似的东西 def factorial(number) (1..number).inject(:*) || 1 end 它可以工作,我理解注入函数在做什么,但我不清楚(:\*)部分的真正含义 我知道这一定是写{num,prod | num*prod}的速记版本,但我希望有一个清楚的解释。谢谢 它意味着要处理的符号,它是一种快捷方式。通常你会写一些 array.map { |e| e.join } 如果符号为proc,则简写为 array.m
def factorial(number)
(1..number).inject(:*) || 1
end
它可以工作,我理解注入函数在做什么,但我不清楚(:\*)
部分的真正含义
我知道这一定是写
{num,prod | num*prod}
的速记版本,但我希望有一个清楚的解释。谢谢 它意味着要处理的符号
,它是一种快捷方式。通常你会写一些
array.map { |e| e.join }
如果符号为proc,则简写为
array.map(&:join)
inject
和reduce
类似,但在这些情况下不需要&
例如,如果您有一个名为numbers
把这些数字加起来,你可以
numbers.inject(&:+)
或者你可以省去符号
numbers.inject(:+)
Inject是一种针对enumerable的方法,它使用一个符号(如您的情况)或一个块(如您建议的长手)组合所述enumerable的元素
例如:
(5..10).reduce(:*)
相当于(5..10).inject{prod,n | prod+n}
:*
只是inject
要执行的方法的*
的方法名。如果您查看inject
它说
如果改为指定符号,则集合中的每个元素都将传递给memo的命名方法。在任何一种情况下,结果都将成为memo的新值。迭代结束时,memo的最终值是该方法的返回值
因此,考虑到inject{| memo,obj | block}
以下是相等的
ary = [1,2,3]
ary.inject(:*)
#=> 6
ary.inject { |memo, obj| memo.*(obj) }
#=> 6
简短解释
:*
是一个符号。符号是不可变的字符串:*
与“*”
类似,只是它是不可变的
在ruby中,乘法也是一种方法调用。这相当于调用第一个乘法器的*(second)
方法,并将第二个乘法器作为参数。事实上,您可以键入3.*(4)
而不是3*4
<就ruby而言,code>3*4只是语法上的糖分
ruby中的方法调用可以通过public\u向对象发送ing符号消息来调用<代码>3。公共发送(:*,4)
也将像3*4
一样工作
要注入的参数被解释为应该是什么类型的消息public\u senT
,也就是说,应该从注入方法的内部调用什么方法
更长的解释
你可以想到
[ 1, 2, 3, 4 ].inject(:*)
在调用inject
的每个可枚举对象的每个相邻对之间注入“*”:
[ 1, 2, 3, 4 ].inject(:*) == 1 * 2 * 3 * 4
当然,1*2*3*4
相当于从左到右,在跑步记录和下一个数字上应用:*以获得下一个记录,然后返回最终记录
module Enumerable
def inject_asterisk
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = tally * next_num
end
return tally
end
end
[2, 3, 5].inject_asterisk #=> 30
您可以通过将组合tally
和next_number
的操作作为参数函数来概括这一点。ruby中的块基本上用作参数函数,总是有一个保留点
module Enumerable
def inject_block(&block)
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].inject_block {|tally, next_num| tally + next_num } #=> 10
如果你的街区总是这样
{|tally, next_num| tally.method_of_tally(next_num) }
在这种情况下(请记住tally+next\u num
tally.+(next\u num)
tally.public\u send(:+,next\u num)
),您可以决定只传递:方法\u of \u tally
作为参数并暗示该块
module Enumerable
def my_inject(method_of_tally_symbol, &block)
if method_of_tally_symbol
block = Proc.new { |tally, next_num|
tally.public_send(method_of_tally_symbol, next_num)
}
end
tally = first
rest = slice(1, length - 1)
rest.each do |next_num|
tally = block.call(tally, next_num)
end
return tally
end
end
[2, 3, 5].my_inject(:+) #=> 10
这一切都是关于将重复的模式提取到可重用组件中,这样您就不必键入那么多的内容。这与Symbol\to#proc
Enumerableinject
完全没有任何关系,只需将方法的名称作为Symbol
,就像是说,attr\u accessor
或define_方法
或发送
。因此,当您使用符号时,累加器是隐含的,因此它实际上只是表示相同内容的一种较短方式。是的,从文档中,仅作为方法名称的符号被发送到备忘录
,并以obj
作为参数。