在Ruby中使用不带引号的字符串参数的method_missing - 可能吗?

时间:2013-05-03 17:33:16

标签: ruby metaprogramming method-missing

我正在学习Ruby并希望能够做到这一点:

Printer.hi there

并拥有Ruby输出

"hi there"   

到目前为止,我有以下实现

class Printer
  def method_missing(name, *args)
     puts "#{name} #{args.join(',')}"
  end
end

但这只能让我做到

Printer.hi "there"

如果我尝试

Printer.hi there

我得到了

NameError: undefined local variable or method `there' for main:Object

这是有道理的,因为我没有定义'那里'。有没有办法让这项工作?

4 个答案:

答案 0 :(得分:3)

不,这是不可能以给定的形式(据我所知)。

你不是在寻找缺少方法的方法,你正在寻找Ruby解释器中的等价物来捕获它找不到给定的符号。所以虽然你不能在那里拦截它,但你可以在一个区块内进行:

def hi(&block)
  begin
    yield
  rescue NameError => e
    e.message =~ /variable or method `(.+)'/
    puts "hi #{$1}"
  end
end

hi { there } # => hi there

请注意,我觉得你是一个可怕的世界公民,向你展示这个。请不要在任何地方使用它。

答案 1 :(得分:0)

不,因为需要引用字符串,因此不会将它们视为变量。

否则there之类的变量需要一些特殊的字符来表示它是一个字符串。然而,由于需要处理空间,因此仍然无法正常工作。

使用单引号或双引号 这就是语言的运作方式。接受这个并继续下一个挑战:)

答案 2 :(得分:0)

是的,有办法。当您在没有显式接收器的情况下编写there时,接收器是该范围的self对象。在这种情况下,它是main。在methods_missing上下文中定义main

def method_missing(name, *args)
  puts "#{name} was called with arguments: #{args.join(',')}"
end

但是,如果你这样做,那可能会破坏你的其余代码。我认为没有意义这样做。

由于puts的返回值为nil,如果您Printer.hi there,则评估为Printer.hi(nil)。因此,为了输出"hi there",您需要定义:

class Printer
  def self.hi _; puts "hi there" end
end

答案 3 :(得分:0)

有趣的是,您可以使用以下代码在ruby 1.8.7中执行此操作:

def method_missing(*args)
  puts args.join ' '
end

我从Gary Bernhardt的演讲中了解到了这一点Wat。在1.9中,这会给你一个堆栈级别太深的错误,除非你在一个类中执行它。谷歌引导我访问Aurthur's tech blog thing上的这篇帖子,声称你可以在JRuby 1.9模式下做类似的事情:

def method_missing(*args)
  puts [method.to_s, args].flatten.join ' '
end

然而,当我在MRI 1.9.3上尝试这个时,它也没有用。所以在1.9你不能完全做你想要的。这是我能来的最接近的地方:

class Printer
  def self.hi(message)
    puts "hi #{message}"
  end
  def self.method_missing(m, *args)
    [m.to_s, args].flatten.join ' '
  end

  def self.bare
    hi there
  end
end

Printer.bare