トップ «前の日記(2010-01-17) 最新 次の日記(2010-01-27)» 編集

Route 477

過去の日記


2010-01-25 Ruby基礎文法最速マスター

Perl基礎文法最速マスターをだいたいそのまま、Rubyに置き換えてみました。

他の言語をある程度知っている人はこれを読めばRubyの基礎をマスターしてRubyを書くことができるようになる…かも知れません。無保証です。

参考:

1. 基礎

インタラクティブRuby (irb)

irbを使うと、Rubyのプログラムを簡単に練習することができます。

/Users/yhara $ irb
irb(main):001:0> puts "hello"
hello
=> nil
irb(main):002:0> 1 + 1
=> 2

以下の説明は、irbを起動して、自分で試しながら読むと習得が早いと思います。

表示 (print, puts, p)

 print "foo"   #=> 改行なし
 puts "foo"    #=> 改行あり
 p 123         #=> デバッグ用

いわゆる「printfデバッグ」は、Rubyでは「pデバッグ」になります。

変数の宣言

Rubyには変数宣言はありません。また変数の型もないので、一つの変数にいろいろなクラスのオブジェクトを代入することができます。

 a = 123
 a = "abc"   #=> aを上書きする

Rubyでは先頭の一文字によって変数の種類が変わります。

 foo   #=> ローカル変数
 @foo  #=> インスタンス変数(@)
 @@foo #=> クラス変数(@@)
 $foo  #=> グローバル変数($)
 FOO   #=> 定数(大文字から始まる)

コメント

「#」以降はコメントになります。

 # コメント

スクリプトの実行

 $ ruby foo.rb

出力結果をファイルに書き出すにはリダイレクトを使います。

 $ ruby foo.rb > out.txt

2. 数値

整数小数が使えます。

 num = 1
 num = 1.234
 num = 100_000_000

四則演算

 num = 1 + 1
 num = 1 - 1
 num = 1 * 2
 num = 5 / 2    #=> 2 (整数どうしの割り算は整数になる)
 num = 5.0 / 2  #=> 2.5 (どちらかが小数なら結果も小数)
 num = 5 % 2    #=> 1 (余りをとる)

インクリメントとデクリメント

Rubyには++演算子がないので、+=や-=を使います。

 i += 1
 i -= 1

3. 文字列

文字列はシングルクォートかダブルクォートで囲みます。ダブルクォートの中では\t(タブ)や\n(改行)などの特殊文字を利用することができます。またダブルクォートで囲まれた文字列の中では「#{}」を使って任意の式を展開することができます。

 str1 = 'abc'
 str2 = "def"
 str3 = "a\tbc\n"
 str4 = "#{str1} def"  #=> "abc def"

文字列操作

結合

 str1 = "aaa" + "bbb"
 str2 = ["aaa", "bbb", "ccc"].join(",")

分割

 record = "aaa,bbb,ccc".split(/,/)

長さ(文字数)

 length = "abcdef".length
 length = "abcdef".size     # String#sizeとString#lengthは同じ動作。好きな方をどうぞ

切り出し

 substr = "abcd"[0, 2]   #=> "ab" (0番目から2文字)

検索

 idx = "abcd".index(/bc/)  #=> 1

4. 配列

配列は「[]」を使います。

 ary = [100, 200, 300]

要素の参照と代入

 a = ary[0]   #=> 100
 b = ary[1]   #=> 200
 ary[0] = 1
 ary[1] = 2

要素の個数

 n = ary.length
 n = ary.size     # Array#sizeとArray#lengthは同じ動作。好きな方をどうぞ

配列の操作

 ary = [1, 2, 3]
 # 先頭を取り出す
 a = ary.shift   #=> aは1、aryは[2,3]に
 # 先頭に追加
 ary.unshift(5)  #=> aryは[5,2,3]に
 # 末尾を取り出す
 b = ary.pop     #=> bは3、aryは[5,2]に
 # 末尾に追加
 ary.push(9)     #=> aryは[5,2,9]に

5. ハッシュ

ハッシュ(辞書)は「{}」を使います。

 hash = {"a" => 1, "b" => 2}

キーには文字列よりも、シンボル(英語しか使えないが軽い文字列みたいなもの)を使うことが多いですが。

 hash = {:a => 1, :b => 2}

要素の参照と代入

 hash["a"]  #=> 1
 hash["b"]  #=> 2
 hash["c"] = 5
 hash["d"] = 7

