EclipseのAntビルドでログが出力されない(文字化けする場合もある?)
先日、Antを実行中にエラーログが出力されない事があってはまったのでメモ。
っというか、javacを実行するよログで出力が止まってたのでエラーかどうかもわからずに半日位はまりました。
コンソールはこんな感じ。
(略) compile: [javac] Compiling 9 source files to C:\workspace\aaa\bbb\classes
ここで止まって、Antは普通に終了するという状況。
結論から言うと、EclipseのコンソールにUTF-8で文字を出力しようとしたため。
EclipseのコンソールはデフォルトではMS932で処理しようとするらしいので、UTF-8で出力しようとすると問題が発生するという事らしい。
(Eclipseのデフォルト文字コードによる??)
Web上には文字化けするとしか情報がなかったので、他にも原因があるかもですがこれまた苦労しました。
実際の出力は↓なので、出力される文字列やら警告時の色やらが原因か?
(略) compile: [javac] Compiling 9 source files to C:\workspace\aaa\bbb\classes [javac] 注:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。 [javac] 注:詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてください。 (後略)
対処方法としては、「実行の設定画面(構成の編集) → 共通 → エンコード」でUTF-8に変更すれば正しく出力されるはずです。
※警告消せよってのは無しで。。。
■関連リンク↓
EclipseのAntビルドでログが途中で切れる?
http://honeplus.blog50.fc2.com/blog-entry-28.html
EclipseのAntビルドでログが途中で切れる?(問題解決)
http://honeplus.blog50.fc2.com/blog-entry-29.html
Eclipseのコンソールの文字コード
http://lostlinksearch.net/blog/2011/02/eclipse%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%AE%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89/
クロージャー内のクロージャーで親のクロージャーを再帰的に呼ぶ方法は?
タイトルが既によくわからない。
ネストしているクロージャーで親のクロージャーを呼べないか?と言うこと。
まぁ、コード見てください。
フォルダ内の全てのファイル名を出力
def f = {} f = { if (it.isFile()) { println it } else { it.eachFile{ f(it) } } } def str =/C:\work/ f(new File(str))
通常、再帰的な処理を行う場合にはクロージャー内でcallメソッドを使用すれば自分を呼び出せますが、↑のような場合callするとeachFileのクロージャーが呼ばれちゃいます。
なんかうまい方法ないんですかね?
というか、見た目も悪いし設計の問題かな??
// 初gist。
// デフォルトだと背景色が酷かったので↓参考にcss修正してみた。
// http://d.hatena.ne.jp/snaka72/20081218/1229622900
追記(2011/08/06)
3bcさんにコメントでowner.call()を使用すれば親を呼べることを教えていただきました。
除算の結果には「%」が使えない
なんか訳のわからないエラーが出てテンパッて、解析してみたら大したことなかったという例。
クロージャの再帰処理とか初めて挑戦してる所で出くわしたので、原因突き詰めるのに時間かかっちゃいました orz
def i = 4 / 2 assert i.class == java.math.BigDecimal // ここで例外発生 def j = i % 2
Exception thrown 2011/08/03 0:51:26 org.codehaus.groovy.runtime.StackTraceUtils sanitize 警告: Sanitizing stacktrace: java.lang.UnsupportedOperationException: Cannot use mod() on this number type: java.math.BigDecimal with value: 2 at org.codehaus.groovy.runtime.typehandling.NumberMath.createUnsupportedException(NumberMath.java:254) (後略)
まとめると↓って事かな。
・除算の結果は「BigDecimal」
・BigDecimalにはmodメソッドがない(「%」が使用できない)
それぞれの事象が問題になることはないだろうけど、↑の例みたいに割った数を更に割って余りを得たい時には困るかも。
(そんな事やることないかもだけどw)
考えてみれば当たり前だけど(1..100)などの範囲は普通のリストじゃない
飽きもせずにFizzBuzzについて考えていたら、
普通の考えるように、カウントしていって特定の値の時に文字を使用するのではなくて、
最初に数字をリストに入れといてがあって、倍数のとこだけ文字列入れればいいんじゃね?って事を思いついた。
そういえば、前回FizzBuzzの最短コードを調べた時に、配列使った例もあたった気がするので、頭のどこかに引っかかってたのかな?
(ポインタとか使ってたのでほとんど読んでないですがw)
で、書いて実行してみたら例外発生!
def list = (1..100) for (i = 2; i < 100; i+=3) { // ここで例外発生 list[i] = "fizz" } for (i = 4; i < 100; i+=5) { if (list[i] instanceof Integer) { list[i] = "buzz" } else { list[i] += "buzz" } } println list.join("\n")
java.lang.UnsupportedOperationException
値の設定は許可してないよ!っとの事らしい。
あぁ、範囲は普通のリストじゃないね。
println((1..100).class)
class groovy.lang.IntRange
調べてみたら「groovy.lang.IntRange」らしい。
パフォーマンス考えると当然ですね。
ということで、ArrayListに変換して修正。
def list = (1..100) as ArrayList for (i = 2; i < 100; i+=3) { list[i] = "fizz" } for (i = 4; i < 100; i+=5) { if (list[i] instanceof Integer) { list[i] = "buzz" } else { list[i] += "buzz" } } println list.join("\n")
もっと面白いやり方ありそうだなぁ。。。
RedmineのAll-in-oneインストーラBitNami
Redmineをインストールしろと言われたので、調べたらrubyやらMYSQLやらなんやら山ほどインストールが必要らしい。
そんなのメンドクサすぎるのでオールインワンパッケージ探したら発見!
BitNami
http://bitnami.org/stack/redmine
というか、後から気づいたんだけど公式からもリンクされてました。
All-in-one インストーラ オフィシャルのパッケージではありませんが、all-in-oneインストーラも入手可能です。 Windows環境でセットアップする際に特に便利です。 BitNami :: Redmine Redmine, Ruby on Rails, MySQLなどがセットになっています。 Windows, Linux, MacOS X用が提供されています。
インストールは↓を参考にすれば特に問題なくインストールできました。
BitNami::Redmine をインストールしてみた
http://d.hatena.ne.jp/kaorun55/20090516/1242482461
インストーラー覗いてみたら、apache、ruby、mysql、subversion、gitがインストールされてるみたいです。
こうやって全部入れちゃうと何かあった時に困るっていうのがお約束ですが、まぁそれは何かあった時にでも。。。
FizzBuzzの最短コードの解析
前の記事でFizzBuzzの最短コードを紹介しました。
一見よくわからない変態コードですが、詳しく見るとそんなに難しい訳じゃなかったです。
問題のソースコード
http://d.hatena.ne.jp/y_tag/20110125/fizzbuzz
100.times{println'Fizz'*(it%3/2)+'Buzz'*(it%5/4)?:++it}
実行結果
1 2 Fizz 4 Buzz Fizz ... 中略... 98 Fizz Buzz
このままだとにくいので、変数作って三項演算子を普通のfor文にして、インデントしてから解析します。
100.times { def str = 'Fizz'*(it%3/2)+'Buzz'*(it%5/4) if (str) { println str } else { println (++it) } }
1行目
「100.times」
0〜99を順に、後のクロージャーに渡す。
(実行結果は1から100までの結果が出力されている事に注意。)
2行目
長いので少しづつ。
「'Fizz'*(it%3/2)」
「*」は文字列の繰り返しなので、「it%3/2」の数だけ繰り返す。
「it%3」は余りなので今回の場合
「0%3/2, 1%3/2, ... 99%3/2, 100%3/2」 → 「0, 0.5, 1」の繰り返し → 「"","","Fizz"」の繰り返し
同様に、Buzzの方は
「0, 0.25, 0.5, 0.75, 1」 → 「"","","","","Buzz"」の繰り返し
ということで、2つを「+」で繋げると
「"","","Fizz","","Buzz"...」となる。
表にしてみるとこんな感じ。
値 | 文字列 |
---|---|
0 | "" |
1 | "" |
2 | "Fizz" |
3 | "" |
4 | "Buzz" |
5 | "Fizz" |
3行目
「if (str)」
Groovyではifに文字列を渡すと空文字やnullの場合はfalseそれ以外はtrueを返す。
4行目
「println str」
という事なので、文字列がある場合はその文字列を表示
6行目
「println (++it)」
空文字の場合は渡された値に1をプラスして表示。
こんな感じみたいです。
1〜100を表示したいのに0〜99で処理を行っているのがポイント!
余りが0の時に表示するのではなく、余りが最大の時に表示するとかテクニックですねぇ。。。
ちなみに上記のGroovy最短コードは55バイトなんですが、rubyだと最短は56バイトらしいです。
なんかちょっと嬉しいのは私だけですか?
http://d.hatena.ne.jp/shinichiro_h/20070509#1178693484
他にも色々見つけたのでGroovy風にして書いてみました。
正規表現版
http://jarp.does.notwork.org/diary/200705b.html#200705111
f={n,i,s->"#"*n=~/^(${"#"*i})+$/?s:""} (1..100).each{println((s=f(it,3,"fizz")+f(it,5,"buzz"))?s:it)}
そんなこんなで、色々見た結果自力で頑張ってここまで縮めてみた。
わかりやすい、理解しやすいところだとこれが限界かな??><
(1..100).each{println((s=(it%3==0?"fizz":"")+(it%5==0?"buzz":""))?s:it)}
ちなみに、prinalnが冗長に感じたので削ってみたら長くなっちゃいましたw
(1..100).collect{((s=(it%3==0?"fizz":"")+(it%5==0?"buzz":""))?s:it)}.join("\n")
FizzBuzzをGroovyで書いてみた
明日は楽しみにしていたJGGUGなので、復習の意味を込めてGroovyでFizzBuzzを書いてみた。
ちなみにFizzBuzzとはこんな感じ。
1 から順に数を数えていく。但し、その数が 3 で割り切れるならば数字の代わりに Fizz と、5 で割り切れるなら Buzz と言うゲーム。3 でも 5 でも割り切れる場合は、FizzBuzz の順に言う。
http://d.hatena.ne.jp/keyword/FizzBuzz
ここで有名になったのかな?
どうしてプログラマに・・・プログラムが書けないのか?
http://www.aoky.net/articles/jeff_atwood/why_cant_programmers_program.htm
とりあえず2分位で書ければプログラマとして合格らしいので、何も考えずに書いてみた。
def f = "fizz" def b = "buzz" for (i in 1..100) { if (i % (3*5) == 0) { println f+b } else if (i % 3 == 0) { println f } else if (i % 5 == 0) { println b } else { println i } }
まぁ、何もひねりがなくそのままですw
流石に2分以内にかけたはず。
きっとGroovyっぽく書いてるのがあるはずと、探してみたらfumokmmさんの答えを発見。
うわぁ。。。Groovyっぽい!!
っというか、switchってリスト受け付けるんだ!
刺激受けまくりだったので、switch使う練習として「%」を使わないで書いてみました。
(なんでcollect使わなかったんだろうw)
def f = "fizz" def b = "buzz" def count1 = 0 def count2 = 0 (1..100).each{ x -> count1++ count2++ switch ([count1 == 3, count2 == 5]) { case{it[0]&&it[1]} : str= f+b;count1=0;count2=0; break case{it[0]} : str=f;count1=0; break case{it[1]} : str=b;count2=0; break default : str=x } println str }
面白かったのがcaseの中括弧内のitはswitchの結果で、
コロンの後のitはクロージャーのitになるということ。(上のコードだと変数「x」としていますけど)
後、caseの中括弧はクロージャーなんでなんでも書けるってこと。
switchやりたい放題じゃないですか。。。
しかし、breakが不恰好ですよね。
でも、if並べるのも。。。
というか、カウンター使うのもどうなんですかね?
いい案浮かんだら書き直したいですね。
(その時にはcollectとか使ってw)
ちなみに、最短は55文字らしいです。
こういう変態コードに憧れてGroovyの勉強始めたので、いつかこういうの書いてみたいですね。
まぁ、"「*」ってなんだっけ?"とか思ってる時点でまだまだですがw
参考↓
No Programming, No Life
http://d.hatena.ne.jp/fumokmm/20101018/1287415075
FizzBuzz最短コード(GolfScript, Groovy)
http://d.hatena.ne.jp/y_tag/20110125/fizzbuzz
第17回 G*ワークショップ
http://kokucheese.com/event/index/13874/