JRubyやり直し

JRubyを使わなくなっていた。理由はjarファイルの指定をアスタリスクで複数指定できなかったから(Windowsの時)。ちょっとAPI呼びたい時に面倒だったから。
しかし、Jythonではどうしても文字列の対応が難しい部分があり、JRubyを使おうと思った。
JRubyの構文が全く思いだせない。

ディレクトリ内のファイル(ディレクトリ)を表示する

Dir.open(".").each do |f|
  puts f
end

完結だ。覚えればPython並みに便利なツールになるんだろう。

ファイルかどうかを判断する

dir = "."
Dir.open(dir).each do |f|
  path = File.join(dir, f)
  puts path
  puts File.file?(path)
end

パスの結合にはFile.join()を使う。

リストの定義、追加、ソート、イテレート

よく使う方法を考えて、リストの中には敢えてHashを入れる

my_list = []
my_list << {:id => "1", :name => "John"}
my_list << {:id => "2", :name => "Bob"}
my_list << {:id => "3", :name => "Ken"}
my_list.sort! do |a,b|
  a[:name] <=> b[:name]
end
my_list.each do |i|
  puts i[:name]
  puts i[:id]
end

Hashの任意の項目でソートできる。
ソーターの指定が簡単にブロックを指定できるところが嬉しい。

文字列の便利な用法

name = "Ruby"
puts "Hello, #{name}!"
puts name.downcase
puts name.upcase

この辺りも簡単。最初はすっかり忘れていてsprintf使っていたけど、分が短い時は#{xxx}の方がずっと完結。

ifブロック

a = 10
if a == 3 then
  #
elsif a == 5 then
  #
else
  #
end

endをついつい忘れてしまう。Pythonの癖だ。

関数の作成

def my_func(x, y=",")
  puts x + y + x + y + x
end
my_func "aaa"
my_func "bbb", ""
my_func("ccc", "-")

デフォルト引数が使える。ほとんどの言語で使えるけどJavaでは使えない。なぜJavaはデフォルト引数を使わせてくれないのだろう。引数違いのメソッドをたくさん作るの面倒なのだが。

まとめ

Rubyなかなか面白い。
タブのスペースの数が2つなので、ifをいっぱい入れ子にするとend end endが沢山ならんで面白い(極端な入れ子の実装の話は置いておいて)。
忘れないうちに、もう一つJRubyでプログラムを作りたい。

同じタグの記事
同じカテゴリの記事

JRubyを久しぶりに

JRubyを久しぶりに

ツールを作る。いつもの通りJythonを使おうと思ったが、時間もあるのでJRubyにした。
以前は、JavaのAPIを繰り返し呼び出すだけの簡単なプログラムだったが、今回は少しだけJRubyでロジックも書いてみた。穴にはまった。

定数クラスから定数を取得するときは::を使う

java.awt.Colorから色を取得しようと思った。

1
2
3
4
5
6
7
8
9
10
11
import java.awt.Color
import java.awt.image.BufferedImage

bi = BufferedImage.new(100, 100, BufferedImage::TYPE_INT_RGB)
g = bi.createGraphics()

g.color = Color.BLUE
# → エラー

g.color = Color::BLUE
# → OK

Rubyでは、メソッドの呼び出しのみを.(ピリオド)で行い、その他の呼び出しは::(コロン2つ)を利用するようだ。
メソッドの呼び出しは.でも::でもどちらでも良いらしい。
java.awt.Colorの.はピリオドでも良いようだ。しかし、java.awt.Color::BLUEは::だ。なんだこれ。

Javaクラスのimportはimport

Rubyの外部ファイル読み込みはrequire。
だからといって、Javaのクラスがすべて外部ファイルで定義されているわけではないので、requireではいけない。javaと同じようにimportを利用する。

1
2
3
4
5
6
7
8
require "java"
# → これはJRubyを組むときは読んでおいた方が良いらしい。

require "java.awt.Color"
# → エラー

import "java.awt.Color"
# → OK

単純なセッター、ゲッターはプロパティの様に呼び出しても良い

これは、なかなか面白い。
また、キャメルケースなメソッドをスネークケースに変換しても呼び出せる。
メソッドの括弧も省略できる。

1
2
3
4
5
6
7
8
9
10
11
g.setColor(Color::RED)
# → Java的。しかしエラーではない。

g.set_color(Color::GREEN)
# → まだJava的。しかしエラーではない。

g.set_color Color::BLUE
# → もう少し。しかしエラーではない。

g.color = Color::YELLOW
# → OK

ゲッター、セッターをプロパティとして扱えるのはKotlinっぽい。

ブロックコメント

ブロックコメントは

1
=begin

から

1
=end

