Archive for 3月, 2010

Ruby – Structの宣言方法

Rubyでは構造体風の振る舞いをするStructクラスがあるのは有名な話。タプル的なものを使わなければいけない際、Hashだと hoge[:name] = "hoge" のように書かなければいけないところを、 hoge.name = "hoge" と書けてタイプ数が減り、便利。

リファレンスマニュアルには以下のような形で、新しい構造体クラスを作る、とある。

1
HogeTuple = Struct.new(:name, :value)

でも、僕はこう書かないと落ち着かない……。

1
2
class HogeTuple < Struct.new(:name, :value)
end

2行(あるいは「;」を含む記法)になってしまうし、何より無名のサブクラスが一つ余計に生成されてしまう(実際、 HogeTuple.ancestors で分かる)ので富豪的な感じがあるが、でも class って宣言が無いと非常にそわそわするんだけど、、、こう書くの僕だけ?

あと、HogeTupleにさらに独自のメソッドを付け加えたい際は、下の書き方のほうがコードがすっきりする、と言うメリットもある(と、最初は考えてた)。

でも

上記記事では、

1
2
3
4
5
class HogeTuple < Struct.new(:name, :value)
  def inspect
    "<#{self.class} name: #{self.name.inspect} value: #{self.value.inspect}>"
  end
end

みたいなのはobsoleteであると主張していて、Struct.newにブロックを伴う書き方がいいようだ。

1
2
3
4
5
HogeTuple = Struct.new(:name, :value) do
  def inspect
    "<#{self.class} name: #{self.name.inspect} value: #{self.value.inspect}>"
  end
end

何が言いたいかというと、「俺もそわそわする!」 と言う方は一緒に流行らせましょう。ということでこの行削除。ここまでは言えない。。

確かにancestorsに無名の謎クラスが入ってしまうのも気持ち悪い感じはある。でも、僕はclass って書いてないとそわそわする。もはや好みの問題?

あと

「StructをどうしてもStrutsと綴ってしまう」と言うコミュニティを作りましょう。Javaほとんど書けない僕ですらこうなのだから、みんなきっと間違えるだろうと思う(勘違い)。

今日の動的メソッド定義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Hoge
  def initialize(opts={})
    if opts[:dynamic]
      def name
        "dynamic"
      end
    end
  end
 
  def name
    "static"
  end
end
#=> nil
 
h = Hoge.new
#=> #<Hoge:0x7f2c5fad2388>
h.name
#=> "static"
h2 = Hoge.new(:dynamic => true)
#=> #<Hoge:0x7f2c5fac4648>
h2.name
#=> "dynamic"
 
h.name
#=> "dynamic" !!!!!!!!!!!!

ポイント: メソッド内で分岐してメソッドを定義すると、全てのインスタンスのメソッドが変わるようだ。

JRuby試した

Hadoopとかにアクセスしたいので試している。

インストール

aptitudeだと1.2とかが入っていけてないので、1.4をダウンロード

1
2
3
4
5
6
7
8
9
tar xzf jruby-bin-1.4.0.tar.gz 
cd jruby-1.4.0/
sudo su
mkdir /opt/jruby
cp -a * /opt/jruby/
exit
export PATH=$PATH:/opt/jruby/bin
jruby -v
# jruby 1.4.0 (ruby 1.8.7 patchlevel 174) (2009-11-02 69fbfa3) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_15) [amd64-java]

JDBCに接続

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'java'
import 'java.util.Properties'
import 'net.sourceforge.jtds.jdbc.Driver'
info = Properties.new
info.put "user", "udzura"
info.put "password", "udzurahoge"
 
driver = Driver.new
conn = driver.connect("jdbc:jtds:sqlserver://sql.udzura.dummy/master", info)
stmt = conn.createStatement
rs = stmt.executeQuery("SELECT TOP 10 * FROM [Hoge].[dbo].[T_Fuga]")
while rs.next
  puts "#{'%03d' % rs.row}: #{rs.getColumn(1)}, #{rs.getColumn(2)}"
end
rs.close
stmt.close

ちょっとずつ覚えましょうね。