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

时间:2023-01-14 14:51:35

I'm learning Ruby and want to be able to do this:

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

Printer.hi there

and have Ruby output

并有Ruby输出

"hi there"   

So far I have the following implementation

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

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

But this only lets me do

但这只能让我这样做

Printer.hi "there"

If I attempt

如果我尝试

Printer.hi there

I get a

我得到了

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

which makes sense as I haven't ever defined 'there'. Is there a way to make this work though?

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

4 个解决方案

#1


3  

No, this is not possible in the form given (as far as I know).

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

You aren't looking for method missing, you are looking for the equivalent in the Ruby interpreter to capture when it cannot find a given symbol. So while you cannot intercept it there, you can do it inside of a block:

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

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

hi { there } # => hi there

Please note that I feel like a terrible world citizen for showing you this. Please don't use it anywhere, ever.

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

#2


0  

Yes, there is a way. When you write there without an explicit receiver, the receiver is the self object of that scope. In this case, it is main. Define methods_missing in the main context.

是的,有办法。当你在没有显式接收器的情况下写入时,接收器是该范围的自身对象。在这种情况下,它是主要的。在主上下文中定义methods_missing。

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

But if you do so, that would mess up the rest of your code, perhaps. I see not point in doing this.

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

Since the return value of puts is nil, if you do Printer.hi there, it will evaluate to Printer.hi(nil). So in order for it to output "hi there", you need to define:

由于puts的返回值为nil,如果你在那里执行Printer.hi,它将评估为Printer.hi(nil)。所以为了输出“hi there”,你需要定义:

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

#3


0  

No because strings need to be quoted, so they are not seen as variables.

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

Otherwise variables such as there would need some special sort of character to indicate that it is a string. However this still wouldn't work well as spaces would then need to be dealt with.

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

Use single or double quotes.
It's how the language works. accept this and move on to the next challenge :)

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

#4


0  

Interestingly you can do this in ruby 1.8.7 with just this code:

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

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

I learned about this from Gary Bernhardt's talk, Wat. In 1.9 this gives you a stack level too deep error unless you do it inside a class. Google lead me to this post on Aurthur's tech blog thing, which claims you can do something similar in JRuby 1.9 mode:

我从Gary Bernhardt的演讲中了解到这一点,Wat。在1.9中,这会给你一个堆栈级别太深的错误,除非你在一个类中执行它。谷歌引导我在Aurthur的科技博客上发表这篇文章,声称你可以在JRuby 1.9模式下做类似的事情:

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

However when I tried this on MRI 1.9.3 it did not work either. So in 1.9 you can't quite do what you want. Here is the closest I could come:

然而,当我在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

#1


3  

No, this is not possible in the form given (as far as I know).

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

You aren't looking for method missing, you are looking for the equivalent in the Ruby interpreter to capture when it cannot find a given symbol. So while you cannot intercept it there, you can do it inside of a block:

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

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

hi { there } # => hi there

Please note that I feel like a terrible world citizen for showing you this. Please don't use it anywhere, ever.

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

#2


0  

Yes, there is a way. When you write there without an explicit receiver, the receiver is the self object of that scope. In this case, it is main. Define methods_missing in the main context.

是的,有办法。当你在没有显式接收器的情况下写入时,接收器是该范围的自身对象。在这种情况下,它是主要的。在主上下文中定义methods_missing。

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

But if you do so, that would mess up the rest of your code, perhaps. I see not point in doing this.

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

Since the return value of puts is nil, if you do Printer.hi there, it will evaluate to Printer.hi(nil). So in order for it to output "hi there", you need to define:

由于puts的返回值为nil,如果你在那里执行Printer.hi,它将评估为Printer.hi(nil)。所以为了输出“hi there”,你需要定义:

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

#3


0  

No because strings need to be quoted, so they are not seen as variables.

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

Otherwise variables such as there would need some special sort of character to indicate that it is a string. However this still wouldn't work well as spaces would then need to be dealt with.

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

Use single or double quotes.
It's how the language works. accept this and move on to the next challenge :)

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

#4


0  

Interestingly you can do this in ruby 1.8.7 with just this code:

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

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

I learned about this from Gary Bernhardt's talk, Wat. In 1.9 this gives you a stack level too deep error unless you do it inside a class. Google lead me to this post on Aurthur's tech blog thing, which claims you can do something similar in JRuby 1.9 mode:

我从Gary Bernhardt的演讲中了解到这一点,Wat。在1.9中,这会给你一个堆栈级别太深的错误,除非你在一个类中执行它。谷歌引导我在Aurthur的科技博客上发表这篇文章,声称你可以在JRuby 1.9模式下做类似的事情:

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

However when I tried this on MRI 1.9.3 it did not work either. So in 1.9 you can't quite do what you want. Here is the closest I could come:

然而,当我在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