LoginSignup
26
22

More than 5 years have passed since last update.

(これから覚えるPG向け)Rubyでびっくりしないためのざっくり解説

Last updated at Posted at 2016-01-22

Rubyでびっくりしないために

別な言語を覚える時のハードルの1つに、その言語の記法だったり慣用だったりがある。
Rubyのそういった特徴の私的メモ。

基本

言語の特徴

  • スクリプト言語でオブジェクト指向言語。
    • ほぼ全てがオブジェクトで構成されている。
  • イテレーション処理とクロージャ処理に長けていて、データの集合をDBと組み合わせて扱うのが得意。
    • 現代のWeb系サービス向け(Railsの影響が大きいかな)。
  • 書き方は結構ゆるめで、敷居が低い。
    • ブロックでカッコを使わないなど、多少癖はある。
  • 全てがオブジェクトなので型はないと思って良い。動的型付け言語
  • Ruby といえば、 Ruby on Rails というくらい、Railsとは切っても切り離せない関係。
    • なので、初心者がRailsから入ると、あるクラスやメソッドが、Rails由来なのか言語標準なのかを判断するのに苦労はする。(気にしないでググる、って手もある)
  • irbという、強力なコマンドラインインタプリタがある。
  • モジュールは豊富。導入も簡単。(Bundlerという仕組みが用意されている)
  • ドキュメントはネット上にも豊富。
    • だけどなぜか探しにくい。いろいろな人が色々な所に書いていて、どれが最新で正しいか判断しにくい。GoogleやQiitaで上位にランクしている記事が数年前のバージョンを対象とした古い記事だったりとか。Rubyに限らないけど、人口に膾炙されているだけに、そういう傾向が目立つ気がする。
    • 「設定より規約」の影響なのか、「当然知っているだろうから(知っている人が対象だから)説明しないよ。あえてね」っぽいのが多い印象。
    • なので、場合によってはソースを見た方が早い、ってこともある。

文法

C由来の言語のいいところを取りつつ、nil;を使わない、制御構造も{}の代わりにdo ~ endなど、独自の設計思想がある。逆に言えば、;{}で区切ったり囲ったりする文法に馴染んだ人には、慣れるまで少し時間が必要かも。

  • JavaやJavascriptのNULLにあたるものは、nil(ニル)。LISPからの影響かしらん。
  • nilfalse以外は全てtrue0true""true
    • なお、undefined 値はない。
  • 変数宣言は要らない。
  • 全ての変数はオブジェクトへの参照。そのため関数への値渡しもない。
  • 行末のセミコロンは要らない。明示的に;を入れて式を区切ることは可能。
    • セミコロンが要らないために、逆に¥で明示的に行を継続させる方法も用意されている。例えば、メソッドの引数を改行後に与えてしまうとRubyは引数が無いと判断してしまう。こういう場合、()で囲むか、¥を使う。
      somearray.push        # <- ()で囲むか、`¥`で行が継続していることの明示が必要
        new_array_member
  • :任意の文字列シンボルを表す。ラベルのようなもの。内部的に番号管理されるので、速度面やメモリ面での利点がある。なによりコードの可読性や文脈が向上するのがありがたい。
  • コメントはPerlと同様##以降がコメントとみなされる。C/C++、Javascriptのような複数行コメント /* */ はない。
    • ブロックコメントがあり、=begin ~ =end。"begin"は省略できない。
  • #coding: utf-8として(マジックコメント)、エンコードを指定して処理系に伝える。ソースコードの1行目ないしは2行目(シェバンがある場合)に書く。

  • 全てが式。ifなども式。式なので結果が発生する。
    • ifのような他言語の制御文にあたるものを式として意識する必要は、普段は持たなくて良い。
      • メソッドの返り値だけ気をつける。
    • メソッドの返り値はreturnで明示的に返すこともできるが、Perlのように、最後の演算結果が暗黙的に返り値となる。
  • 代入式で一度に複数個への代入が可能。(a,b = 1,2
  • 三項演算子(A ? X : Y)は、それぞれの記号の前後は必ずスペースが必要。演算の優先順位的に誤った解釈が発生しうるから。
    • 言語仕様としてメソッド名に?を与えられるので、A?はメソッド名に、また X:はハッシュ中のシンボルを使ったキーにRubyが解釈してしまう。
  • 多方向分岐では、switchではなく、Bashとおなじcaseを使う。
    • ifcase も、ブロックを閉じるのは、fiesac ではなく、全て end
    • なので、endばかり並んで可読性が悪くなるようなネストにならないよう、注意。
  • 繰り返し制御文として、for, while, until がある。
    • forはまず利用しないだろう。Enumerable なオブジェクトであれば、メソッドで繰り返し処理(eachなど)が豊富に用意されているから。
  • "Format String" % values" で、sprintf("Format String",values)シンタックスシュガーになる
    • なので、Rubyistはsprintfは使わないそうな。
  • 変数展開可能な文字列中で、#{}でくくって、式を囲める。

変数・定数

  • 宣言されたクラスやモジュールなどは、すべて定数として管理されている。
  • 定数は大文字で始まる。全て大文字である必要は、ない。
  • グローバル変数は頭に$をつける。
  • インスタンス変数には頭に@をつける。クラス変数には頭に@@をつける。
  • ::は、定数参照時の演算子。Hoge::Fuga::Piyopiyoのように使う。なお、::Hogehoge でトップレベルの定数を指す。

計算、演算

  • ++--演算子はない。
  • 演算子は、その実、メソッドである。(=以外の演算子はメソッドのようだ)
  • 何も考えずに1/210/3 と演算しても、結果はそれぞれ03になる。Integerオブジェクトの/メソッドがそうしているから。結果をFloatにする場合は、除数か被除数をFloatにする。
  • .....範囲演算子。フリップフロップも使える。
  • Perl 同様、and, or, notといった、優先度の低い論理演算子が用意されている。

配列、ハッシュ

  • 配列ハッシュは、それぞれArray.new()Hash.new()で新しい空の要素を作れるが、次のような記法で、最初から値が入ったものを作れる。
# 配列の初期化
a0 = []                                         # 空の配列
a1 = ["zero","uno","dos","tres"]

# ハッシュの初期化
h0 = {}                                         # 空のハッシュ
h1 = {"alpha"=>1, "bravo"=>2 }                  # key が文字列
h2 = { :first => "alpha", :second => "bravo" }  # key にシンボルを使用する方法1
h3 = { third: "nagashima", forth: "delta"    }  # key にシンボルを使用する方法2

配列

  • 配列の参照は、[]を使う。
  • *は、配列の内容を展開する。
irb(main):001:0> d=[1,2,3,4]
=> [1, 2, 3, 4]
irb(main):002:0> p d
[1, 2, 3, 4]
=> [1, 2, 3, 4]
irb(main):003:0> p *d
1
2
3
4
=> [1, 2, 3, 4]
  • また、*をメソッド側の仮引数につけると、この場合は配列化をする(可変長引数などを使う場合に便利)。
irb(main):001:0> def fuga(a, *b)
irb(main):002:1> p a; p b
irb(main):003:1> end
=> nil
irb(main):004:0> fuga(1,2,3,4)
1
[2, 3, 4]
=> [2, 3, 4]
irb(main):005:0> 

ハッシュ

クラス/モジュール/メソッド/ブロック

クラス

  • クラスの継承は単一継承で、複数クラスからの多重継承はできない(モジュールで対応)。
  • クラスやモジュールはネストできる。
    • ネストは、名前空間を共有する以外の意味はなく、継承などが生まれるわけではない。
    • クラスとモジュールで、名前空間を共有できる。
  • クラス名は定数として管理されるため、大文字で始まらないと処理系に怒られる。また、キャメライズせよ
  • クラスにエイリアス(alias)が設定できる。
  • クラス定義直下のスコープで実行文を置ける。またそれらは逐次的に実行される。
    • クラス定数などを置いたり、attr_accessorアクセサを定義する)など、ユーティリティなメソッド呼び出し文を置いたりする。
  • Klass#initializeメソッドが初期化関数で、Klass.newメソッドがコールされるとこの関数が呼び出される。
    • Klassに関しては後述「その他」を参照。
  • メソッド内でsuperを呼び出して、スーパークラス(親クラス)のメソッドを呼び出せる。親クラスそのものではなくてメソッドのコードなので注意。
  • private より後ろのメソッド定義は、Privateメソッドになる。

