我模糊地回忆起take与懒惰评估有关,但我无法弄清楚如何使用它来做到这一点,并且找不到任何有用的谷歌搜索或文档. “take”是Google的硬方法名称.
first(n)和take(n)是documented非常相同,不太有帮助.
first → obj or nilfirst(n) → an_arrayReturns the first element,or the first n elements,of the enumerable. If the enumerable is empty,the first form returns nil,and the second form returns an empty array.
–
take(n) → arrayReturns first n elements from enum.
告诉我“与懒惰评估有关”是不够的,我有点记得已经,我需要一个如何使用它的例子,与之相比.
解决方法 好吧,我看过源代码(Ruby 2.1.5).在引擎盖下,如果首先提供一个参数,它会转发它.否则,它返回一个值:static VALUEenum_first(int argc,VALUE *argv,VALUE obj){ NODE *memo; rb_check_arity(argc,1); if (argc > 0) { return enum_take(obj,argv[0]); } else { memo = NEW_MEMO(Qnil,0); rb_block_call(obj,ID_each,first_i,(VALUE)memo); return memo->u1.value; }}
另一方面,take需要一个参数,并始终返回给定大小或更小的数组,其中包含从头开始的元素.
static VALUEenum_take(VALUE obj,VALUE n){ NODE *memo; VALUE result; long len = NUM2LONG(n); if (len < 0) { rb_raise(rb_eArgError,"attempt to take negative size"); } if (len == 0) return rb_ary_new2(0); result = rb_ary_new2(len); memo = NEW_MEMO(result,len); rb_block_call(obj,take_i,(VALUE)memo); return result;}
所以,是的,这就是为什么这两个如此相似的原因.唯一的区别似乎是,第一个可以不带参数调用,并且不会输出数组,而是输出单个值.另一方面,< ...>.第一(1)等同于< ...> .take(1).就如此容易.
然而,对于懒惰的集合,情况有所不同.懒惰集合中的第一个仍然是enum_first,如上所示,它是enum_take的快捷方式.然而,采用C编码的lazy_take:
static VALUElazy_take(VALUE obj,VALUE n){ long len = NUM2LONG(n); VALUE lazy; if (len < 0) { rb_raise(rb_eArgError,"attempt to take negative size"); } if (len == 0) { VALUE len = INT2FIX(0); lazy = lazy_to_enum_i(obj,sym_cycle,1,&len,0); } else { lazy = rb_block_call(rb_cLazy,ID_new,&obj,lazy_take_func,n); } return lazy_set_method(lazy,rb_ary_new3(1,n),lazy_take_size);}
…不会立即评估,需要.force调用.
事实上,它暗示了in the docs under lazy
,它列出了所有懒惰实现的方法.该列表确实包含take,但不包含first.也就是说,在懒惰的序列中,保持懒惰,而不是.
以下是一些示例,它们的工作方式不同:
lz = (1..float::INFINITY).lazy.map{|i| i }# An infinite sequence,evaluating it head-on won't do# Ruby 2.2 also offers `.map(&:itself)`lz.take(5) #=> #<Enumerator::Lazy: ...># Well,`take` is lazy then# Still,we need valueslz.take(5).force#=> [1,2,3,4,5]# Why yes,values,finallylz.first(5)#=> [1,5]# So `first` is not lazy,it evaluates values immediately
通过在2.2之前的版本中运行并使用2.2的代码(< ...> .lazy.map(&:本身))可以获得一些额外的乐趣,因为这样当你失去懒惰的那一刻将立即引发NoMethodError.
总结以上是内存溢出为你收集整理的ruby Enumerable#first vs #take全部内容,希望文章能够帮你解决ruby Enumerable#first vs #take所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)