- 行コメント
- 埋め込みドキュメント(`=begin' 〜 `=end')
- マジックコメントとは
- エンコーディングの指定
- 文字列リテラルの凍結(`frozen_string_literal')
- インデント不整合の警告(`warn_indent')
- 定数の Ractor 共有可能化(`shareable_constant_value')
Ruby のコメントには、# から行末までを対象とする行コメントと、
=begin から =end までの行を対象とする埋め込みドキュメントの
2 種類があります(字句規則については 字句構造/コメント も参照してください)。
また、ソースファイルの先頭に書かれた特定の形式のコメントは「マジックコメント」と呼ばれ、通常のコメントとは違い、Ruby の処理系に対してエンコーディングの指定や文字列リテラルの扱いなどを伝える働きを持ちます。
行コメント
例# これは行コメントです。
p 1 + 1 # 式の後ろに書いたコメントです。
# から行末まではコメントとみなされ、Ruby インタプリタからは無視されます。ただし文字列リテラルの中の # や、?# という文字リテラルの # はコメントの開始とはみなされません。
埋め込みドキュメント(`=begin' 〜 `=end')
例=begin
ここから =end のある行までは
複数行にわたるコメント(埋め込みドキュメント)になります。
=end
puts "hello"
行頭(桁 0、インデントなし)から始まる =begin の行から、同じく行頭から始まる =end の行までの間はまとめてコメントとして扱われ、Ruby インタプリタからは無視されます。=begin と =end はどちらもインデントすると埋め込みドキュメントとして認識されず、構文エラーになります。
x = 1
=begin
この =begin はインデントされているため
埋め込みドキュメントの開始として認識されません。
=end
=begin・=end の行には、続けて自由な文字列を書くこともできます
(その部分も無視されます)。
=begin タイトルなど自由に書けます
本文
=end 任意の文字列
puts "hello"
Ruby インタプリタは埋め込みドキュメントの中身の書式を規定しませんが、慣習として RD 形式で書かれることが期待されています。
マジックコメントとは
マジックコメントとは、ソースファイルの先頭部分に書かれた特定の形式のコメントのことで、Ruby の処理系に対してそのファイルの解釈方法に関する指示を伝えるものです。通常のコメントと違い、書ける位置と書き方の形式が決まっています。
- マジックコメントが効果を持つのは、それが書かれたファイル自身に
対してだけです。
require/loadで読み込む他のファイルや、evalで評価する文字列には影響しません。 - ソースコード(実際に実行されるコード)より前に書かれている必要が あります。一度でも実行コードが出現した後に書いても無視されます。
- ファイルの 1 行目が
#!から始まる shebang 行 (Rubyの起動/インタプリタ行の解釈) である場合、マジックコメントは 2 行目以降から探されます。
現在 Ruby が認識するマジックコメントには以下のものがあります。
- エンコーディングの指定(エンコーディングの指定)
- 文字列リテラルの凍結(文字列リテラルの凍結(`frozen_string_literal'))
- インデント不整合の警告(インデント不整合の警告(`warn_indent'))
- 定数の Ractor 共有可能化(定数の Ractor 共有可能化(`shareable_constant_value'))
このうち、エンコーディングの指定だけは特別扱いされていて、ファイルの 1 行目(shebang がある場合は 2 行目)に厳密に書かれている必要があります。空行や他のコメント行を挟んだ位置に書いても認識されません。
それ以外のマジックコメント(frozen_string_literal, warn_indent,
shareable_constant_value)は、実行コードより前であれば、複数のコメント行や空行、=begin〜=end を挟んだ後に書いても認識されます。
# ファイルの説明などの通常のコメント
# 続きのコメント
# frozen_string_literal: true
p "abc".frozen? #=> true
複数のマジックコメントを、emacs のモードライン形式でまとめて 1 行に書くこともできます。
例# -*- coding: utf-8; frozen_string_literal: true -*-
p __ENCODING__ #=> #<Encoding:UTF-8>
p "abc".frozen? #=> true
エンコーディングの指定
例# coding: euc-jp
p __ENCODING__ #=> #<Encoding:EUC-JP>
ソースファイルのエンコーディング(スクリプトエンコーディング)を指定します。以下のいずれの書き方でも認識されます。
# encoding: euc-jp
# coding: euc-jp
# -*- coding: euc-jp -*-
Ruby 2.0 以降、マジックコメントが無い場合のデフォルトのスクリプトエンコーディングは UTF-8 です(Ruby 1.9 では US-ASCII でした)。
マジックコメントが指定されなかった場合の決定規則(コマンドライン引数や shebang との優先順位など)や、shebang 行がある場合の書き方など、より詳しい内容については 多言語化/magic comment を参照してください。Encoding クラス、Encoding.default_external も参照してください。
文字列リテラルの凍結(`frozen_string_literal')
例# frozen_string_literal: true
s = "abc"
p s.frozen? #=> true
begin
s << "d"
rescue => e
p e.class #=> FrozenError
end
true を指定すると、そのファイル内の文字列リテラルから生成される
String オブジェクトが、生成された時点であらかじめ freeze された状態になります。false(指定しなかった場合のデフォルト)では、この機能は無効です。
この設定はファイル単位で有効になります。require/load で読み込んだ他のファイルの文字列リテラルや、eval で評価した文字列リテラルには影響しません。
# frozen_string_literal: true
eval('p "abc".frozen?') #=> false
freeze されていないコピーが必要な場合は Object#dup や単項演算子
+(String#+@)が、明示的に freeze したコピーが必要な場合は単項演算子 -(String#-@)が使えます。
インデント不整合の警告(`warn_indent')
例# warn_indent: true
def foo
if true
puts "x"
end # if に対して end のインデントの深さが揃っていない
end
$ ruby -w indent.rb
indent.rb:6: warning: mismatched indentations at 'end' with 'if' at 4
end と、それに対応するキーワード(if など)とでインデントの深さが異なる場合に警告を出すかどうかを指定します。この警告自体はデフォルトで有効になっていますが、実際に表示されるのは -w オプションや -W2
を指定して実行した場合($VERBOSE が true の場合)に限られます。
# warn_indent: false と指定すると、-w/-W2 を指定して実行した場合でもこの警告を抑制できます。意図的に特殊なインデントを使うコード
(DSL やコード生成物など)で警告を消したい場合に使われます。
定数の Ractor 共有可能化(`shareable_constant_value')
例# shareable_constant_value: literal
FOO = {a: 1, b: [1, 2, 3]}
p Ractor.shareable?(FOO) #=> true
p FOO.frozen? #=> true
このマジックコメントより後にある定数への代入について、その値をどこまで自動的に Ractor で共有可能(Ractor.shareable?)にするかを指定します。以下のいずれかを指定します。
- **
none**(デフォルト): 何もしません。通常通りの代入を行います。 - **
literal**: 代入される値がリテラルであり、かつその中身も再帰的に 共有可能な値だけからなる場合に、freeze して共有可能にします。 - **
experimental_everything**: 代入される値がリテラルであるかに 関わらず、Ractor.make_shareable を使って共有可能にします (実験的機能)。 - **
experimental_copy**:experimental_everythingと同様ですが、 共有可能でない値の場合、元のオブジェクトを直接 freeze するのでは なく、コピーしてから freeze して共有可能にします(Ractor.make_shareable のcopy: trueに相当、実験的機能)。
# shareable_constant_value: experimental_copy
obj = Object.new
FOO = obj
p Ractor.shareable?(FOO) #=> true
p FOO.equal?(obj) #=> false (コピーされている)