ハッシュの操作

キーの取得

 hash.keys   #=> ["a", "b", "c", "d"]  (Ruby 1.8.xでは順不動)

値の取得

 hash.values #=> [1, 2, 5, 7] (同上)

キーの存在確認

 hash.key?("a")  #=> true

ハッシュのペアの削除

 hash.delete("a")

6. 制御文

Rubyでは、条件文で偽と見なされるのはfalseとnilのみで、それ以外のオブジェクトは 全て真と見なされます(0や空文字列も真)。

if文

if a == 1
  ...
elsif b == 2
  ...
else 
  ...
end

while文 (あまり使いませんが)

i = 0
while i < 5
  ...
  i += 1
end

Array#eachとブロックを使った繰り返し

[1, 2, 3].each do |i|    # 「do |..| .. end」のことをブロックと呼びます
  puts i                 # Array#eachは、各要素をブロックに渡して実行してくれます
end                      # 1, 2, 3と順に表示します。

[1, 2, 3].each{|i|       # ブロックには「{|..| .. }」というちょっと短い記法もあります。
  puts i                 # 上の記法とは(結合順位が違うだけで)全く同じ動作になります。
}

Integer#timesとブロックを使った繰り返し

5.times do |i|           # 0, 1, 2, 3, 4と順に表示します
  puts i
end

5.times do               # 値を使わないときは、「|..|」の部分は書かなくて構いません
  puts "hello"
end

Kernel#loopとブロックを使った無限ループ

loop do
  puts "stop me!"        # 無限に表示し続けるので、Ctrl-Cで止めてください。
end

その他の繰り返し

Enumerableモジュールには、繰り返しを行う便利なメソッドがたくさん定義されています。

条件に合うものだけを選ぶ

 [1,2,3,4,5].select{|x| x.even?}  #=> [2,4]

条件に合うものを除く

 [1,2,3,4,5].reject{|x| x.even?}  #=> [1,3,5]

条件に合う最初のものを返す

 [1,2,3,4,5].detect{|x| x.even?}  #=> 2

等しい値があるか調べる

 [1,2,3,4,5].member?(3)           #=> true

条件に合うものがあるか調べる

 [1,2,3,4,5].any?{|x| x.even?}    #=> true

全ての要素が条件に合うかを調べる

 [1,2,3,4,5].all?{|x| x.even?}    #=> false

条件に合うものの個数を数える

 [1,2,3,4,5].count{|x| x.even?}   #=> 2

最大のものを返す

 [1,2,3,4,5].max                  #=> 5

最小のものを返す

 [1,2,3,4,5].min                  #=> 1

加工結果が最大のものを返す

 [1,-2,3,4,-5].max_by{|x| x.abs}  #=> -5

加工結果が最小のものを返す

 [1,-2,3,4,-5].min_by{|x| x.abs}  #=> 1

昇順にソートする

 [1,-2,3,4,-5].sort               #=> [-5, -2, 1, 3, 4]

加工結果で昇順にソートする

 [1,-2,3,4,-5].sort_by{|x| x.abs} #=> [1, -2, 3, 4, -5]

加工結果を配列で返す

 [1,-2,3,4,-5].collect{|x| x.abs} #=> [1, 2, 3, 4, 5]

selectにはfind_all、rejectにはdelete_if、detectにはfind、member?にはinclude?、collectにはmapという別名があります。 *1

*1 Rubyistはcollect派とmap派に二分されますが、筆者はmap派です。理由はタイプ数が少ないからです

7. サブルーチン

Rubyには「サブルーチン」というものはありませんが、 トップレベルでメソッド定義を行うことで、どこからでも呼べるメソッドを定義することができます。 これはサブルーチンのように使うことができます。

def sum(x, y)
  return x + y
end

p sum(1,2)        #=> 3

8. ファイル入出力

読み込み

とりあえずFile.readだけ覚えておけばなんとかなると思います。

str = File.read("foo.txt")  #=> strに、foo.txtの内容を丸ごと含む文字列が代入される

書き込み

File.openで開いて、IO#writeで書き込みます (IO#putsとかもあります)。

File.open("out.txt", "wb") do |f|
  f.write str
end

知っておいた方がよい文法

Rubyの真偽値

前述のように、falseとnilが偽、それ以外の全ての値は真です。

「nil」は値がないことを示す特別な値です。例えば、配列で範囲外の要素を取ろうとするとnilが返ってきます。

 ary = [1,2,3]
 ary[100]           #=> nil

