閲覧ありがとうございます!現在大学3年生でRubyを学習しているものです。今回はRuby3.3のリファレンスマニュアル (https://docs.ruby-lang.org/ja/3.3/doc/index.html) を読んで個人的に、疑問に思ったことをまとめてみました。なにか間違いあればコメントいただけると嬉しいです!まだ未完成ですがこれからも追記していく予定です。※修正 2025/8/30 コメントでご教授いただきましたことを参考にしています。
はじめに
Rubyとは、まつもとゆきひろ氏によって日本で作成された言語。「エンジニアが楽しくコーディングできるように」という理念のもと作られた。インタプリタ言語であり、pythonなどと同じように一行ずつコードを実行していく。 スクリプトを読み込んで構文解釈していく。(多分遅い?)変数や定数の型を明示しなくてもよく、比較的シンプルで自由なコーディングができると考えられる。
字句構造
ほとんどpythonと同じ。しかしながら、少し違った点がある。
- コメントアウト
- pythonでは複数行コメントアウトするためには「'」や「"」を用いていたが次のように記述する。
=begin コメント =end
プログラムと式
これも基本は他の言語と同様に考えればよい。
-
引数について
-
Rubyでは次のように定義したメソッドに引数を渡す際に()をつけなくてもよいという特徴がある。
def foo(x) puts x end foo 2しかしながら、これでは次のような場合エラーとなってしまう。
def foo(x) puts x end foo true and false理由としては「(foo true) and false」というようになってしまっていることによる。結局の所いつもどおり引数を与えるときはグルーピングを行ったほうが良いと言える。
-
プログラム終了について
- 実行ファイルの最後だけではなく、「__END__」のみの行でも終了できる。
変数と定数
-
変数について
-
適応されるスコープやアクセス範囲によって名前が決まっている。下に行くほど範囲が広い。
a #ローカル変数 :ブロックやモジュールの中のみがスコープ範囲 @a #インスタンス変数 :オブジェクトごとに別々。オブジェクト内では同じものが使える。 @@a #クラス変数 :クラス内で共有。オブジェクトごとに別々にはならない。 $a #グローバル変数 :プログラムのどこからでも参照できるインスタンス変数とクラス変数で詰まったので、より具体的に記述する。
インスタンス変数を用いたコード例を示す。class User def set_name(name) @name = name end def get_name @name end end alice = User.new bob = User.new alice.set_name("Alice") puts alice.get_name # => "Alice" puts bob.get_name # => nilもし
@nameが@@nameであるならputs bob.get_name # => "Alice"となる。一度クラス変数に値を与えておけば、その後のオブジェクト全てに値が共有される。
-
スレッドとは?
- メモリ空間を共有して同時実行できる制御の流れのことらしい。並列処理ができる。 定数
- 大文字で始まる識別子。ただし、大文字で始まるからといって必ずしも定数ではない。(メソッドの可能性あり)定義されていないものはNameErrorになる。クラスやモジュールにおいて、親で定数を定義していれば子から参照可能。クラスは子<親で継承できる。トップレベルで定義された定数はクラスオブジェクトとなる。(決めた定数名の定数にオブジェクトが代入される) 参照
- ::から始まるものは一番外側のスコープを参照する。一方で::を含んでいないときは現在の場所から外に向かって探索する。もしなかったら、スーパークラスを順番に探索。※モジュールM1:M2のようになっているときはM2のみを見る。モジュールは遡らず、Rubyの定数探索は「継承優先」と考えられる。
リテラル
だいたい他の言語と似たようなもの。
-
文字列
- 「"」や「'」で囲うと文字列として認識される。しかしながら、どちらも同じというわけではなく、「"」ではバックスラッシュ記法と式展開が有効になるため積極的に使っていきたい。また、?+1文字 でも文字列として認識される。 正規表現リテラル
-
文字の検索などを行うときに役に立つ。「正規表現リテラルはその中に式展開を含まなければ、何度評価されても同一の正規表現オブジェクトを返します。」というところが良くわからなかったので、式展開ありのoオプションを元に考えたい。oオプションは同一リテラルであった上でどう評価するかに関わっている。そのため、
name = "Ruby" re1 = /#{name}/o name = "Python" re2 = /#{name}/o p re1 # => /Ruby/ p re2 # => /Python/ p re1.equal?(re2) # => trueこのコードを実行すると、re1とre2は異なる値となりoオプションは意味がなくなる。そこで、次のコードを考えた。
# o あり name = "Ruby" 3.times do |i| r = /#{name}/o puts r.object_id end # => 60 # => 60 # => 60 # o なし 3.times do |i| r = /#{name}/ puts r.object_id end # => 80 # => 100 # => 120このように一度評価されたら、それ以降も同じ/Ruby/を使い続けていることがわかる。式展開がなければ(oオプションでない)nameに値を代入していく感じではなくなり、同一の正規表現オブジェクトを返すということになる。つまり、正規表現リテラルはそのオプションに関わらず同一の正規オブジェクトを返すとわかる。
シンボル
- 文字列では生成される度に新しいオブジェクトが作られるが、シンボルは文字列と違い、生成された文字列が同じならばそれぞれが同じオブジェクトとなる。(プログラムにひとつ作られる)以前までは、永久にメモリに残る仕様であったためGC(garbage collection)不可能であった。しかし現在はGC可能となっている。
演算子
-
Module#attrって何?
-
インスタンス変数への読み書きを行うメソッドを作るショートカットらしい。読み取りはTrue前提でTrue/Falseで書き込みを作るかどうか決めれる。
こういう本質的には同じだけどシンプルにしたものを構文糖という。※構文糖については詳しくはコメントいただいたscivolaさんを参照
sedやawkって何?
- テキスト処理のツール。sedはテキストの置換や削除、抽出 に使い、awkは行単位で列ごとの操作を可能にする。条件式として範囲式を用いる場合、sedやawk由来の特殊な条件式として振る舞う。状態を保持したり、リセットしたりするフリップフロップ回路と似ている。
制御構造
Rubyは「式」
-
パターンマッチ構文って何?
-
オブジェクトの構造を形で条件分岐する。例えば次のようなもので、ネストが深いときに無駄を減らせる。
obj = [1, 2] case obj in [a, b] なんかのコード end
-
ENDブロック
- ENDブロックを複数登録すると、登録したときと逆の順番で実行されるのはなぜなのか。その理由としてはRuby は内部的に END ブロックをスタックに登録しているため、後から入れたものが先に取り出される仕組みになっていると考えられる。
まだわかっていないこと
詳しい組み込み変数の役割
基本的な用語
| 用語 | 説明 |
|---|---|
| リテラル | ソースコード中に記述される固定値(10や"Hello"など) |
| スーパークラス | 親クラスのこと |
| メソッド |
Classの中でオブジェクトに結びついたもの |
| クラス | 設計図のようなものこれをもとにオブジェクト作成 |
| モジュール | メソッドやクラスの集まり |
| オブジェクト | クラスから作られるもの ※Rubyでは数値や配列、定数はすべてオブジェクト |
| トップレベル | 一番外側にある領域 |
| スクリプトエンコーディング | ソースコードで使われている記法(UTF-8やShift_JISなど) |