はじめに:Rubyクイズ!!
Rubyプログラマのみなさん、こんにちは。
突然ですが、問題です。
以下のコードを実行すると何が起きるでしょうか?
msg = """
Hello, world.
I am Ruby.
"""
puts msg
はい、実行結果はこうです。
$ ruby sample.rb
Hello, world.
I am Ruby.
どうですか?想像通りの結果になりましたか?
それではまた。ごきげんよう。
・・・ではなくて、上のコードに出てきた3連引用符("""
)ってみなさん知ってましたか?
Rubyを長年やってる人もあまり見たことはないんじゃないでしょうか。
というか僕も最近知りました。
"""
の種明かし
「Rubyに """
なんていう構文はあったっけな〜?🤔」と思ってネットや書籍を調べても、たぶんそんな構文はどこにも載っていないと思います。
これ、実は""" = "" + "
の意味になっているだけなんです。
つまり、先ほどのコードはこう書いているのとほぼ同じです。
msg = "" + "
Hello, world.
I am Ruby.
" + ""
結果として、こう書いていることと同じになります。
msg = "
Hello, world.
I am Ruby.
"
ウソだ!と思っている人も、puts
の代わりにp
を使って確認すると、納得がいくかもしれません。
msg = """
Hello, world.
I am Ruby.
"""
p msg
# => "\nHello, world.\nI am Ruby.\n"
公式リファレンスの説明を確認する
公式リファレンスにも以下のような説明が載っています。
空白を間に挟んだ文字列リテラルは、コンパイル時に1つの文字列リテラルと見倣されます。
p "foo" "bar"
=> "foobar"
リファレンスには「空白を間に挟む」とありますが、空白なしでも1つの文字列になるようです。
p "foo""bar"
# => "foobar"
よって、
"""abc"""
は、
"" "abc" ""
と書いていることになり、結果として、
"abc"
と書いたことになるわけです。
ちなみに、シングルクオートで書く場合も考え方は同じです。
p 'foo' 'bar'
# => "foobar"
p '''abc'''
# => "abc"
余談:C言語も同じ文法を持っています
「隣り合った文字列リテラルは1つの文字列として扱われる」という文法は、C言語でも同じだそうです。
というか、C言語の影響を受けているとこういう文法が用意される、と言った方が正しいかもしれません。
# include <stdio.h>
int main(void) {
// 実行すると"Hello, World!"になる
printf("Hello, " "World!\n");
return 0;
}
参考 https://stackoverflow.com/a/23811427/1058763
でもなんで """
なの?
しかし、なんでRubyでわざわざ"""
なんて書く人が出てくるんでしょうか?
僕は"""
を自分で書いたことがないので、これは僕の推測になりますが、PythonやCoffeeScriptなど、他の言語の文字列リテラル(改行が入れられる文字列リテラル)をうっかりRubyでも書いてしまった、という理由があるのかもしれません。
Pythonの場合
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")
出典 https://docs.python.org/ja/3/tutorial/introduction.html#strings
CoffeeScriptの場合
html = """
<strong>
cup of coffeescript
</strong>
"""
出典 https://coffeescript.org/#strings
しかし、Rubyであればこういうケースは"""
ではなく、ヒアドキュメント構文を使うのが良いと思います。
msg = <<TEXT
Hello, world.
I am Ruby.
TEXT
puts msg
# => Hello, world.
# I am Ruby.
まとめ
というわけで、この記事では摩訶不思議なRubyの3連引用符(ダブルクオート3つ、またはシングルクオート3つ)の謎について説明しました。
日常的に使うことはまったくオススメしませんが、ちょっとしたトリビアとして「へえ〜」と思ってもらえれば幸いです😄