奇怪的 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 插件的明确目标之一 - 咱们正在尝试标准化,以便您能够回到编写应用程序代码之中。

相关文章
相关标签/搜索