LoginSignup
0
0

More than 1 year has passed since last update.

Ruby備忘録、Rubyの特に分かりにくかったところ、メソッド呼び出しのカッコ省略等

Posted at

この記事について

ruby学習中のため、その備忘録です。railsの話はほぼ出てきません。
rubyを学習していて特に分かりにくかったところなどを中心に書いています。

他言語からRubyへ

PHPやPython等他言語を使ってる人に対しては、Ruby公式サイトにそれぞれの言語とRubyの違いについて書かれたページがあります。

他言語からのRuby入門

メソッド呼び出しのカッコ省略、return省略

引数無しのメソッド呼び出しのカッコ省略

rubyではメソッド呼び出しの際カッコを省略することができます。

def hello
  puts 'hello!'
end

hello() # hello!
hello   # hello!

引数ありのメソッド呼び出しのカッコ省略

引数がある時もカッコの省略ができます。
引数が複数ある場合は,で繋ぎます。

def hello_name(name)
  puts "hello #{name}!"
end

hello_name('suzuki') # hello suzuki!
hello_name 'suzuki'  # hello suzuki!

def hello_name2(name1, name2)
  puts "hello #{name1}, #{name2}!"
end

hello_name2('suzuki', 'sato') # hello suzuki, sato!
hello_name2 'suzuki', 'sato'  # hello suzuki, sato!

returnの省略

また、メソッド内の最終行で戻り値を返す場合はreturnを省略できます。

def plus10(n)
  n + 10 # return n + 10
end

def double(n)
  n * 2
end

puts plus10 3        # 13
puts double plus10 3 # 26 ← puts double( plus10(3) )

メソッド定義のカッコ省略

メソッド定義でもカッコが省略できます。
引数無しの場合だけでなく、引数ありの場合でも省略できるみたいです。
ただ、実際に引数ありのメソッド定義でカッコを省略して書いている人は少ないように感じました。

def bye_name name
  puts "bye #{name}!!"
end

def bye_name2 name1, name2
  puts "bye #{name1}, #{name2}!!"
end

bye_name 'suzuki'          # bye suzuki!!
bye_name2 'suzuki', 'sato' # bye suzuki, sato!!

メソッドの別名

メソッドの別名を付ける際はaliasalias_methodを使用します。
alias_methodclassの外では使えません。

def method1
  puts 'method!'
end

# これはメソッドの別名を付けてる訳ではなく、戻り値を代入している
not_method = method1 # method!

method1 # method!
not_method # 何も出力されない
puts not_method # nil ← putsの戻り地はnil

alias :method2 :method1
method2 # method!

メソッドのオプション引数、ハッシュの波カッコ省略

オプション引数

引数にデフォルト値を設定してオプション引数とすることで、メソッド呼び出し時に省略できるようになります。

def pow(n, m=2)
  n ** m # nのm乗
end

puts pow 3    #  9
puts pow 3, 4 # 81

ハッシュの波カッコ省略

引数の最後がハッシュの場合は{}を省略できる

def filter_high_persons(min, persons)
  persons.filter {|k,v| v > min}
end

puts filter_high_persons(170, {suzuki: 175, sato: 165, tanaka: 180}) # {:suzuki=>175, :tanaka=>180}
puts filter_high_persons 170, suzuki: 175, sato: 165, tanaka: 180    # {:suzuki=>175, :tanaka=>180}

railsでも基本(){}を省略して書かれることが多いです。
例えばルーティングのところは省略せずに書くと以下のようになります。

get 'test1', to: 'tests#test1', as: 'test_action1'
get('test1', {to: 'tests#test1', as: 'test_action1'})

その他

命名

識別子に!?を使えます。

慣習的に戻り値が真偽値のメソッドには名前の最後に?を付けることが多く、iscan等はあまり使いません。
例えばis_successではなく、success?と命名します。

慣習的に破壊的メソッドには名前の最後に!を付けることが多いです。
例えばArraysortメソッドは非破壊的ソートを行い、sort!メソッドは破壊的ソートを行います。
メソッド名に!が付いていなければ絶対に破壊的メソッドではない、という訳ではありません。

また、処理失敗時にfalse等を返すメソッドには!を付けず、処理失敗時に例外を発生させるメソッドには!を付けるといった命名もされています。
例えばRailssaveは成功したかどうか真偽値を返しますが、save!メソッドは失敗時に例外を発生させます。

標準出力

標準出力するメソッドにputs, print, pがあり、それぞれ出力の仕方が少しずつ異なっています。
主に改行の入り方が違うようです。

