ruby学習メモ

  • モジュールの優先順位
# モジュール1の定義
module Sample1
  def test
    puts "Sample1!!"
  end
end

# モジュール2の定義
module Sample2
  def test
    puts "Sample2!!"
  end
end
class Clazz1
  include Sample1
  include Sample2
end
Clazz1.new.test
=> Sample2!!  # 最後に宣言した Sample2#test が呼び出される


class Clazz2
  include Sample2
  include Sample1
end
Clazz2.new.test
=> Sample1!!  # 最後に宣言した Sample1#test が呼び出される


class Clazz3
  def test
    puts "Clazz3!!"
  end
  include Sample2
  include Sample1
end
Clazz3.new.test
=> Clazz3!!  # クラス Clazz3 に定義された test が呼び出される
# スーパークラスの定義
class SuperClazz
  def test
    puts "superClazz!!"
  end
end
class Clazz4 < SuperClazz
end
Clazz4.new.test
=> superClazz!!  # スーパークラスに定義された test が呼び出される


class Clazz5 < SuperClazz
  def test
    puts "Clazz5!!"
  end
end
Clazz5.new.test
=> Clazz5!!  # クラス Clazz5 に定義された test が呼び出される


class Clazz6 < SuperClazz
  include Sample1
end
Clazz6.new.test
=> Sample1!!  # Sample1#test が呼び出される

ruby学習メモ

  • while
file = File.open("Ex084.txt")
while line = file.gets
	print if line =~ /start/ .. line=~ /end/
end

Ex084.txt の内容

1
start
3
4
end
6

出力結果

start
3
4
end
$. で読み込んだ行を表示することが出来る
puts $.
print "行数:#{$.}"
  • begin/end を使用する際の注意
# 実行されない
print "Hello\n" while false
# 1回実行される
begin
  print "Goodby\n"
end while false

実行結果

Goodby

begin/end の場合は必ず1回実行される。

イテレータによる繰り返し

puts "test1"
0.upto(9) do |x|
  print x, " "
end
print "\n\n"

puts "test2"
0.step(16, 5) {|x| print x, " "}
print "\n\n"

puts "test3"
[ 1, 1, 2, 3, 4 ].each {|x| print x, " "}

結果

test1
0 1 2 3 4 5 6 7 8 9 

test2
0 5 10 15 

test3
1 1 2 3 4 
  • for in
print "\n\n"
for v in [1,2,3,4,5]
  print v, " "
end
1 2 3 4 5
  • クラスに each メソッドを宣言すると、for in で使用することが出来る
class EachableClass
  def each
    yield "value1"
    yield "value2"
    yield "value3"
  end
end

for v in EachableClass.new
  print v, " "
end
value1 value2 value3 

break redo next

break もっとも内側のループを抜ける。
next ループの終わりにジャンプし、次の繰り返しに入る。continue 見たいな
redo 次の要素に移動せず、もう一度ブロックの処理を行う。
retry ループを最初から起動しなおす。

break に引数を指定することが出来る

result = for v in [1,2,3,4,5]
  break(v * 10) if v == 3
end

print result

=> 30

引数が省略されている場合は nil を引き渡したものとします。

変数のスコープ・ループ・ブロック

while スコープは生成されない
until スコープは作成されない
for in スコープは作成されない。for xxx in の xxx もスコープが作成されないので注意
eachなどのブロック ブロック内で定義された値はローカルスコープとなる。ただしブロック外で既に定義されている変数についてはその変数が使用されるため、スコープも継承される

ruby学習メモ

条件式

nil でも 定数 false でもないものは全て真(true)を意味する
演算子 意味
== 等価性をテストする
=== case 文の when で使用
<=> 汎用比較演算子。レシーバが引数より小さいとき -1, 両者が等しいとき 0, レシーバが引数より大きいとき +1 を返す
<, <=, =>, > 大小の比較
=~ 正規表現パターンマッチ
eql? レシーバと引数の型と値が等しいとき true を返す。例えば、1 == 1.0 は true、1.eql?(1.0) は false
equal? レシーバと引数のオブジェクトIDが同じとき true を返す

defined?

引数が定義されているかどうか。定義されていない場合は nil

defined? a
=> nil

a = 1
=> 1

defined? a
=> "local-variable"

論理式の値

words = Hash.new
(words[:key] ||= []) << "value1"
=> ["value1"]

(words[:key] ||= []) << "value2"
=> ["value1", "value2"]

#上記は以下と同じ
words[:key] = words[:key] || []
words[:key] << "value3"
=> ["value1", "value2", "value3"]

条件式

  • if文
ifthen
  [exp]
elsifthen
  [exp]
else
  [exp]
end
  • if 文を複数行にまたがって書くときは then を省略できます。
if 〜
  [exp]
elsif 〜
  [exp]
else
  [exp]
end
  • then の代わりに : を使用する
if :  [exp]
elsif :  [exp]
else [exp]
end
  • unless(if文の否定)
unless 〜
  [exp]
else
  [exp]
end
  • if修飾子
puts "aaa" if true
=> aaa と表示される

 puts "aaa" if nil
=> aaa と表示されない

-case式
>|ruby|
#うるう年
def leep(year)
  leep = case
    when year % 400 == 0: true
    when year % 100 == 0: false
    else year % 4 == 0
  end
  return leep;
end

leep(2000)
=> true
leep(2100)
=> false
def test
  while line = gets
    case line.chomp!
    when "debug"
      puts "debug!!"
    when "quit"
      return
    else
      puts line
    end
  end
end

# then キーワードも使用可能
case line.chomp!
when "debug" then puts "debug!!"
when "quit" then return
else puts line
end