に適用される。
よく、ソースの先頭に覚書を残すので、ブロックコメントの使い方は覚えておかなくては。
しかし、ネットをみると、ブロックコメントはあまり使わないらしい。
行コメントの#を使うようだ。今はIDEが良くできているので、各行に#を補ってくれるのだろう。
また、Javaでも言われているが、ブロックコメントの中にブロックコメントは書けないので、そういう時のためにブロックコメントは残しておくのだろうか。

しかし、Pythonと同様に複数行コメントに三重引用符が使える。
これでコメントを残しても良いのかな?

スクリプト引数

ARGVに引数が入っている。ARGVは配列。sizeやlengthで引数の数を確認できる。

1
2
3
4
5
puts ARGV.size
puts ARGV.length
if ARGV.size > 0
    puts ARGV[0]
end

また、$0にスクリプト(コマンド)そのものが入っている。

1
2
puts $0
# → JRubyのirbで実行したらjirbが返ってきた。

まとめ

JRubyも良い言語だ。簡便に書けるし、実行速度も不足ない。
JythonとJRuby、どちらを選ぶかはなかなか悩む。

同じタグの記事
同じカテゴリの記事

JRubyを始める

Ruby(JRuby)を始める(始めた)

Javaのサードパーティー製APIをスクリプトから呼びたくて始めたJython。
python言語は容易に学習でき、あっさり使えるようになったが、
日本語が出現するたびに悩むことになる。
・Javaで取得した任意の文字コードの文字列を加工しようと思ったとき
・Javaで取得した任意の文字コードの文字列をcodecs.openで出力しようとしたとき
これは、Jythonでなくても、python2.7でも同様に苦労することになった。
str文字列と、unicode文字列の違いで実行時エラーになってしまう。
Jythonがpython3になってくれれば…
Jythonはメンテナンスが止まっていそうなので、他の言語に逃げることに。

Kotlinはコンパイルもできるが、スクリプトでも実行できるので、Kotlinに挑戦した。
Kotlinは優れている。いろいろなロジックを簡潔に書けるようになっている。
lambdaも便利だし、型推論も便利。SmartCastも理にかなっている。null safeなところも良い。
しかし、スクリプトとして少し使いたいだけの時は、ちょっと面倒。
Javaで作られたモジュールはreturn Mapだが、それは暗黙にMapと決まっているとき、キャストせずに使いたい。
null safeなKotlinだけど、Javaで作られたモジュールは、躊躇せずnullを返してくる。
Kotlinで完結させるなら良いかもしれないけど、やはりサードパティーのJavaAPIを使おうと思うと…

そこで、JRubyを使うことにした。
rubyの構文は独特な気がしたので、なかなか手を出せなかったが遂にこの時が来た。
perlが得意だったこともあるため、使ってみると懐かしさもあった。
学習の順番が良かったかもしれない。Kotlinでlambdaの良さを感じた後だったので、
rubyのlambdaが心地よい。

ここが良いruby

rubyを使っていて、ここが良いと思ったこと。

unless

ifを否定で使いたいとき、ifが「もし~ならば」に対して、unlessは「もし~でなければ」と使える。

1
2
3
4
5
a = 1
b = 2
unless a == b
    puts "not equal."
end

perlみたい。

文字列への変数展開

“#{var_name}”とすることで、文字列に変数を展開できる。

1
2
3
4
var_name = "test value"
puts "TEST1:[#{var_name}]"
puts "TEST2:[#{var_name.size}]"
puts "TEST3:[#{var_name.upcase}]"

Kotlinみたい(Kotlinは$だけど)。

n回繰り返しが簡単

10.timesで10回繰り返しが書ける。

1
2
3
10.times do |i|
    puts i
end

pythonも簡単だけど、rubyはもっと簡単。

1
2
for i in range(10)
    print(i)

pythonはブロックをインデントで表現できるので、結構短くコーディングできる。

メイン処理

スクリプトなので、スクリプトの先頭から処理が走ってしまうが、
直接実行したときのみ実行されるメソッドを定義する。

1
2
3
if __FILE__ == $0
    puts "Main"
end

pythonでも似たような感じ

1
2
if __name__ == '__main__':
    print("Main")

pythonはブロックの終端を書かなくて良いのが素敵。

まとめ

JRubyはなかなか心地よい。
構文はシンプルで、面倒が少ない。
do endは慣れる必要があるが、その程度だと思う。

しかし、サードパーティのJavaAPIを呼ぶこととなると、少し面倒なところもある。
APIがその先で読んでいるAPIのjarが読めないことがある。
JRubyはCLASSPATHを理解してくれて、そこからライブラリを探して勝手に動いてくるのだが、
たまに、明示的にrequire “xxxx.jar”しなてくはならない時がある。

JRubyを通じてrubyの使い方が理解できたので、それはそれで良かったのだが、
サードパーティJavaAPIを呼び出すのは、結果的にKotlin+Java8になりそう。

dll hellならぬjar hellに耐性があるのはKotlin+Java7(8以降)だと思う。

同じタグの記事
同じカテゴリの記事