ruby Enumerable#first vs #take

ruby Enumerable#first vs #take,第1张

概述ruby Enumerable / Array first(n)和take(n)之间有什么区别? 我模糊地回忆起take与懒惰评估有关,但我无法弄清楚如何使用它来做到这一点,并且找不到任何有用的谷歌搜索或文档. “take”是google的硬方法名称. first(n)和take(n)是documented非常相同,不太有帮助. first → obj or nilfirst(n) → an_a ruby Enumerable / Array first(n)和take(n)之间有什么区别?

我模糊地回忆起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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/langs/1287161.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存