ruby Enumerable#first 与 #take

2023-12-26

ruby 枚举/数组有什么区别first(n) and take(n)?

我依稀记得take与惰性评估有关,但我不知道如何使用它来做到这一点,并且在谷歌搜索或文档中找不到任何有用的东西。 “take”是一个很难通过谷歌搜索的方法名称。

first(n) and take(n) are 有记录的 http://ruby-doc.org/core-2.2.0/Enumerable.html非常相似,但没有太大帮助。

first → obj or nil
first(n) → an_array
Returns 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) → array
Returns first n elements from enum.

告诉我“take 与惰性评估有关”是不够的,我已经记得了,我需要一个示例来说明如何使用它,与first.


好吧,我已经查看了源代码(Ruby 2.1.5)。在引擎盖下, if first提供了一个参数,它将其转发给take。否则,它返回单个值:

static VALUE
enum_first(int argc, VALUE *argv, VALUE obj)
{
    NODE *memo;
    rb_check_arity(argc, 0, 1);
    if (argc > 0) {
    return enum_take(obj, argv[0]);
    }
    else {
    memo = NEW_MEMO(Qnil, 0, 0);
    rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
    return memo->u1.value;
    }
}

take, 另一方面,需要一个论点并始终返回给定大小或更小的数组,其中的元素是从开头获取的。

static VALUE
enum_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, 0, len);
    rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
    return result;
}

是的,这就是两者如此相似的原因。唯一的区别似乎是,first可以不带参数调用,并且不会输出数组,而是输出单值. <...>.first(1)另一方面,等价于<...>.take(1)。就如此容易。

然而,对于惰性集合,情况就不同了。first在惰性集合中仍然是enum_first如上所示,这是一个快捷方式enum_take. take然而,是 C 编码的lazy_take:

static VALUE
lazy_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, 1, &obj,
                     lazy_take_func, n);
    }
    return lazy_set_method(lazy, rb_ary_new3(1, n), lazy_take_size);
}

...这不会立即评估,需要.force呼吁这一点。

而事实上,它已经暗示了在下面的文档中lazy http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-lazy,它列出了所有延迟实现的方法。该列表确实包含take,但不包含first。也就是说,在惰性序列上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 values

lz.take(5).force
#=> [1, 2, 3, 4, 5]
# Why yes, values, finally

lz.first(5)
#=> [1, 2, 3, 4, 5]
# So `first` is not lazy, it evaluates values immediately

