我开始在我的代码中放置print语句。为了不使输出混乱,我做了类似的事情:
dputs LEVEL, "string"
其中LEVEL
为0表示错误,1表示重要... 5表示详细,并与DEBUG_LEVEL
进行比较。现在我的问题是,在一个声明中:
dputs 5, "#{big_class.inspect}"
总是评估字符串,如果我将DEBUG_LEVEL
设置为1.此评估可能需要很长时间。我最喜欢的解决方案是:
dputs 5, '#{big_class.inspect}'
然后根据需要评估字符串。但是我没有设法以我能评估的形式获得字符串。所以我能想到的唯一想法是:
dputs( 5 ){ "#{big_class.inspect}" }
但这看起来很难看。那么我该如何评估一个'#{}'字符串?
答案 0 :(得分:6)
您可以dputs
使用sprintf
(通过%
)来完成此操作。这样它就可以决定不构建内插字符串,除非它知道它将打印它:
def dputs(level, format_str, *vars)
puts(format_str % vars) if level <= LEVEL
end
LEVEL = 5
name = 'Andrew'
dputs 5, 'hello %s', name
#=> hello Andrew
或者,正如您所建议的那样,您可以传递一个块,该块将推迟插值直到块实际运行:
def dputs(level, &string)
raise ArgumentError.new('block required') unless block_given?
puts string.call if level <= LEVEL
end
答案 1 :(得分:1)
我认为你不能在那里躲避丑陋。插值发生在调用dput之前,除非你把它放在一个块中,这会推迟它直到dputs评估它。我不知道dput来自哪里,所以我不确定它的语义是什么,但我猜这个块会让你得到你想要的懒惰评估。不漂亮,但它确实起到了作用。
答案 2 :(得分:1)
我认为这没什么价值,但我想出了:
2.3.1 :001 > s = '#{a}'
=> "\#{a}"
2.3.1 :002 > a = 1
=> 1
2.3.1 :003 > instance_eval s.inspect.gsub('\\', '')
=> "1"
2.3.1 :004 > s = 'Hello #{a} and #{a+1}!'
=> "Hello \#{a} and \#{a+1}!"
2.3.1 :005 > instance_eval s.inspect.gsub('\\', '')
=> "Hello 1 and 2!"
不要在生产中使用它:)
答案 3 :(得分:0)
a = '#{1+1} some text #{big_class.inspect}'
仅在需要时,我找不到比通过字符串更好的方式和 eval 所遇到的所有“#{}”:
str = ""
"#{b}\#{}".scan( /(.*?)(#\{[^\}]*\})/ ){
str += $1
str += eval( $2[2..-2] ).to_s
}
如果你没有明确,你可以摆脱临时变量 str :
"#{b}\#{}".scan( /(.*?)(#\{[^\}]*\})/ ).collect{|c|
c[0] + eval( c[1][2..-2] ).to_s
}.join
String.scan-method遍历每个'#{}' - 块,因为可能有不止一个,评估它( 2 ..- 2 会删除“#{ “和”}“)并将其与字符串的其余部分放在一起。
对于不以'#{}' - 块结尾的字符串的角落情况,添加一个空块,只是为了确定。
但是,在Ruby工作了几年之后,这仍然感觉很笨拙和C-ish。也许是时候学习一门新语了!