Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

Ruby First Impression

Ruby覚えてみたくなったんで、思い立ったが吉日。独習本を買ってトライしてみた。

独習Ruby

独習Ruby

Rubyは簡単な言語です(キリッとか言ってるヤツどっかおかしくね。めっちゃ言語仕様複雑じゃん・・・。こんなにもぐぐりながら勉強を開始した言語は無かった。APIリファレンスを開きながらぽんぽーんと叩いてへーへーへーっていう感じにはならんかったよ。これ、Rubyの内部のパーサーの仕組みもある程度知っておかないと、絶対遅いコード書くことになりそう。受け取ったオブジェクトを常に動的に判定してよしなに解析している雰囲気がプンプン伝わってくる。joinとconcatと「+」でパフォーマンスに影響でそう。

他の言語にも同じことは言えるけど、Rubyは特に気をつけたほうがよいのではないかと心配になっている。まだ「Rubyだとプログラミングが楽しいお」の言わんとしていることが分からん。

Rubyはみんなオブジェクト

関数もオブジェクトなのでhogeって書くと引数なしのhoge関数が呼ばれたりする。JSやってれば違和感ない。

変数のスコープ

  • 「_」が頭にあるとローカル変数。つーかデフォルトはローカル変数
  • 「$」が頭にあるとグローバル変数

が、Rubyはwhileやforにはブロックスコープが無い。イテレータにしかない。

while true
  var = true
  break
end
p var
# => true
loop {
  var = true        # このブロックの中でローカル
  break
}
p var
# => -:5: undefined local variable or method `var' for #<Object:0x401a7b28> (NameError)

演算子

いっぱいあってよくわかんなくなった。リファレンスをそのたび見ることにする。++と--が無いことは覚えた。+=1と-=1で代用する。あと「a..b」と「a...b」で挙動が違う。前者はa以上b以下で後者はa以上b未満。どっからこういう発想が生まれるんだ。よくもまぁこんなこと考えるよw

別名

変数やメソッドに別名つけられるのな。へーって思った。演算子にも別名があるんだね。

<<や*といった演算子を使うことで定義されたメソッドと同じことやってくれる。こういうのをシンタックスシュガーっていうことを知った。甘いのかこれ。別に甘くないぞ。

p [1, 2, 3] * 3 #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
p [1,2,3] << 4 #=> [1,2,3,4] 

ちょっときもい。Eclipse脳だとArrayを参照すれば補完してくれるからメソッド呼べばいいじゃん可読性上がりそうだしとか思うけど、スクリプト言語の場合はtype数が少ないほうが喜ばれるのかしら。

条件分岐

ifの反対のunlessってのがあるのには驚いた。whileの反対のuntilってもあった。if(falseになる条件)でいいと思っちゃう。あとこんな書き方も出来るのな。

a,b=1,2
p "aはbよりも小さいです" if a< b

いいよこんなことしなくて・・・。素直にif(b>a) p "aはbより小さい"で良くないか・・・。

イテレータ

もっともRubyの特色が出ている気がした。

ary = [1,2,3,4,5]
ary.each { |item| p item}
p ary.select { |item % 2 == 0| } #=> [2,4]
(1..5).each do |i| p i end
100.times do |i| p i end

なんか色々パターンがある。

文字列

1.8系は単なるバイト配列でしかないんだってさ。1.9からエンコード情報を持った文字オブジェクトみたいなものになる。日本語の文字数を図る為には、その文字のエンコードを指定して1文字ずつカウントする。

puts "公用語が英語とかなに考えてんだよ日本男児なめんな".split(//u).length

正規表現

=~ってなんだよ。$&ってなんだよ。以上。

シンボル

これってJavaでいうEnumみたいなもんだと解釈した。

ただ、この使い方は困惑した。

class Person
  attr_reader:name
  attr_reader:age
  attr_accssor:feel
  
  def temper
    return @feel > 50 ? "good" : "bad"
  end
end

シンボルとインスタンス変数が1対1で紐づいている。確かにインスタンス毎に1個あればいいんだけど、attr_reader::@nameとかでよくないって思った。

メソッド

最後のreturnは省略するのが慣例なんだって。voidの場合はどうなるの?rubyにはvoidがないってことにならないか、これ。PHPと同じで引数にデフォルト値与えられるのがいい。javaはこれがないから実行時エラー回避コードが増える時がある。*を引数の前につけると引数の配列として参照できる。面白い。

あるオブジェクトの任意のメソッドを実行する(jsでいうfunction.applyのようなやつ)場合は、Method.callやObject.sendがある。

クラス

クラス変数もインスタンス変数も、プロパティ直アクセスが出来ない。attrなんとかで設定する。

同名のメソッドが複数のクラスに存在するだけでインターフェイスを共通化することが出来る。だからrubyにはインターフェイスが無い。シグニチャ違えば別メソッド扱いになるようだ。でもさ、結局コレってどこのオブジェクトでメソッドを呼ばれたかを知らないとぐちゃぐちゃになりそうだなぁ。

モジュール

Enumと抽象メソッドの集まりみたいなもん。乱暴だけど。

ブロック付きメソッド

{}の中にメソッドを入れることが出来る。yieldとcallを使う手がある。

def hoge
yield
end
hoge{p "yield!"}
def foo(&block)
 block.call
end
p foo{p "call!"}

無名関数のようなもんだな。きっと。

クロージャ

javascriptでなれておいてよかった。

def counter
  count = 0
  f = Proc.new {
    count += 1
  }
  return f
end

c = counter
puts c.call #=>1
puts c.call #=>2
puts c.call #=>3
puts c.call #=>4

このProc.newってのを手続きオブジェクトっていうらしく、こいつの内側から外側のローカル変数(この場合はcount)を参照でき、状態も保持できる。

例外

Javaでいうとtry catch finallyがbegin rescue ensure。throwsがraise。

オレオレ例外は例外クラス(StandardError)を継承すればおk。

コメント

一行は#で複数行が=begin/=end。後者はわかりづれぇー。

なにはなくとも

Ruby Reference Manual - るりまをお気に入りに入れよう。