【问题标题】:how to natively implement a method like [] in Ruby?如何在 Ruby 中本地实现类似 [] 的方法?
【发布时间】:2011-12-22 22:18:21
【问题描述】:

所以如果像 [] 和 []= 这样的 index_accessor 方法没有硬编码到解释器中,有没有办法直接在 Ruby 中定义这些方法?换句话说,如何定义方法名称,其中参数位于方法名称“[*]”的一部分内

我可以发誓我曾经在 Pickaxe 或 Ruby Way 中发现过这个,但数小时的翻页让我两手空空

【问题讨论】:

  • 你看过Array[]Array[]=的源代码吗?它们是用 C 实现的。有关更多信息,请参阅Array's docs 中的源代码链接。
  • 我知道它们是用 C 编写的。但是您也可以将 [] 和 []= 添加到任何自定义对象,而不仅仅是重载 Array 子类。但我认为我同意这是不可能的,因为解释器对它们进行了硬编码并且没有自定义定义的能力。 (我想知道 Rubinius 是如何用他们的整个 'Implement Ruby in Ruby' 做到的......)
  • 这个问题真的不清楚。你应该给我们一些示例代码并说“这可能吗?”。
  • 我发现了我认为我看到的东西,它是方法名称中的@,用于在对象之前而不是之后应用方法名称(例如“def -@”然后你可以调用“ -obj" 有效,但这似乎只适用于 + 和 - ,尽管它可以用于任何对象的任何原因。哦,好吧

标签: ruby arrays methods function


【解决方案1】:
class Foo
  def []=(k, v)
  end

  def [](k)
  end
end

EDIT1:

虽然从定义上看可能不像,但上面定义的方法可以这样调用:

f = Foo.new
f[1] = 2
f[3]

【讨论】:

  • 我认为 OP 并没有特别询问 []... 他们想定义,比如说,obj<thing>,并且不知道如何让 ruby​​ 调用这样的方法。 AFAIK,这是不可能的,因为解释器只是针对它处理的少数情况有特殊规则。
  • 正确。这样例如我可以编写一些方法定义,它最终会像对象一样。|val|尽管由于其他原因无法使用管道,但它说明了意图
【解决方案2】:

不幸的是,没有办法用有趣的名字定义你自己的方法,你只能重新定义那些名字被硬编码到 Ruby 中的方法。

【讨论】:

    【解决方案3】:

    如果您想为 Ruby 引入新语法,我认为在 YARV 的源代码中编辑 parse.y 是不错的选择。 Rubykaigi 2011 上有一个名为 parse.y famtour 的演讲,向您展示了通过编辑 parse.y 可以做的各种事情。

    【讨论】:

      【解决方案4】:

      这是 Ruby 语法解析器的限制。通常你只能调用像object.method(arg) 这样的方法,但方括号是一种特殊情况(以及其他一些情况)。解析器会将object[something] 解释为object.[](something),即在object 上调用[] 方法,参数为something

      您可以使用任何您喜欢的方法名称,但对于花哨的方法名称,您必须使用define_method 而不是defsend,而不是直接调用该方法以使语法解析器理解您的代码。

      这是在 Greeter 上定义和调用方法 <> 的示例。

      class Greeter
        define_method "<>" do |name|
          puts "Hello, #{name}"
        end
      end
      
      Greeter.new.send("<>", "Semyon")
      

      【讨论】:

      • 其实[][]=可以分别称为object.[](1)object.[]=(1,2),不需要send
      • 谢谢,我不知道。编辑了答案。
      猜你喜欢
      • 1970-01-01
      • 2013-04-23
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多