在如 rails 這樣的開源庫中,我們常常見到這樣的一類寫法: class_eval <<-RUBY, lxx_file, lxx_line + 1 def xxx # do something here end RUBY 令人困惑不已。 不過這裡的知識點非常簡單,只要掌握了 heredoc 與 e ...
在如 rails 這樣的開源庫中,我們常常見到這樣的一類寫法:
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def xxx
# do something here
end
RUBY
令人困惑不已。
不過這裡的知識點非常簡單,只要掌握了 heredoc 與 eval 的用法,就很好理解這裡的代碼了。
heredoc
heredoc 是一種定義多行字元串的方法,同時保持原始縮進和格式。相當於 JavaScript 中的 ``。
heredoc 以 <<-
開頭,跟上一個隨意的單詞,最後再以這個字元串結束:
multi_str = <<-FOO
1
2
3
FOO
puts multi_str
多行字元串會保留所有的縮進,並且在尾部會帶上 \n
換行符。
對於換行符,可以使用 chomp
來去除:<<-FOO.chomp
。
如果你在縮進的情況下聲明 heredoc,可能會變成這樣,十分醜陋:
multi_str = <<-FOO
1
2
3
FOO
如果保持縮進:
multi_str = <<-FOO
1
2
3
FOO
最後的輸出結果也會帶上 1 所有縮進,這裡可以使用 ~
代替 -
,或是使用 strip
。
multi_str = <<~FOO
1
2
3
FOO
multi_str = <<-FOO.strip
1
2
3
FOO
這兩種方式都會以第一行為標準,在所有行的開頭,刪除空格。
eval
eval 在很多腳本語言中都存在,它可以讓我們將字元串作為代碼執行。
ruby 中存在多個 eval 方法,比如 eval
class_eval
module_eval
instance_eval
等。
他們分別可以實現不同的 eval 功能。
以 class_eval
為例:
class Foo
STR = <<-RUBY
def say
p 'I am Foo'
end
RUBY
Module.class_eval STR
end
Foo.say
我們可以輕鬆將字元串變成方法。
代碼分析
現在我們終於可以看懂這段代碼了,它其實就是使用了 heredoc 多行字元串,將字元串里變成了一個真正的 ruby 方法。
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def xxx
# do something here
end
RUBY
那麼後面的 __FILE__, __LINE__ + 1
有什麼用呢?
其實我們完全可以不傳這兩個參數。
但是加入我們字元串生成的方法報了錯該怎麼辦呢?一般我們的方法報錯都會有文件名、行號。
eval 使用字元串生成方法,自然沒有這些東西,所以我們傳入當前文件的文件名,和當前行的行號+1,來幫助 Ruby 生成更好的報錯信息。
(完)
作者:幾乎一米八的徐某某 出處:Aero Blog (https://www.cnblogs.com/xhyccc/) 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連接,否則保留追究法律責任的權利。