2012-10-20 121 views
4

我開始在整個代碼中放置print-statements。爲了不弄亂輸出,我不喜歡的東西:錯誤重要懶惰評估「#{}」 - ruby​​中的字符串

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}" } 

但這看起來很醜。那麼,如何評估一個'#{}'字符串?

+4

任何理由,爲什麼你不能使用內置的[記錄器類](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html)而不是重新發明輪子? –

+0

同意。使用記錄器或Syslog功能。不要重新發明輪子。 –

+0

使用記錄器,我必須將「嚴重性」映射到我的「調試級別」,這不是太好,恕我直言。用「太多字符」來編寫代碼塊的問題仍然是一樣的......所以我仍然希望能夠評估「#{big_class.inspect}」...... – ineiti

回答

1

我不認爲你可以避開那裏的醜陋。插值在調用dputs之前發生,除非您將其放入一個塊中,該塊將其推遲到dputs評估它爲止。我不知道dputs來自哪裏,所以我不確定它的語義是什麼,但我的猜測是這個塊會讓你得到你想要的懶惰評價。不漂亮,但它能完成這項工作。

+0

Dputs是我寫的一個簡單的模塊,它可以很好地打印調試消息,包括類和方法,並將很長的行格式化爲多個縮進行。 – ineiti

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 
+0

這個想法是,所以我寧願用單引號'dputs 5','長時間調試#{bigclass.inspect}','通過'dputs 5','長調試%s',bigclass.inspect'來編寫。我甚至不確定後者不會評估! – ineiti

+0

我剛剛檢查過,上面給出的sprintf示例在每種情況下都進行評估......所以我又回到了塊。但我相信有一種方法可以評估'#{big_class.inspect}'! – ineiti

+0

它會評估'inspect',當然,但不是插值。你可能會「確定」有一種方法來獲得你想要的語法和行爲,但沒有。 –

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方法遍歷每個'#{}' - 塊,因爲可能有多個,評估它(2 ..- 2刪除了「#{」和「}」 )並將其與其餘的字符串放在一起。

對於字符串不以'#{}' - 塊結尾的情況,添加一個空白塊,只是爲了確保。

但是,在Ruby中待了幾年之後,這仍然感覺笨重和C-ish。也許是時候學習一種新的語言!

+0

但是這實際上是在錯誤的上下文中評估變量,所以它不起作用。所以我想我給我的投票給邁克拉森說誰不能躲避醜陋。幾個月後,我已經習慣了新的語法;) – ineiti

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!" 

不要使用在生產:)