モジュール

  • モジュールは、インスタンス化できない、機能(部品)を提供としたクラス、といったところ。
  • モジュール名も大文字で始まらないと怒られる。同様にキャメライズせよ。
  • クラスは、複数のモジュールを取り込むことができる。(Mix-in)
  • ざっと言えば、class内で includeでインスタンスメソッドとして、extendでクラスメソッドとして、任意のモジュールのメソッドを取り込める(参考)。
  • モジュール内でクラスを定義している例があるが、モジュールで名前空間作っているということ。
module Hoge::Fuga
  class Piyopiyo                # Hoge::Fuga::Piyopiyo

メソッド

  • メソッド呼び出し時に、引数を()で括らなくてもよい。
    • ただし、引数の渡し方によっては、()で括らないとうまく解釈されない場合があるので、場合に応じてくくる。
  • メソッドの最後の演算結果(評価)がメソッドの返り値となる。
    • return で明示的に返すことも可能。
  • メソッド名の末尾に!をつけたものは、破壊的なもの、取り扱いに注意が必要なメソッド、という慣用がある。
  • メソッド名の末尾に?をつけたものは、Boolean値を返すもの、という慣用がある。
  • 引数にデフォルト値を指定できる。
  • ブロックを渡す場合は、呼び出し部分の直後に{}do ~ endで定義することで渡すことが可能。
    • このブロック部分は、メソッド側から、yieldによって呼ぶことができる。
def product(a,b)
  yield a*b
end

product(3,4) do |r|
  p "Result %d" % r
end  

正規表現

その他

  • PerlのPod同様、Rdocがある
  • 幾つかコーディング規約が散見できる(ex. Cookpad, GitHub 有志翻訳版、とか)が、ざっくり言えば タブは半角空白2文字 がマスト。
  • ドキュメントやコードのの慣用表現がいくつかある。
    • 式の結果を表すコメント部分は、# => xxx のように表す。
    • サンプルコードや実際のコードで、クラスそのものを表すのに、classだと読み手が混乱してしまったり、そもそも予約語で使えなかったりするので、Klass,klassという表記が使われる。(他には、aliazとか)
    • あるメソッドが呼ばれる時、そのメソッドのオブジェクトそのものをさして レシーバー(reciever)と称す。
    • クラスメソッドは Klass.method で表す。一方、インスタンスメソッドは Klass#method で表す。コード上はどちらもreciever.methodで呼び出す。

(おわり)

26
22
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
22