コマンドライン引数

ARGVという組み込み定数に入っています。

 # ruby foo.rb a.txt b.txt としたとき:
 p ARGV     #=> [a.txt, b.txt]

C言語と違って、ARGV[0]にプログラム名が入っていたりはしません。プログラム名は$0という変数から取得できます。

 # ruby foo.rb a.txt b.txt としたとき:
 p $0       #=> foo.rb

unless式

ifの逆です。

 unless a == 1 do
   ...
 end

後置のif (if修飾子)

Rubyではifやunlessを文の後ろに置くことができます。

 puts "ok" if x == 1
 puts "ng" unless x == 1

クラス定義

クラスは「class..end」で定義します。

class Person
  def initialize(name, age)
    @name, @age = name, age
    @address = nil
  end
  attr_reader :name, :age
  attr_accessor :address
end

jhon = Person.new("Jhon", 15)
p jhon.name
jhon.address = "USA, Earth"

その他のよく使うクラス

あとは DirRangeTime くらいですかね。

余談

本体に入らなかった、Rubyの「仕組み」についての話です。

全てがオブジェクト

Rubyでは、全ての値が、いずれかのクラスに属するオブジェクトです。 例えば数値の「1」はFixnumクラス、文字列「"foo"」はStringクラス、 配列「[1,2,3]」はArrayクラスのオブジェクトです。

全てがメソッド

Rubyには「関数」のようなものはなく、printやputsでさえもKernelモジュールに定義されたメソッドです。

 puts "foo"              # これは、
 self.puts "foo"         # これの省略形
 p self                  #=> main (トップレベルのselfは、mainという特別なオブジェクト)
 p self.class            #=> Object (mainは、Objectクラスのインスタンス)
                         #          (Objectクラスは、Kernelモジュールをインクルードしている)
                         #          (なので、トップレベルでputsと書ける)

Kernelモジュールに定義されたメソッドは、プログラムのどこからでも呼び出せます。

Rubyでは演算子もメソッドです。例えば「1 + 2」はInteger#+の呼び出し、 「ary[1]」はArray#[]の呼び出し、「ary[1] = 2」はArray#[]=の呼び出しです。

(おまけ)Ruby書籍紹介

筆者の独断と偏見によるRuby書籍紹介です。

  • 他のプログラミング言語をマスターしていて↓
    • Rubyの特徴を手早く知りたい
    • Rubyを網羅的に学びたい
    • 認定試験に備えたい
    • Java方面から来ました
      • Rubyとの違いを知りたい
      • JRubyに興味がある
      • 上司を説得したい
  • プログラミングとかあんまり慣れてない↓
    • これ一冊でOK、的な本がほしい
    • 何かを作りながら学びたい
  • コンピュータにあまり慣れてない↓
    • 初歩から応用まで一冊で
    • 基礎から応用までじっくりと
    • 堅苦しいのはいやなの
  • 基礎は分かったんで↓
    • どんなことができるのか知りたい
    • なんか作ってみたい
    • Webアプリがやりたい
    • 「まつもとゆきひろ」を「ひろゆき」と間違えないようになりたい
本日のツッコミ(全5件) [ツッコミを入れる]
knu (2010-01-25 19:36)

変数の宣言のところにスコープについて補足するともっとよくなると思います。<br><br>ifやbeginはスコープを導入しないから<br><br>if a >= 0<br> x = a<br>else<br> x = -a<br>end<br>p x<br><br>begin<br> result = something.try<br>rescue<br> #...<br>end<br>p result<br><br>とできるけど、ブロックは導入するので<br><br>list.each do |x|<br> if x > 0<br> flag = true<br> end<br>end<br>p flag<br><br>はだめ、みたいなことです。<br><br>(whileとかforはスコープを導入しないってのは教育的配慮で教えない方がいいのかもしれない)

mdaisuke (2010-01-25 23:24)

四則演算の最後の余りは1になりますかね。

sorah (2010-01-26 09:23)

Enumertableのminの部分がmaxになってるような・・

こう (2010-01-27 19:43)

ひろゆきワロタ

雲のパン屋 (2010-01-29 11:42)

classのところで書き忘れ?<br><br>jhon = Person.new("Jhon", 15)<br>p jhon.name #=>"Jhon"<br>p jhon.age #=>15<br>jhon.address = "USA, Earth"<br>p jhon.address #=>"USA, Earth"


過去の日記