请注意,这是对我的问题here 的跟进。
我正在尝试解析以下Tcl代码:
foo bar {
biz buzz
}
在Tcl中,foo
是方法名称,bar
是参数,其余是eval
要处理的“块”。
现在这是我目前的实现:
def self.foo(name, &block)
puts "Foo --> #{name}"
if block
puts "block exists"
else
puts "block does not exist"
end
end
def self.method_missing(meth, *args, &block)
p meth
p block
meth.to_s &block
end
tcl = <<-TCL.gsub(/^\s+/, "").chop
foo bar {
biz buzz
}
TCL
instance_eval(tcl)
其中输出以下内容:
:bar
#<Proc:0x9e39c80@(eval):1>
Foo --> bar
block does not exist
在此示例中,当块传递给foo
方法时,它不存在。然而在method_missing
它确实存在(至少它似乎存在)。这是怎么回事?
注意,我知道ruby的括号优先级,并意识到这有效:
foo (bar) {
biz buzz
}
但是,我想省略括号。那么在红宝石中这是可能的(没有词汇分析)吗?
答案 0 :(得分:1)
这与method_missing
无关。在传递块和一些参数时,您根本无法省略括号。在您的情况下,Ruby将尝试使用块作为参数调用bar
方法,并将其全部结果作为单个参数传递给foo
方法。
您可以通过简化方法调用来自己尝试(所有元编程都只是模糊了您案例中的真正问题):
# make a method which would take anything
def a *args, &block
end
# try to call it both with argument and a block:
a 3 {
4
}
#=>SyntaxError: (irb):16: syntax error, unexpected '{', expecting $end
# from /usr/bin/irb:12:in `<main>'
答案 1 :(得分:1)
你可以这样做(我标记了我改变的行):
def self.foo args # changed
name, block = *args # changed
puts "Foo --> #{name}"
if block
puts "block exists"
else
puts "block does not exist"
end
end
def self.method_missing(meth, *args, &block)
p meth
p block
return meth.to_s, block # changed
end
那样,块就会存在。
答案 2 :(得分:0)
因此,我发现最好的解决方案是在处理字符串之前只需gsub
字符串。
tcl = <<-TCL.gsub(/^\s+/, "").chop.gsub('{', 'do').gsub('}', 'end')
foo bar {
biz buzz
}
TCL