読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

Scheme/SmalltalkユーザーがRuby入門してみる

ruby

ある作りたいものがあるのですが、まずは今ある中で良いとされているモノや設計思想を知っておこうと考えました。そのためには最低でも1,2ヶ月ぐらい腹をくくってそれに取り組む必要があると思います。

というわけで趣味と実益を兼ねて、しばらくRuby on Rails、そのために触ったことがないRubyを書いてみようと思います。

まずは今知っているもの、使いたいものをRubyでどう使えるか、を調べてみます。以下はそのメモです。

REPL

irb

関数/メソッド呼び出し

トップレベルでdefした関数はfoo(a, b) 又は foo a, bで呼び出せる。

メソッド呼び出しはreceiver.method arg1, arg2の形。

トップレベルでのdefKernelクラスへのインスタンス/クラス両メソッド追加で、レシーバを省略できるだけ。プライベートメソッドになるのでレシーバ指定して呼び出すのはやや面倒?

foo、barともにトップレベル定義メソッド(関数)ならfoo bar xfoo(bar(x))と右結合になる。

返り値

最後の式。又はreturn xで返せる。

lambda/block/第一級関数

Smalltalkに似た{|a, b| ...} 又は do |a, b| ... endという形のブロックが使える。

ブロックはProcクラスのインスタンスで、使うためにはf.call 1, 2などのようにcallメソッドを呼ぶ必要がある。これはSmalltalkの感覚に近い。Schemeの関数の感覚ではない。

ブロック表記がそのままブロックという値として扱えるわけではなく、Proc.new {...}やその省略形proc {...}lambda {...}で明示的に生成する。

def foo (f)
  f.call 1, 2
end

foo proc {|a, b| p a; p b}

ただし1つだけメソッドに渡す場合は、Proc.newprocを省略して、def foo (&block) block.call endのように&で受け取ったり、それも省略してyieldというキーワードで直接呼べる。引数も渡せる。

def foo
  yield 1, 2
end

def bar (n)
  yield n, 2
end

foo {|a, b| p a; p b}
bar (1) {|a, b| p a; p b}  # ブロック以外の引数がある場合は括弧が必要

トップレベルで定義した関数名を手続きオブジェクトとして直接渡すのは面倒っぽい。とりあえずSmalltalk的に考えると良さそう。

末尾呼び出し最適化

MRIには無いっぽい?

メタクラス

Smalltalkと違ってMetaclassクラスは無く、Classクラスがそれ自身のクラスになって循環している。

あれ、じゃあクラスメソッドはどこに属してるんだろうと思ったけど、Classクラスの無名のインスタンスを作って継承ルートに挟んでるのかな

トレイト

無いっぽい、mixinやモジュールを学ぶ必要がある

コレクションとmap/reduceやcollect/injectなど

Enumerableモジュールを何かしたやつにあるっぽい。

Smalltalkと比べて

  • map/collect, select, rejectはそのままな使い方
  • reduce/injectはinject (init) {...}inject {...}
  • find/detectはifFound受け取れるやつない、残念

シンボル

:name

同値/同一性判定

同値には大抵==、同一性にはequal?メソッドを使う。Schemeと逆なので注意しよう。

"foo".equal? "foo" # => false
"foo" == "foo"     # => true

記号メソッドの呼び出しについて

:foo.== :foo  # => true

ウオッ

ローカル変数

定義無しでいきなり使える。危なくない……?小文字又はアンダースコアで始める。

インスタンス/クラス変数参照

インスタンス変数は@、クラス変数は@@を前につける。

クロージャ

トップレベルであれこれするのは避けたほうが良さそう。メソッドの引数とローカル変数では素直に使える。

メソッド内関数(メソッド)定義

レキシカルスコープじゃない……?どうも外側のメソッドが属してるクラスに属するみたいだ。避けたほうが良さそう。

現時点での感想

許容可能なLisp、特にLisp-1のつもりで書くのは危なさそう。反対にSmalltalk-80との根っこの部分での違いは今のところ感じない。

広告を非表示にする