奇怪的 Ruby
最近我為 prettier 寫了一個 Ruby 版本的外掛plugin for prettier ,在過程中我發現 Ruby 語言中很多奇怪的地方(通過需要考慮 AST 的每個節點型別以及結構的每個變體),我發現一些有趣的事情,並在這裡與你分享。
case
Ruby 中的 case 表示式與其他語言的 Switch 語句非常相似,它們提供基於一個值來處理不同邏輯分支的方法。但你也可以使用沒有謂詞的 case 表示式,
case when foo == 1 ... when bar == 2 ... end
這在功能上等同與檢查if foo == 1
和 elsifbar == 2
。
flip-flops
Flip-flops(名稱來自電路設計)是最難懂的操作符之一。這篇文章 有一個很好的解釋。
lines.each do |line| next unless (line =~ start_pattern)..(line =~ end_pattern) puts line end
基本上,這將遍歷一些列表lines
,列印滿足開始和結束時間條件的每一個行。
for 迴圈
你知道 Ruby 還有for
迴圈嗎?他們看起來像這樣:
for num in [1, 2, 3] do puts num end
這也意味著in
是一個保留字,所以你也不能將其用作識別符號。
hooks
Ruby 有兩個特殊的 Block 塊,它們內建在語言中讓你可以 hook 指令碼的開始和退出。我認為它們對於指令碼編寫特別有用,而對於應用程式級邏輯則不那麼有用。他們看著像是:
BEGIN { puts 'script has started' } END { puts 'script has ended' }
有趣的是這些 Block 不支援do...end
寫法,我不知道為什麼。
數字
在 Ruby 中二進位制,八進位制和十六進位制數字有一種特殊的語法表示,以下所有語句的值都為 true:
0b10 == 2# 二進位制 0o10 == 8# 八進位制 0x10 == 16# 十六進位制
最重要的是,您甚至可以刪除八進位制數重點額o
而使用字首0
,010 == 8
即為 true,如果不小心這個可能很容易出現意想不到的問題!
procs
Procs 和 lambdas 都有一個使用方括號呼叫的特殊語法,比如:
add = ->(left, right) { left + right } add[3, 4] # => 7
傳遞給方括號的引數數量與傳遞給 proc 的數量一致。因此,對於沒有元素的 proc 或 lambdas,您可以完全去掉引數,如:
greet = -> { puts 'Hello, world!' } greet[]
字串
字串有各種有趣的屬性!下面是一些讓我感到驚訝的事情。
%x
字面量
您可能知道反引號表示式(即ls
),它將生成一個程序在 shell 中執行,然後將 stdio 輸出返回給呼叫者。(要小心請不要自己 RCE)
你可能不知道%x
字面量,它們實際上是同一個東西(即%x[ls]
)。不要與其他 %-字面量 混淆,像%w
和%i
建立陣列!
%q
字面量
你可以使用%q
和%Q
來建立一個字串字面量(比如%q[abc]
)。這實際上和使用單引號和雙引號是一樣的,區別是後者不需要對雙引號進行轉移,非常方便。
插值
Ruby 中正常的字串插值看起來像這樣"a #{b} c"
,其中b
是會響應to_s
的變數( 即除BasicObject
之外的任何東西 )。但是你知道如果像插入一個例項(instance)、類或全域性變數可以不用大括號,也就是下面的程式碼完全有效:
@instance = 'instance' @@class = 'class' $global = 'global' "#@instance #@@class #$global" == 'instance class global' # => true
它甚至可以在正則表示式中使用!如果用上面的表示式中的/
替換雙引號,你將獲得帶有插值變數的正則表示式。
?
字面量
我之所以把最好的留到最後,因為這真的是挺奇怪,以下兩個語句在 Ruby 中都有效:
?a == 'a' ?\M-\C-a == "\x81"
事實證明?
允許您建立長度為 1 的字串,並引入一些特殊的附加功能。有關進一步說明,請直接從 Ruby 文件中獲取:
\cx or \C-x控制字元,其中 x 是一個可列印的 ASCII 字元 \M-x元字元,其中 x 是一個可列印的 ASCII 字元 \M-\C-x元控制字元,其中 x 是一個可列印的 ASCII 字元 \M-\cx如上 \c\M-x如上 \c? or \C-?刪除,ASCII 7Fh (DEL)
void
在Ruby中,您可以使用()
來表示nil
,因為它被視為沒有語句的空表示式。這導致能夠做各種奇怪的事情,比如!()
,其值為true
。
tl;dr
Ruby非常具有表現力,它為您提供了許多方法。這與許多語言形成了鮮明的對比(例如,在 Python 之蟬 (The Zen of Python) 中,它指出 “應該有一種 - 最好只有一種 - 顯而易見的方式”)。
當然這種方法有權衡。雖然它可以為您提供快速生產程式碼的能力,但如果有無數相似的處理方法,它也會降低閱讀效率。這是 prettier 和其 Ruby 外掛的明確目標之一 - 我們正在嘗試標準化,以便您可以回到編寫應用程式程式碼之中。