Top > Ruby > 関数

このページの概要

  • よく使うコードは「関数(厳密にはメソッド)」にして、どこからでも呼べるようにしましょう。
    • この項目では、メソッドのことをあえて「関数」と呼んでいます。C言語系の言語から入る人向け? (Basic な方ならサブルーチン?)
  • 動作確認環境 : Ruby 1.8.4

putsなども関数

  0
puts "hello"

なにげなく呼んでいる puts も、関数です。 Ruby の関数はコマンドラインでコマンドを実行するときのように、関数 オプション1 オプション2 と実行することもできますし、C言語のように 関数(オプション1,オプション2) と呼ぶこともできます。

関数を作ってみる

 関数は def というキーワードで作成できます。  関数は基本的に「最初は小文字のアルファベット、あとは英数字と _ (アンダースコア)」な名前をつけることができます。慣習的に、小文字のアルファベットと _ で命名するといいでしょう。

以下のコードは my_func という関数を定義しています。 そして、for の繰り返しの中から関数を呼んでいます。

  0
  1
  2
  3
  4
  5
  6
  7
#!/usr/bin/env ruby
def my_func
  puts "hello"
end
 
for i in 1..10
  my_func
end

さて、my_func を puts のように my_func("me") とオプションを付けられるでしょうか?おそらく、エラーになるはずです。それは、def の行にはどこにもオプションを使うという記述がないからで、my_func はオプション無しで呼ばれると定義されてしまっているためです。

my_func("me") で呼び出した結果。引数の数が違うと怒られてしまいます。
////
-:7:in `my_func': wrong number of arguments (1 for 0) (ArgumentError)
        from -:7
        from -:6

引数を受け取れるようにするには、以下のようにします。

  0
  1
  2
  3
  4
  5
  6
  7
#!/usr/bin/env ruby
def my_func(name)
  puts "hello, " + name.to_s
end
 
for i in 1..10
  my_func(i)
end

def の末尾に (name) がついていますが、これは引数を1個使いますよ、という意味なのです。 そして、繰り返しでは 1~10の数字を渡していて、これが my_func で 「hello, 1」のように結合されて表示されるようになっています。問題は、このやり方だと引数無しで呼ぶと、

wrong number of arguments (0 for 1) (ArgumentError)

こんな風に怒られてしまうことです。それを解決するには、デフォルト引数というものを使います。引数がなければ規定値はこの値にする、ということですね。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
#!/usr/bin/env ruby
def my_func(name="nanashi_san")
  puts "hello, " + name.to_s
end
 
my_func
 
for i in 1..10
  my_func(i)
end

引数無しで呼ばれた my_func は 「hello, nanashi_san」と表示したはずです。

複数の引数

引数を二つ以上準備するには、(引数1,引数2) のようにカンマで変数名を区切っていくだけです。

以下のサンプルはデフォルト引数を使っていますので、引数の数は 0 ~ 2 受け付けます。 最後の行は3つ引数をつけてありますが、引数の数のエラーになるためコメントアウトしてあります。

  0
  1
  2
  3
  4
  5
  6
  7
  8
#!/usr/bin/env ruby
def versus(east="east",west="west")
  puts east.to_s + " vs " + west.to_s
end
 
versus              #=> "east vs west"
versus("north")     #=> "north vs west"
versus("dog","cat") #=> "dog vs cat"
#versus("dog","cat","bird") #=> wrong number of arguments (3 for 2) (ArgumentError)

ローカル変数のスコープ、値のやりとり

def ~ end の間で使用している小文字からはじまる変数は、その関数専用(ローカル変数)です。 広域で使いたい変数は $ ではじまる変数で定義することで実現できます(グローバル変数)。

しかしながら、グローバル変数はアップデートの際に障害として立ちはだかることも多いので、引数で関数に値を入力して、「return 値」 という文で関数そのものが値を出力するようにしたほうがいいでしょう。

  • 悪い例
    • def の内側の i と外側の i は別物。よって、未定義変数扱い(i = nil型) となり、nil に足し算はできないのでエラーになります。
        0
        1
        2
        3
        4
        5
        6
        7
      
      #!/usr/bin/env ruby
      def bad_func
        i = i + 1 #=> undefined method `+' for nil:NilClass (NoMethodError)
      end
       
      i = 0
      bad_func
      puts i
  • 微妙な修正例
    • いちおう動きますが、i が何なのか読み手が混乱するかもです。
        0
        1
        2
        3
        4
        5
        6
        7
        8
      
      #!/usr/bin/env ruby
      def update_func(i)
        i = i + 1
        return i         #update_func が i という変数の値と同じになります。
      end
       
      i = 0
      i = update_func(i) #=> 1 / update_func(0) は 1 になります。
      puts i             #=> 1
      
  • 良い修正例
    • 関数内と関数外で変数名が別々になりましたので、紛らわしくなくなりました。
        0
        1
        2
        3
        4
        5
        6
        7
        8
      
      #!/usr/bin/env ruby
      def update_func(func_opt)
        func_opt = func_opt + 1
        return func_opt
      end
       
      i = 0
      i = update_func(i) #=> 1 / update_func(0) は 1 になります。
      puts i             #=> 1
      

リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: Fri, 22 Jul 2011 21:58:00 JST (1525d)