# コロンも使用可能
case line.chomp!
when "debug": puts "debug!!"
when "quit": return
else puts line
end

ruby学習メモ

コマンド展開

OSによりコマンドとしいて実行される。末尾に改行が付く

`echo aaa`
=> "aaa\n"
%x{ echo "aaa" }
=> "\"aaa\"\n"
 def duration=(new_duration)
    puts "new duration = #{new_duration}"
    @duration = new_duration
  end
end
song = Song.new;song.duration = "hogehoge"

代入の返却値は破棄される。

class RetTest

  def hoge=(new_value)
    @value = new_value
    return 100
  end
end

下記の場合は value に 100 ではなく 20 が設定される

test = RetTest.new
value = test.hoge = 20
value
=> 20

属性書き込みメソッドの場合はself が暗黙レシーバにならない

class BrokenAmplifier
  attr_accessor :left_channel, :right_channel
  def volume=(vol)
    left_channel = self.right_channel = vol
  end
end
ba = BrokenAmplifier.new
ba.left_channel = ba.right_channel = 99
ba.volume =  5
ba.left_channel
=> 995 にならない
ba.right_channel
=> 5

多重代入

代入される値が代入に影響を与えない

value = 1
value, value = 100,value
=> [100, 1] ← [100,100]にはならない
value
=> 1
a = [1,2,3,4]

b,  c = a       => [1, 2, 3, 4]        b => 1 c => 2
b, *c = a       => [1, 2, 3, 4]        b => 1 c => [2, 3, 4]
b,  c = 99,  a  => [99, [1, 2, 3, 4]]  b => 99 c => [1, 2, 3, 4]
b, *c = 99,  a  => [99, [1, 2, 3, 4]]  b => 99 c => [[1, 2, 3, 4]]
b,  c = 99, *a  => [99, 1, 2, 3, 4]    b => 99 c => 1
b, *c = 99, *a  => [99, 1, 2, 3, 4]    b => 99 c => [1, 2, 3, 4]
b,(c,d),e=1,2,3,4
=> [1, 2, 3, 4] b => 1 c =>2 d=>nil e=>3

b,(c,d),e=[1,2,3,4]
=> [1, 2, 3, 4] b => 1 c=>2 d=>nil e=>3

b,(c,d),e=1,[2,3],4
=> [1, [2, 3], 4] b=>1 c=>2 d=>3 e=>4

b,(c,d),e=1,[2,3,4],5
=> [1, [2, 3, 4], 5] b=>1 c=>2 d=>3 e=>5

b,(c,*d),e=1,[2,3,4],5
=> [1, [2, 3, 4], 5] b=>1 c=>2 d=>[3, 4] e=>5

+= 演算子

class StringTest
  def initialize(string)
    @value = string.gsub(/[aeiou]/, '*')
  end
  
  def +(other)
    StringTest.new(self.to_s + other.to_s)
  end
  
  def to_s
    @value
  end
end

a = StringTest.new("damn ")
a += "hogehoge"

ruby に ++ や -- はない。

ruby学習メモ

配列展開メソッド呼び出し

アスタリスクをつけることにより、配列を展開してそれぞれを引数とすることが出来る

 def five(a,b,c,d,e)
   "#{a} #{b} #{c} #{d} #{e}"
  end
 five(1,2,3,4,5)
 => "1 2 3 4 5"
 five(1,2,3, *['4','5'])
 => "1 2 3 4 5"
 five(*(1..5).to_a)
 => "1 2 3 4 5"

lambda

 anyfunc = lambda {|n| n * n}
 ((1..10).collect(&anyfunc).join(", "))
 => "1, 4, 9, 16, 25, 36, 49, 64, 81, 100"

lambda
与えられたブロックから手続きオブジェクト (Proc のインスタンス) を生成して返します(Proc.newと同じです)。
ブロックが指定されなければ、呼び出し元のメソッドで指定されたブロックを手続きオブジェクトとして返します。呼び出し元のメソッドがブロックなしで呼ばれると ArgumentError 例外が発生します。

def hashparam(name, params)
  "#{name} params=#{params}"
end

hashparam(
  "test",
  {
    :param1=>"value1", 
    :param2=>"value2" 
  })
=> "test params=param1value1param2value2"

ruby学習メモ 練習問題

CodeZine「脱 超初心者 Javaアルゴリズム問題集 第2回」を ruby でやってみる

http://codezine.jp/careerup/article/aid/1495.aspx

問題1

標準入力された月、日が、今日であるかどうかを判定するプログラムを作成してください。

  • コマンドラインに「今日は何月何日でしょう?」のメッセージを表示する。
  • それぞれ、「何月?==> 」「何日? ==> 」を表示して入力を受け取る。
  • 入力された月日が今日であれば「正解!!」、間違っていれば「間違っています」と表示する。
回答?
# 脱 超初心者 Javaアルゴリズム問題集 第2回
# 条件分岐(複合条件)
#
# http://codezine.jp/careerup/article/aid/1495.aspx

class Study2
  def start
    puts "今日は何月何日でしょう?"
    print "何月?==>"
    month = Integer(readline)

    print "何日?==>"
    day = Integer(readline)
    now = Time.now

    if month == now.month && day == now.day
      puts "正解!!"
    else
      puts "間違っています。"
    end

  end
end


Study2.new.start
メモ
month = readline.chomp!

だと

month == now.month

が true にならない。String と Fixnum で型が異なるため

irb(main):276:0> readline.chomp!
=> String
irb(main):277:0> now.month.class
=> Fixnum