奇怪的 Ruby

最近我爲 prettier 寫了一個 Ruby 版本的插件 plugin for prettier,在過程當中我發現 Ruby 語言中不少奇怪的地方(經過須要考慮 AST 的每一個節點類型以及結構的每一個變體),我發現一些有趣的事情,並在這裏與你分享。git

case

Ruby 中的 case 表達式與其餘語言的 Switch 語句很是類似,它們提供基於一個值來處理不一樣邏輯分支的方法。但你也可使用沒有謂詞的 case 表達式,github

case
when foo == 1
  ...
when bar == 2
  ...
end

這在功能上等同與檢查 if foo == 1 和 elsif bar == 2正則表達式

flip-flops

Flip-flops(名稱來自電路設計)是最難懂的操做符之一。這篇文章有一個很好的解釋。shell

lines.each do |line|
  next unless (line =~ start_pattern)..(line =~ end_pattern)

  puts line
end

基本上,這將遍歷一些列表 lines,打印知足開始和結束時間條件的每個行。數組

for 循環

你知道 Ruby 還有 for 循環嗎?他們看起來像這樣:ruby

for num in [1, 2, 3] do
  puts num
end

這也意味着 in 是一個保留字,因此你也不能將其用做標識符。less

hooks

Ruby 有兩個特殊的 Block 塊,它們內置在語言中讓你能夠 hook 腳本的開始和退出。我認爲它們對於腳本編寫特別有用,而對於應用程序級邏輯則不那麼有用。他們看着像是:插件

BEGIN {
  puts 'script has started'
}

END {
  puts 'script has ended'
}

有趣的是這些 Block 不支持 do...end 寫法,我不知道爲何。設計

數字

在 Ruby 中二進制,八進制和十六進制數字有一種特殊的語法表示,如下全部語句的值都爲 true:code

0b10 == 2   # 二進制
0o10 == 8   # 八進制
0x10 == 16  # 十六進制

最重要的是,您甚至能夠刪除八進制數重點額 o 而使用前綴 0010 == 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 插件的明確目標之一 - 咱們正在嘗試標準化,以便您能夠回到編寫應用程序代碼之中。

相關文章
相關標籤/搜索