メソッド 引数毎の改行 配列の要素間の改行 nil 補足
puts 入る 入る 空行を出力 配列の[]の表示なし
p 入る 入らない nilと出力
print 入らない 入らない 何も出力されない スペースも入らない
puts 'suzuki', 'sato'        # suzuki(改行)sato(改行)
puts ['suzuki', 'sato']      # suzuki(改行)sato(改行)
puts name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行)
puts nil                     # (空行)

p 'suzuki', 'sato'        # "suzuki"(改行)"sato"(改行)
p ['suzuki', 'sato']      # ["suzuki", "sato"](改行)
p name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行)
p nil                     # nil

print 'suzuki', 'sato'        # suzukisato
print ['suzuki', 'sato']      # ["suzuki", "sato"]
print name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}
print nil                     # 何も出力されない

式と文に違いはない

式と文に違いはなく、全ては値をもつ。

x = 10
res = if 0 <= x
        '0以上'
      else
        '0未満'
      end
puts res # 0以上

シンボル

シンボルは単なる軽量文字列ではない。
シンボルはオブジェクトの実体を指すもので、同じシンボルであればメモリ上の同じ場所を参照する。

puts :test.object_id == :test.object_id   # true  ← メモリ上の全く同じ場所にある
puts 'test'.object_id == 'test'.object_id # false ← 値が同じだけでメモリ上の別々の場所にある

型、インスタンスの調べ方

型・クラスはclassメソッドで調べられます。
インスタンスが特定のクラスのものか調べる際はkind_of?instance_ofメソッドを用います。
kind_of?はそのクラスの直接のインスタンスか、そのクラスを継承しているクラスのインスタンスであればtrueとなります。
instance_of?はそのクラスの直接のインスタンスの時のみtrueとなります。

puts Time.class  # Class
puts Time.kind_of?(Class) # true
puts Time.kind_of?(Time)  # false

time = Time.now

puts time.class  # Time
puts time.kind_of?(Class) # false
puts time.kind_of?(Time)  # true

class MyTime < Time
end
my_time = MyTime.now

puts MyTime.class  # Class
puts my_time.class # MyTime
puts my_time.kind_of?(Time)       # true   ← MyTimeはTimeを継承しているため
puts my_time.kind_of?(MyTime)     # true
puts my_time.instance_of?(Time)   # false  ← MyTimeのインスタンスであってTimeのインスタンスではない
puts my_time.instance_of?(MyTime) # true

nil (null)

&.演算子

nilに対して&.演算子を用いるとundefined methodエラーを回避できます。
nilが入る可能性がある変数のメソッドを直接呼び出す書き方をしているとnilになった時にエラーが出てしまう為、そういった場合に&.演算子を使うことがあります。

class Test
  def hello
    'hello!'
  end
end

test = Test.new
p test.hello  # "hello!"

test = nil
# p test.hello # undefined method `hello' for nil:NilClass

if test # nilはfalse扱い
  p test.hello # ここは通らないのでエラーとならない
else
  p 'bye!' # bye!
end

# `&.`演算子や`||`演算子を使えば条件分岐を減らすことができる時もある
p test&.hello           # nil ← エラーとならずにnilが返される
p test&.hello || 'bye!' # "bye!"

&.演算子を使用しても、nilではないものに対して存在しないメソッドを呼び出した場合はエラーとなる

now = Time.now
# p now&.hello # undefined method `hello' for ~:Time

tryメソッド

railsのtryメソッドを用いると、nilではないものに対して存在しないメソッドを呼び出した場合でもエラーとなりません。

# rails上でしか動きません
now = Time.now
p now.try(:hello)

変数が定義されているか調べる方法

変数が定義されているか確認する際はdefined?メソッドを用います、未定義であればnilを返します。

a = 10
p defined?(a) # local-variable
p defined?(b) # nil

可変長引数、展開

可変長引数

引数名の前に*を付けることで引数の個数を可変にすることができます。
渡された引数は配列となって可変長引数に渡されます。

def variable_arg(*args)
  p args.class # Array
  p args       # [1, 2, 3]
end

variable_arg 1, 2, 3
def sum(*nums)
  nums.sum
end

puts sum 1, 2    # 3
puts sum 1, 2, 3 # 6

通常の引数と可変長引数を組み合わせることもできます。

def name_sum(name, *points)
  "#{name}さんの合計点は#{points.sum}点です"
end

puts name_sum 'suzuki', 10, 20, 30 # suzukiさんの合計点は60点です

展開

逆にメソッド呼び出し時の引数名の前に*を付けると配列を展開してメソッドに渡すことができます。

def five_avg(a, b, c, d, e)
  (a + b + c + d + e) / 5
end

def avg(*nums)
  nums.sum / nums.length
end

points = [10, 20, 30, 40, 55]
puts five_avg *points # 31
puts avg *points      # 31

参考

0
0
0

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
0
0