通过在 2.2 之前的版本中运行并使用 2.2 的代码可以获得一些额外的乐趣(<...>.lazy.map(&:itself)),因为这样当你失去懒惰的那一刻就会立即提高NoMethodError.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ruby Enumerable#first 与 #take 的相关文章

  • 将 ruby​​ 类转换为模块比使用改进更好的方法?

    Module refine http ruby doc org core 2 0 0 Module html method i refine方法接受一个类和一个块并返回一个细化模块 所以我想我可以定义 class Class def inc
  • 两个 ruby​​ 进程之间的通信可能/容易吗?

    如果我有一个 ruby 脚本Daemon顾名思义 它作为守护进程运行 监视系统的某些部分并能够执行需要身份验证的命令 例如更改权限 是否有一种简单的方法来拥有第二个 ruby 脚本 例如client 与该脚本通信并向其发送命令 询问信息 我
  • 为什么||和 或 在 Rails 中的行为有所不同? [复制]

    这个问题在这里已经有答案了 可能的重复 i true 和 false 在 Ruby 中是真的吗 https stackoverflow com questions 2802494 i true and false in ruby is tr
  • 如何使用 Ruby on Rails 3 检查 HTTP 请求的“Content-Length”字段?

    我正在使用 Ruby on Rails 3 在我的视图文件中我有以下代码 为了避免服务器过载 我会在服务器接收上传文件之前检查上传文件的大小 这是因为 按下表单的提交按钮 服务器会先完整接收文件 然后再检查文件 我知道一个HTTP 请求有标
  • 将 Rack::Deflater 插入机架中的哪个位置?

    我目前有以下内容 use Rack Rewrite use Rack Cache verbose gt true metastore gt memcached localhost 11211 rack cache meta entityst
  • rspec 中的模拟方法链

    有一系列方法可以获得user目的 我试图模拟以下内容以返回user in my Factory Girl current user AuthorizeApiRequest call request headers result 我可以模拟该
  • 升级到 Rails 6 时是否有一种编程方法可以检测 Zeitwerk::NameError?

    我目前正在将旧的 Rails 应用程序迁移到 Rails 6 好像项目中有些文件和里面定义的类不一致 运行应用程序测试时我没有看到此错误 但部署后我收到如下错误 Zeitwerk NameError expected file app my
  • 在 Rails 中呈现路由错误的 404 页面

    我试图在 Rails 中渲染集成的 404 页面作为例外 我尝试了这个 但仍然收到路由错误页面 posts controller rb def destroy if current user username post email post
  • Ruby 的 Faraday - 多次包含相同的参数

    我正在使用一个 API 该 API 迫使我多次发送相同的参数名称以级联不同的过滤条件 因此 示例 api GET 调用如下所示 GET http api site com search a b1 a b2 a b3 a c2 我使用 Far
  • 如何加载 UrlHelper 和 Rails 中的路线?

    我想包括路线和link toPORO 中的方法 在控制台中测试这个时 我遇到了这个 如果我在没有路由助手的情况下包含 UrlHelper 一切似乎都工作正常 ruby 1 9 3 rc1 001 gt Rails version gt 3
  • 默认:Rails 资源路由的排除选项

    一个小问题 我正在将 Rails 用于 REST API 但由于它是 RESTful API 所以我并不真正需要 new or edit我的任何资源的路由 因为人们只会完全通过自动 JSON 请求而不是图形方式与此 API 交互 例如 不需
  • 何时使用node.js、sinatra、rails? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 这 3 种语言 框架的最佳用途是什么 混合所有 或 2 个 有用吗 如果您正在构建一个完整的 Web 应用程序 您可能应该使用 Rails 因为
  • 为什么包含此模块不会覆盖动态生成的方法?

    我试图通过包含一个模块来覆盖动态生成的方法 在下面的示例中 Ripple 关联添加了rows 方法表 我想调用该方法 但之后还要做一些额外的事情 我创建了一个模块来重写该方法 认为该模块的row 可以打电话super使用现有的方法 clas
  • 启动同一作业的多个延迟作业进程

    我在运行多个工作人员的设置中使用延迟作业 就我的问题而言 这并不重要 但假设我运行 10 个工作线程 当前在开发模式下执行此操作 我遇到的问题是两个不同的工作人员有时开始处理同一项工作 调用我的工作对象上的执行方法 据我所知 延迟作业正在使
  • 添加两个 ActiveRecord::Relation 对象[重复]

    这个问题在这里已经有答案了 如何将两个关系添加在一起 当我尝试 运算符时 它返回一个数组 但我需要它来返回关系 谢谢 麦克风 Try new relation relation merge another relation
  • rake db:migrate db:reset 和 db:schema:load 之间的区别

    和 之间的不同rake db migrate and rake db reset我很清楚 我不明白的是如何rake db schema load与前两者不同 只是为了确保我在同一页面上 rake db migrate 运行尚未运行的迁移 r
  • Cucumber / Savon 省略或删除日志输出

    在运行黄瓜测试时 我得到 除了测试结果之外 许多与调试 日志相关的输出 格式如下 D 2013 03 06T12 21 38 911829 49031 DEBUG SOAP request D 2013 03 06T12 21 38 911
  • Rails 3.2 防止使用错误保存对象

    我有一个 ActiveRecord 对象 我想阻止它被保存 而不对模型进行永久验证 你曾经可以使用做这样的事情errors add但它看起来不再有效了 user User last user errors add name name doe
  • Rails: :inverse_of 和关联扩展

    我有以下设置 class Player lt ActiveRecord Base has many cards inverse of gt player do def in hand find all by location hand en
  • Rails 基本 Base64 身份验证

    我正在尝试复制此 GET curl 请求 curl D X GET H Authorization Basic dGVzdEB0YXByZXNlYXJjaC5jb206NGMzMTg2Mjg4YWUyM2ZkOTY2MWNiNWRmY2Nl

随机推荐