【Rubyすべてがオブジェクト】変数と真偽値/論理演算子/コメント

本記事は、Rubyの基礎文法である、
変数や真偽値、論理演算子に触れると同時に、
「すべてがオブジェクト」というRubyの特徴的な思想についても
解説します。

この思想は、Rubyの文法の根幹になっているのと、
Rubyの面白い部分でもあるので、
ぜひともご参考ください。

文章ではなく、動画で視聴したいという方は、
下記の動画を御覧ください。

すべてがオブジェクトとは?

Rubyの代表的な特徴として、
「すべてがオブジェクト」というものがあります。

どういうこと?って感じだと思いますが、
割と文字通りの意味です。

順番に解説していきます。

そもそもオブジェクト指向言語におけるオブジェクトは、
クラス(設計書)の具象化したもののような形で、
例えばCarクラスのオブジェクトは、
実際の車で、走ったり、ブレーキーで止まったりといった振る舞い(メソッド)を
持つといったイメージがありますよね。
(オブジェクト指向について、ちょっと怪しいという人は、
こちらの記事で詳しく解説しているのでご参考ください。)

そのため、他の言語では、
このクラス(設計書)とオブジェクトは別物のはずですが、
Rubyでは少し毛色が変わって、
このクラスもオブジェクトにあたります。
(別物であることには変わりませんが、
クラス自体が親クラスのインスタンスという側面を持っているという感じです)

例えば、nilオブジェクトから親クラスを追ってみようと思います。
以下は、irbというRubyで使えるサンドバッグ環境です(irbコマンドで起動できます)

irb(main):010:0> nil.class
=> NilClass
irb(main):011:0> NilClass.superclass
=> Object
irb(main):012:0> Object.superclass
=> BasicObject
irb(main):013:0> BasicObject.superclass
=> nil

上記のclassというのは、
メソッドで、呼び出し元オブジェクトのクラスを返します。

superclassメソッドは、親(継承元)クラスを返します。

それで、上記の返り値を見てみると、
最終的に、BasicObjectを継承していることがわかります。

つまり、文字列とか数値とか、nilといったものは、
BasicObjectを祖先にに持っているということです。
(BasicObjectの親クラスは存在しないですね)

「すべてがオブジェクト」というのは、
このことを指しています。

つまり、すべてBasicObjectの子孫ということですね。

さてそんなオブジェクトですが、
オブジェクトは、振る舞い(メソッド)を持っているので、
値に対してメソッドを呼び出すことができます。

irb(main):014:0> nil.to_s
=> ""
irb(main):015:0> ''.to_s
=> ""
irb(main):016:0> 2.to_s
=> "2"

nilも''も2もオブジェクトなので、
to_sというメソッドを呼び出すことができています。

例えば、Pythonとかだと、

int(2)
str(2)

のように、メソッドの引数にオブジェクトなどを渡していますが、
Rubyの場合、オブジェクトに対して、メソッドを呼び出すというのが特徴的ですね。

これは、JavaScriptのラッパーオブジェクトに少し似ている特徴ですね。
JavaScriptのラッパーオブジェクトについては、
下記の記事で解説しています。

[st-card myclass="st-no-shadow" id="23" label="参考" pc_height="" name="" bgcolor="#cccccc" color="#ffffff" webicon="st-svg-file-text-o" readmore="on" thumbnail="on" type="text"]

すべてがオブジェクトとは、
何かというと、上記のような特徴のことです。

変数

変数とは?何って言う人は、
こちらの記事で変数そのものについて、
解説しているので良ければ参考にしてください

さてRubyでの変数定義は、
非常にシンプルな記法で、

greet = 'hello world'

で足ります。

いれるだけかーいっていうぐらいシンプルな文法ですね(笑)

TypeScriptみたいに、letとかconstみたいなものをつける必要はありません

ただ、Rubyの変数名は、スネークケースで書くのが、
慣習というかコーディング規約で定められています。

https://www.ruby.or.jp/ja/tech/development/ruby/050_coding_rule.html
https://shugo.net/ruby-codeconv/codeconv.html

なので、基本的にはスネークケースで書きます。
ちなみに、スネークケース以外で書いてもエラーにはなりません。

Rubyのちょっと面倒くさいのが、
スネークケース以外の変数も宣言できてしまうので、
コーディング規約でNGとされている記法も、
押し通すことが可能ということです。

irb(main):020:0> greetGreet = 'Hello'
=> "Hello"

これはすなわち、プロジェクトで、
厳格に記法とかを統一しないと、
コードが荒れやすいともいえますね。

