gpt4 book ai didi

ruby - Ruby 中带有大写首字母的方法的可选括号?

转载 作者:数据小太阳 更新时间:2023-10-29 08:25:24 24 4
gpt4 key购买 nike

我刚开始在我的 .NET 应用程序中为 DSL 使用 IronRuby(但当我在纯 Ruby 中测试它时,行为似乎是一致的)——作为其中的一部分,我定义了通过 define_method 从 DSL 调用的方法.

但是,在调用以大写字母开头的方法时,我遇到了一个关于可选括号的问题。

给定以下程序:

class DemoClass
define_method :test do puts "output from test" end
define_method :Test do puts "output from Test" end

def run
puts "Calling 'test'"
test()
puts "Calling 'test'"
test
puts "Calling 'Test()'"
Test()
puts "Calling 'Test'"
Test
end
end

demo = DemoClass.new
demo.run

在控制台中运行此代码(使用纯 ruby​​)会产生以下输出:

ruby .\test.rb
Calling 'test'
output from test
Calling 'test'
output from test
Calling 'Test()'
output from Test
Calling 'Test'
./test.rb:13:in `run': uninitialized constant DemoClass::Test (NameError)
from ./test.rb:19:in `<main>'

我意识到 Ruby 约定是常量以大写字母开头,而 Ruby 中方法的一般命名约定是小写字母。但是现在,parens 真的扼杀了我的 DSL 语法。

有什么办法可以解决这个问题吗?

最佳答案

这只是 Ruby 歧义解决的一部分。

在 Ruby 中,方法和变量位于不同的命名空间中,因此可以有同名的方法和变量(或常量)。这意味着,当使用它们时,需要有某种方式来区分它们。通常,这不是问题:消息有接收者,而变量没有。消息有参数,变量没有。变量被分配给,消息没有。

唯一的问题是当你没有接收者、没有参数也没有赋值时。然后,Ruby 无法区分不带参数的无接收者消息发送和变量之间的区别。因此,它必须制定一些任意规则,这些规则基本上是:

  • 对于以小写字母开头的模糊标记,更愿意将其解释为消息发送,除非您肯定知道它是一个变量(即解析器(不是(!)口译员)之前看过作业)
  • 对于以大写字母开头的模糊标记,更愿意将其解释为常量

请注意,对于带有参数的消息发送(即使参数列表为空),没有歧义,这就是您的第三个示例有效的原因。

  • test():明明是消息发送,这里没有歧义
  • test:可能是消息发送,也可能是变量;解析规则说是消息发送
  • Test():明明是消息发送,这里没有歧义
  • self.Test:也是显然是一个消息发送,这里没有歧义
  • Test:可能是消息发送或常量;解析规则说它是一个常数

请注意,这些规则有点微妙,例如:

if false
foo = 'This will never get executed'
end

foo # still this will get interpreted as a variable

规则说,一个不明确的标记是被解释为变量还是消息发送是由解析器决定的,而不是由解释器决定的。所以,因为解析器已经看到了 foo = whatever,所以它将 foo 标记为一个变量,即使代码永远不会被执行而 foo 会评估为 nil,就像 Ruby 中所有未初始化的变量一样。

TL;DR 总结:你是 SOL。

可以做的是覆盖 const_missing 以转换为消息发送。像这样:

class DemoClass
def test; puts "output from test" end
def Test; puts "output from Test" end

def run
puts "Calling 'test'"
test()
puts "Calling 'test'"
test
puts "Calling 'Test()'"
Test()
puts "Calling 'Test'"
Test
end

def self.const_missing(const)
send const.downcase
end
end

demo = DemoClass.new
demo.run

除了这显然行不通,因为 const_missing 是在 DemoClass 上定义的,因此,当 const_missing 运行时,self DemoClass 这意味着它在应该通过 demo 调用 DemoClass#test 时尝试调用 DemoClass.test .test.

我不知道如何轻松解决这个问题。

关于ruby - Ruby 中带有大写首字母的方法的可选括号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2950956/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com