【问题标题】:How to turn a Ruby method into a block?如何将 Ruby 方法变成一个块?
【发布时间】:2013-08-17 15:20:21
【问题描述】:

有没有办法简化下面的代码?

filenames 是文件名(字符串)的列表,例如["foo.txt", "bar.c", "baz.yaml"]

filenames.map { |f| File.size(f) }

有没有办法把“File.size”变成一个proc或block?对于现有对象的方法,我可以做&:method。模块级方法有类似的东西吗?

【问题讨论】:

    标签: ruby styles pointfree


    【解决方案1】:
    filesize = proc { |f| File.size(f) }
    filenames.map(&filesize)
    

    【讨论】:

    • +1 非常酷。为什么我没有想过这样做?现在我有了一个很棒的新重构技巧。
    • 这并没有简化它,它增加了额外的复杂性。
    • @MartinC.Martin 实际上,它并没有简化它。但这正是你问的。这个答案非常简单地将表达式变成了一个过程。怪你自己。这是你的错,不是洛根的。
    • 在这种情况下它并没有简化它,但是如果你需要重新使用 proc 它可以帮助保持干燥。有时,当您不关心 proc 的具体实现时,为复杂的 proc 命名(通过局部变量或方法)也有助于保持代码的可读性。
    • @MartinC.Martin fwiw,两者在一个重要方面存在细微差别。像这样使用.method 返回一个lambda,而不仅仅是一个proc。试试这个,你会明白我的意思:%w{what a nice little doggo}.map(&String.new.method(:upcase))
    【解决方案2】:

    你可以使用Object#method(method_name):

    filenames.map(&File.method(:size))
    

    【讨论】:

    • 是的..这是我要给的..但你打败了我..谢谢你提出这个..+1.
    • 有趣,我猜错了'&'的绑定顺序。
    【解决方案3】:

    Stdlib 的Pathname 为文件和目录提供了一种更加面向对象的方法。也许有一种方法可以重构您的filelist,例如而不是:

    filenames = Dir.entries(".")
    filenames.map { |f| File.size(f) }
    

    你会使用:

    require 'pathname'
    filenames = Pathname.new(".").entries
    filenames.map(&:size)
    

    【讨论】:

    • 谢谢,这解决了我的实际问题,虽然它没有回答问题的标题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 2013-09-29
    • 1970-01-01
    • 2012-07-04
    • 2014-01-05
    • 1970-01-01
    相关资源
    最近更新 更多