余談ですが、私が以前経験したPJのRubyコードは、
すべての変数がキャメルケースで書かれていて絶望した経験があります。
(これは、あえてそうしているとかではなく、フロントがキャメルケースだから、
無思考でRubyもキャメルケースにしているだけでした。)

Rubyが一面、上級者向けといわれるのは、
こういう側面にあるかもしれませんね。

自由に書くことができる分、
基本的なコーディング規約とか
簡潔で依存性が小さいコードを書くように心がけないと、
簡単に負債化してしまうおそれがあります。

よく元々Java出身のRubyエンジニアが書くコードは綺麗と言われたりしますが、
これも、このあたりに関係しているかもしれないですね。

ちなみに、定数は、すべて大文字として定義します。

いちおう、警告は出ますが、
Rubyの定数は、再代入できるっちゃできてしまうので、
この辺もちょっと自由すぎる匂いがしますね...

なので、良いコードがどういうものか、
ある程度自分なりに仮説やインデックスがある人じゃないと、
コードをカオスにしてしまいやすいというのが、
Rubyが上級者向けと言われる所以ですかね。

式展開

文字列の中で、変数の値を展開したいときは、

irb(main):021:0> greet = 'hello'
=> "hello"
irb(main):022:0> puts "hello#{greet}"
hellohello
=> nil
irb(main):024:0> puts "hello#{greet.to_s}"
hellohello
=> nil

という風に、ダブルクオートで、
#{変数や式}という記法で式展開できます。

ちなみに、シングルクオートの場合は、
式展開されず、そのまま表示されます。

irb(main):025:0> puts 'hello#{greet}'
hello#{greet}
=> nil

式展開を使わなければ、
両者の挙動にさして違いはありません。

式展開というと、
変数の値を埋め込むために使う機能と思われがちですが、
下記のように計算することもできます。

irb(main):005:0> puts "#{1 + 2 }"
3
=> nil

真偽値

次にRubyにおける真偽値を紹介します。

真偽値とは、TrueとFalseというように、
真か偽を表すものですね。
(参考記事)

真偽値に変換した際、
何がTrueになり、
何がFalseになるかというのは、
プログラミング言語によって異なります。

多くのプログラミング言語では、
0などはfalseになることが多いですが、
Rubyにおいては、異なります。

以下詳細に解説していきます。

falseとnil以外真

Rubyの特徴的なものとして、
真偽値があります。

タイトルの通り、
Rubyの場合、偽(false)になるのは、
falseとnilだけです。

めちゃくちゃシンプルですよね。
なので、他のプログラミング言語だと
偽になりがちな、次の値もすべて真ということになります。

''
' '
0
'false'

0や空文字列は、
JavaScriptとかでは、falseに認定されるものですが、
Rubyにおいては、trueと認定されます。

以下、確認してみます。

irb(main):030:0> !!' '
=> true
irb(main):031:0> !!' '
=> true
irb(main):032:0> !!''
=> true
irb(main):033:0> !!0
=> true
irb(main):034:0> !!'false'
=> true
irb(main):035:0> !!false
=> false
irb(main):013:0> !!nil
=> false

上記の、「!」というのは、
要素の真偽値を反転させる演算子で、
例えば、aが真のときは、!aは偽となります。

「!!」というのは、反転させたものをもう一度反転させるので、
結果として、要素の真偽値を返します。

その要素の真偽値を返り値にしたいときは、
たまに使う記法かなと思います。

それを踏まえて、
上記のコードを見ると、
確かに、nilとfalse以外は、
trueになっているのが確認できますね。

論理演算子

上記で、少し出てきた、
「!」などですが、
これらは論理演算子というものです。

Rubyで頻繁に使うものとして、
&&や||、**!**などの論理演算子があります。

&&は、
例えば、条件1&& 条件2という風に使用し、
両方とも真なら、全体の式の評価も真を返すというものです。

これに対して、||は、
いずれか一方が真なら真で、両方偽で偽となります。

!は、否定で
真偽値を反転させます。

それぞれ、&&(and)、||(or)、!(not)のイメージに近いかなと思います。

irb(main):036:0> true && true
=> true
irb(main):037:0> true && false
=> false
irb(main):038:0> false || true
=> true
irb(main):039:0> false || false
=> false
irb(main):040:0> !true
=> false
irb(main):041:0> !false
=> true

これらの返り値には、
短絡評価というものが使われているので、
短絡評価評価について解説します。

短絡評価

上記の論理演算子ですが、
Rubyでよく使われるのが、
短絡評価というものがあります。

例えば次のようなコードです。

irb(main):049:1* class User
irb(main):050:1*   attr_reader :name, :email
irb(main):051:1*
irb(main):052:2*   def initialize(name, email)
irb(main):053:2*     @name = name
irb(main):054:2*     @email = email
irb(main):055:1*   end
irb(main):056:1*
irb(main):057:2*   def email_verified?
irb(main):059:2*     true
irb(main):060:1*   end
irb(main):061:0> end
=> :email_verified?
irb(main):062:0>
irb(main):063:0> user = User.new("John Doe", "[email protected]")
=> #<User:0x00007fcd178f6bc8 @email="[email protected]", @name="John Doe">
irb(main):064:0>
irb(main):065:1* if user && user.email_verified?
irb(main):066:1*   puts "ユーザーの名前は #{user.name} です。"
irb(main):067:1* else
irb(main):068:1*   puts "この操作はログイン後にのみ利用可能です。"
irb(main):069:0> end
ユーザーの名前は John Doe です。
=> nil
irb(main):070:0> user
=> #<User:0x00007fcd178f6bc8 @email="[email protected]", @name="John Doe">
irb(main):071:0> user && user.email_verified?
=> true
irb(main):072:0> user || user.email_verified?
=> #<User:0x00007fcd178f6bc8 @email="[email protected]", @name="John Doe">
irb(main):073:0> false && user
=> false
irb(main):074:0>

上記では、オブジェクト指向を使用しているので、
オブジェクト指向について確認したい場合は、
こちらの記事をご参考ください。

[st-card myclass="st-no-shadow" id="800" label="参考" pc_height="" name="" bgcolor="#cccccc" color="#ffffff" webicon="st-svg-file-text-o" readmore="on" thumbnail="on" type="text"]

上記のコードの着目ポイントですが、userという変数とuserがメソッドを持っているという状況を作りたかっただけなので、
その部分だけ着目してもらえれば大丈夫です。

重要なのは、

irb(main):070:0> user
=> #<User:0x00007fcd178f6bc8 @email="[email protected]", @name="John Doe">
irb(main):071:0> user && user.email_verified?
=> true
irb(main):072:0> user || user.email_verified?
=> #<User:0x00007fcd178f6bc8 @email="[email protected]", @name="John Doe">
irb(main):073:0> false && user
=> false
irb(main):074:0>

の部分で、||の場合、
どちらかがtrueになればいいので、
userの段階でtrueになることが確定し、
user.email_verified?が実行されず、
返り値がuserオブジェクトになっています。

これに対して、&&の場合、
どちらかがfalseになった段階で、
falseになることが確定するので、
最後のコードのようなfalse && userだと、
falseが最初に来た段階で、userが評価されず、
返り値がfalseになっています。

最初の、user && user.email_verified?は、
どちらもTrueになっているので、
最後のuser.email_verified?の返り値(true)が
返されます。

短絡評価とは、このように、式を評価する際に、最初が条件を満たすかを判定し、
条件を満たす場合にはその後の式を評価せずに処理を終了することです。

これを利用すると、Trueのときには、
変数代入をしたいが、Falseのときは、
したくないみたいな処理を書くこともできます。

短絡評価自体は、他のプログラミング言語にもある機能ですが、
Rubyでは割と頻出なので覚えておくといいでしょう。

コメント

コメントとは、他のプログラミング言語においても存在するもので、
該当のコードを実行させないように指定することができます。
Rubyにおけるコメントは、#を使います。

puts 'Hello world'
# この行は実行されません
# puts 'Hello world2'

コメントについては、シンプルですね。
どういうときにコメントを書くべきかというのは、
意外と難しい議論でして、人によって考え方がわかれます。

ただ、基本的に冗長なコメントは書くべきではないとされているので、
下記のようなコメントは推奨されないでしょう。

puts 'Hello world' # Hello worldと出力する
val = 100 # valに100を代入する
puts val #valを出力する

こういう逐一コメントは、
冗長なだけでなく、
仮にval変数をval_1とかに修正した場合、
コメントの方も修正する必要が出てくるため、
変更に弱くなります。

個人的には、コメントは書かないことが可能なら、
書かないほうが良いと思います。

というのも、理想としては、コメントではなく
コードに語らせることが一番だからです。

けれども、現実問題それが難しいこともあるので、
複雑なコードについては、大まかな処理の概要をコメントで残すという
ことは結構あります。

無思考でコメントを書きそうになってしまったときは、
コメントを書かずにわかりやすいコードを書く方法はないかと検討してみてもいいと思います。

ただ、正直コメントに対する考え方は、
チームによって異なるので、積極的にコメントを残そうという方針のチームもあります。

なので、最終的には、チーム次第なところもありますが、
コメントを書いてしまったら、コメントのメンテナンスと言う作業が増える時点で、
確実に変更に弱くなるので、書かないことが可能なら、書くべきではないということは確かです。