予約語は知っておきたい。
成果物
情報源
字句構造
- 識別子
- コメント
- 埋め込みドキュメント
- 予約語
Rubyの現在の実装はASCIIキャラクタセットを用いています。アルファベットの大文字と小文字は区別されます。識別子と一部のリテラルの途中を除いては任意の場所に空白文字やコメントを置くことができます。空白文字とはスペース、タブ、垂直タブ、バックスペース、キャリッジリターン、ラインフィード、改ページです。改行は行が明らかに次の行に継続する時だけ、空白文字として、それ以外では文の区切りとして解釈されます。
ASCIIなのか。日本語のコメントとかはどうなっているの? というか、たしかUCS正規化方式でなくCSI方式だったよね? 内部文字コードはバイナリじゃなかったの?
改行と認識されるのは、キャリッジリターン+ラインフィードかラインフィードです。
識別子
例:
foobar ruby_is_simple
Rubyの識別子は英文字またはアンダースコア('')から始まり、英文字、アンダースコア('')または数字からなります。識別子の長さに制限はありません。
つまり正規表現で言うと以下ってことかな? ほかのプログラミング言語と同じかな?
[_a-zA-Z][_a-zA-Z0-9]+
でもさ、メソッドの末尾に!
や?
が付与できるよね? あれは名前だって書いてあったんだけど。メソッドの末尾だけは例外ってこと? 一言も書いてないし。
コメント
例:
# this is a comment line
埋め込みドキュメント
例:
=begin the everything between a line beginning with `=begin' and that with `=end' will be skipped by the interpreter. =end
Rubyのソースコードにドキュメントを埋め込む事ができます。文が始まる部分の行頭の=beginから、=endで始まる行までが埋め込みドキュメントです。Ruby インタプリタとしては内容に縛りはかけませんが、通常は RD 形式でドキュメントを埋め込むことを期待しています。
RD形式というのがわからないが、rdoc
でHTMLに置換できる書式のことをそういうのだろう。これまでの公式ドキュメントにそんなことは書いていなかった気がするが。こんなところで初登場? rdoc
コマンド説明のときに出して欲しかった。
あと、rdoc
はちゃんと#
コメントも同様に解析する。むしろスタイルガイドでは#
コメントを推奨している。
予約語
予約語は以下のものです。
BEGIN class ensure nil self when END def false not super while alias defined? for or then yield and do if redo true __LINE__ begin else in rescue undef __FILE__ break elsif module retry unless __ENCODING__ case end next return until
これが欲しかった。知らないのもチラホラある。undef
,super
,alias
,defined?
。やはりasync
やawait
はない。きっとそのうち標準実装されると信じているが。
予約語はクラス名、変数名などに用いることはできません。ただし接頭辞$, @、@@が先頭についたものは予約語とは見なされません。また、def のあとやメソッド呼び出しのピリオドのあとなどメソッド名であるとはっきり分かる場所ではメソッド名として用いることができます。
グローバル変数、インスタンス変数、クラス変数は接頭辞があるから名前重複を回避できる。メソッドも定義や呼出はほぼ回避できる。でも上記の言い方だと、メソッド名であるとはっきりわからない場所があって、そこでは名前重複してしまうと読み取れる。まったく思いつかないので実際に重複するコード例が欲しかった。
また、番号指定パラメータは変数名、def で定義するメソッド名に用いることはできません。
_1 _2 _3 _4 _5 _6 _7 _8 _9
番号指定パラメータ
番号指定パラメータ
ってなんだよ。まーた説明がないのでググった。
Ruby2.7で導入されたらしい。ブロックの仮引数を連番名で受け取れる。
['A','B','C'].each {|v| p v}
['A','B','C'].each {p _1}
['A','B','C'].each_with_index {|v,i| p "#{i}:#{v}"}
['A','B','C'].each_with_index {p "#{_2}:#{_1}"}
- 割り当てられなければ
nil
- 使用できる連番は
1
〜9
の8個 _10
のようにするとNameError
_1
のようなローカル変数があればwarning
_1
のようなローカル変数がブロック外の上で宣言されていたらローカル変数を参照してしまう_1
のようなメソッドがあると番号指定パラメータが参照される- ネストしたブロック内では1階層でしか使えない
- 従来の仮引数と混在させるなら仮引数名を番号指定パラメータにせねばならない
使いどころ
以下の条件を満たしているときだけに限って使うべきだと思う。
- 仮引数がひとつである
- 仮引数の内容が何であるかメソッド名からはっきりとわかる
ちゃんと考えないと可読性がさがるから。
['A','B','C'].each {p _1}
['A','B','C'].each_with_index {p "#{_2}:#{_1}"}
1つ目はまだいい。each
とうメソッド名からして要素がひとつずつ取得されることが想像できる。だから仮引数の内容は要素だと想像できる。
2つ目は混乱する。_1
は要素なのか、それともインデックスなのか。位置引数は名前がないためわからない。メソッド名からどの位置に何の値がくるかわかるものなんてそうそうないと思う。つまり、仮引数が2つ以上あるときは番号指定パラメータを使わないほうがいい。
仮引数が1つのときだけ番号指定パラメータを使うべき。だとしたら_
で仮引数を参照できるようにして欲しかった。でも以下のように_
にしてしまうとエラーになった。
['A','B','C'].each {p _} # undefined local variable or method `_' for main:Object (NameError)
以下のようにすれば_
を仮引数として使えるが、それなら意味のわかりそうな文字を使ったほうがいい。むりやり_
を仮引数名にしてもいいことはない。
['A','B','C'].each {|_| p _}
Rubyでは_
だと使わない捨てるべき変数であるかのように見えてしまう。パターンマッチではそういった意味で使われることがあるから。
タイプ数を減らせるので番号指定パラメータを使うことには価値がある。けれど可読性が犠牲になるのは間違いない。トレードオフ。
['A','B','C'].each {p _1}
['A','B','C'].each {|_| p _}
['A','B','C'].each {|v| p v}
所感
相変わらず説明不足がすごい。
対象環境
- Raspbierry pi 4 Model B
- Raspberry Pi OS buster 10.0 2020-08-20 ※
- bash 5.0.3(1)-release
- Ruby 3.0.2
$ uname -a Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux