Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
I';我在学Ruby,我不';我不清楚:*在inject(:*)中的含义_Ruby - Fatal编程技术网

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
Enumerable
inject
完全没有任何关系,只需将方法的名称作为
Symbol
,就像是说,
attr\u accessor
define_方法
发送
。因此,当您使用符号时,累加器是隐含的,因此它实际上只是表示相同内容的一种较短方式。是的,从文档中,仅作为方法名称的符号被发送到
备忘录
,并以
obj
作为参数。