ひしだまの変更履歴

ひしだまHPの更新履歴。
主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。

Streamを返すメソッド

2014-04-29 15:53:40 | PG(Java)

前回までのあらすじ
ジャバ八村にやってきた俺たちは、Stream使い方を会得することは出来たが、Streamを作る方法については、いまだ明かされない謎が残っていた…。


という訳で、Java8のStreamの勉強の総仕上げ。
Streamを使おうと思ったら、Streamインスタンスを生成する必要がある。
Streamクラスのof()やIntStreamのrange()等のStreamクラスに直接用意されているメソッドは探しやすいし、List等のコレクションからstream()でStreamを取得するのも分かり易いが、それ以外にもStreamを返すメソッドがある。 

クラス名メソッド名説明
java.lang.CharSequence chars 文字(char)のStream
codePoints 文字(コードポイント)のStream
java.util.regex.Pattern splitAsStream パターンで分割した各文字列のStream
java.io.BufferedReader lines 読み込んだ各行のStream
java.nio.file.Files lines ファイルの各行のStream
list ディレクトリー直下の各パス(ファイルやディレクトリー)のStream
walk サブディレクトリーまで含めた各パスのStream
find 条件指定可能なFiles#walk()
java.util.jar.JarFile stream jarファイル内のエントリー(JarEntry)のStream
java.util.zip.ZipFile stream zipファイル内のエントリー(ZipEntry)のStream

CharSequence(StringやStringBuilder等)のchars()やcodePoints()は、文字列を「文字の並び」として扱うのに便利。
まぁ、IntStreamで扱わないといけないので複雑になってしまう部分はあるけど。
(Scalaの方がシンプルなので、初心者だったらむしろScalaの書き方の方が分かりやすそうだが^^;)
この辺り、将来的にIntStreamが拡張されてもう少し便利になるような予感がする。
(少なくとも、int用のCollectorを受け取るcollectメソッドは有ってもいいんじゃないか?)

BufferedReader#lines()も便利だが、ファイルから読み込む場合はFiles#lines()を使うことの方が多そう。

ディレクトリー配下のファイル(やディレクトリー)のパス一覧を取得するFiles#list()やwalk()もnewDirectoryStream()やwalkFileTree()に比べたらずっとシンプル。
(Files#newDirectoryStream()はDirectoryStreamという(Listのような)オブジェクトを返すのだが、Java8のStreamが先に導入されていたら、きっとDirectoryStreamは作られなかっただろうと思う^^;)


Java8のStream関連で調べたかったことは、ひとまずこれで完了かな。

コメント
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Java8のStreamを一通り見てみた

2014-04-13 23:59:59 | PG(Java)

前回までのあらすじ
Streamを求めてジャバ八村にやってきた俺たちは、Streamでよく使うと思われるラムダ式を調べ始めたが、その元となる関数型インターフェースの裏にはデフォルトメソッドstaticメソッド、それにラムダ式にからんで実質的finalの新仕様が隠されていた。
そしてラムダ式と対になるメソッド参照やStreamと共に導入されたOptionalを経て、ついに俺たちはStreamに辿り着いたのだった。


という訳で、Streamを調べる前に関係していそうな新仕様を先に確認して、ようやくStreamを見ることが出来た。
Scalaのコレクションのメソッドに比べると少ないが、それでもそこそこメソッドは存在している。
結局ほとんどの面においてScalaの方が便利ではあるのだが、Java8が関数型言語への入門としてStreamを導入したのであれば、まずは基本的に使うものだけでいいという判断なのかな?
何にしても、mapメソッドが使えるのは嬉しい(笑) 

しかしJavaにはプリミティブ型というものがあるので、実行効率(速度)を求めるなら、プリミティブ型のまま操作できる必要がある。
その為にオブジェクトを対象とするStreamの他にIntStreamやLongStream・DoubleStreamを用意している。
また、値を変換するmapメソッドも、プリミティブに変換する為のmapToInt()・mapToLong()・mapToDouble()といった別のメソッドが用意されている。(Scalaだったら、数値型かどうかに関係なくmapメソッドだけ使えばいいのだが)
この辺り、プリミティブ型を持つJava言語としては頑張って用意したなぁという感じではあるのだが、関数型言語に不慣れな初心者にとってはどれを使えばいいのか混乱を招きそうな上に、他の関数型言語に慣れたモヒカンにとっては面倒なだけ(あるいはマサカリを投げる標的を増やしただけ)だorz 

また、ListやMapといった従来のコレクションに追加された関数型言語風メソッドは概ねforEachくらいで(せめてmapだけは欲しかった)、そういったメソッドを使いたければ一旦Streamに変換する必要がある。これはstream()やparallelStream()メソッドとして用意されているので、Javadocを見ただけですぐ分かるのだが。
しかしStreamから他のコレクション(ListやSet等)へ変換する方法は、ScalaだとtoListtoSetといったメソッドが用意されているのだが、Java8ではcollectメソッドCollectorオブジェクト(Collectors.toList()toSet())を渡すことで実現している。ユーティリティーみたいな別クラスになっているので、その気になれば新しいメソッドを追加するのは簡単だ。
よくこんな仕組みを考えたものだと感心するが、しかしStreamのcollectメソッドのJavadocを見て「Listに変換するにはこれを使えばいいんだ!」と思いつく人は(特に初心者には)いないと思う。

結局、Javaで関数型言語っぽい基本的な使い方をするにはStreamは充分使えるが、Java固有の面倒くささが新たに作られてしまっていて、関数型言語の初学者(関数型言語の勉強の入り口)としては地雷になりそうorz 


ちなみに、ラムダ式はけっこうシンプルなので(今のところプレースホルダーも無いし)、覚えるのはそんなに難しくないし、見たときに「何をしているのか」も比較的簡単に分かると思う。
むしろ、誤解を招きそうなのはメソッド参照の方。特に「クラス名::メソッド名」という指定方法がstaticメソッドでもインスタンスメソッドでも可能なのは、後から見たときにちょっと混乱しそうな気がする。
(ラムダ式を書く場合、たいていは引数の型を省略するが、引数の個数や引数名から、何をするものなのかは想像が付く可能性がある。しかしメソッド参照だと、そういう情報はすっぱり落ちてしまう)
まぁ、たぶん慣れの問題、あるいはIDEの支援機能次第だけど。
メソッド参照を使うときれいに書けることもあるしね。→コードポイントの例(どのオーバーロードを使っているのか分かりにくいんだが…、しかしこれはこの例がちょっと特殊な方かもしれない?)

もし「将来的に時代についていけなくして会社を滅ぼす為に、新機能を禁止して“勉強する気のない人間でも分かる”コーディング規約を作れ」と言われたら、僕はラムダ式を禁止するより先にメソッド参照を禁止するね(爆)

コメント
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

DMDL EditorX Importer生成時に余分なimportが出来るバグの修正

2014-04-09 23:41:39 | PG(分散処理)

DMDL EditorXのissue 13に挙げられたバグを修正。

Importer/Exporter生成ウィザードで生成したクラスに、余分なimport文が出来てしまうバグ。
もう少し詳しく言うと、Eclipse起動後にこのウィザードを何回か使うと、以前に生成したクラスのimport文まで出てしまうという症状。
そのクラスが存在していないと、当然import文がコンパイルエラーになる。 

ウィザードのインスタンスは毎回生成しているのでおかしいなぁ…と思ったら、ソース生成用のインスタンスはEclipseプラグインのExtensionとして生成しているので、Eclipse起動後はずっと同じインスタンスを使い回していた(汗)
なので、import文のキャッシュがクリアされずに残っていたorz

Asakusa Framework勉強会2014春で土佐さんがウィザードを使った際に出ていたエラーは、たぶんこれだと思われる。すみません>< 

コメント
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Asakusa Framework 勉強会 2014春に行ってきました

2014-04-08 23:59:58 | PG(分散処理)

2014/4/7『Asakusa Framework 勉強会 2014春』に行ってきました。→Togetter 

最初は土佐さんの『Asakusa Framework はじめの一歩・改』。
前回のが『はじめの一歩』で、今回の『改』は、主にGUIを使うようになったことが違いでした。
前回はちょうどShafuが出たばかりでまだ認知されていなかった為、Mavenを使ったコマンドベースだったのが、今回はShafuでプロジェクト作成していました。
それどころか、拙作のDMDL EditorXデータモデル作成ウィザードを使ってDMDLを生成していたのでびっくり^^;
結合モデルのキーの指定方法は、ペアとなる項目を2つ選択してからコピーするのですが、他のツールではそういう方法はしないので分かりにくいかもしれないですね^^; すみません。(今回の勉強会ではひっそりひそんでいようと思っていたのに、つい使い方を指摘してしまいました)
属性の追加ウィザードとかImporter/Exporterクラスの生成ウィザードも使われていて、フル活用でした。ありがとうございます。
生成したImporter/Exporterクラスでimport文がエラーになっていたのは、親クラスのimport文だと思われます。ウィザード内で想定しているパッケージ名と実際のパッケージが合っていないのだと思います。
ただ、build.gradle内のパッケージは変更していないようだったので、何が不一致になったのかよく分からないですが。
(追記:全然別のバグだと思われます><→バグ修正) 

DMDLから生成されるクラスのパッケージ名は、build.gradle内に記述するようになっています。(AsakusaFWの仕様)
そこから「gradlew cleanEclipse eclipse」コマンド(あるいはShafu(Jinrikisha)の「Eclipseプロジェクト情報を再構成」メニュー)でEclipse用の定義を生成すると、一緒に.settings/com.asakusafw.asakusafw.prefsというファイルが作られます。
DMDL EditorXはそのファイル内に書かれているパッケージ情報を見ています。ただし、内部でキャッシュしているので、現状では、Eclipseを再起動しないと再読み込みしません^^;
このキャッシュ・再読み込みに関しては改善しないといけないなぁと思っています。

あと、Asakusa Toad Editorも使っていただいて、ありがたいことです。

これで、ほとんどの作業がGUIで出来るというデモでした!
が、(慣れるとDMDLを直接書く方が(コピペしやすくて)速いし、Java上のDSLも補完機能が使えるのでやりやすいと思いますので)Toad Editorはまだまだですorz 


2つめはCTCの中島さん・金子さん。
RACKというCTCさんが開発したミドルウェア上でAsakusaアプリケーションを動かしたという話でした。

RACKは(Rubyの同名の何かとは関係なくて)OpenStackのAPI呼び出しを抽象化するものらしいです。
Javaのプログラム内で「process[0] = new RACK("app1");」みたいにして仮想マシンを起動できるようです。
AWSで言えば、EC2インスタンス起動のAPIを呼んでいるようなものですかね。

Hadoopクラスター起動時にRACKのプロセス間通信でお互いのIPアドレスを通知して初期化しているとのことで、そういう初期化処理が簡単に書けるようだと嬉しいですね。
EMRは起動は簡単でも、Asakusaアプリケーションのデプロイ(配置)とかは何らかの手段で行う必要があってちょっと面倒なので。 


3つめは杵渕さんの『健全な睡眠のために』。
Asakusaアプリケーションの運用環境の話でした。
夜間に障害連絡で携帯電話が鳴ると子供が起きるので奥さんも不機嫌になる、というのは共感を集めているようでした(爆) 

当初(EMRが無かった頃)は「RDB→WindGate→EC2で作ったHadoopクラスター」という構成だったのを、「RDB→S3」+「S3→EMRのHadoopクラスター」という構成に変えたと。
前者の構成では、途中で落ちたらRDBの読み込みからやり直さざるを得なかったが、後者の構成では弱点だったオンプレミス⇔AWS間の通信障害も減ったようです。 

想定外データの扱いについては、AsakusaFW特有…なのかな?
AsakusaFWのOption系クラスでは、値がnullだとget()でNullPointerExceptionが発生するようになっているので、それを考慮してコーディングする必要があります。
面倒な仕様だ…とも思いますが、Java8のOptionalでもnullだとget()でNoSuchElementExceptionが発生するので、関数型言語界隈では当たり前の仕様のようです。
(Java8のOptionalはifPresentメソッドとかが便利なので、AsakusaFWもJava8対応してラムダ式が使えるようにならないかなぁ。過去の互換性を考えると難しいかなぁ?)

本番データをS3に配置するようになったので、CI環境からそれを読み込んでテストできる…という話は、想定外データを見つけるのには向いているかもしれないですが、CI環境から本番データにアクセスしてもよいというポリシーは一般的にはあまり無いのではないかと思います^^;

紹介されていたアドベントカレンダー2013のペンギンアイコンというのは、cocoatomoさんのAsakusaFWの運用に関するブログですね。 


最後はOSSラボの船井さんの『JobSchedulerを使ったAsakusaのジョブ管理』。

ドイツのSOS社が開発したJobSchedulerを使ってAsakusaアプリケーションを実行した話です。(JobSchedulerという名前は、Apache HTTP Server並に誤解を招く固有名詞ですね^^;)
JobSchedulerは2005年(JP1と同時期)から公開されており、ヨーロッパが中心だが、日本でも去年から本番業務で何社か使われ始めているそうです。

ジョブ定義(JobSchedulerではジョブチェーンと呼ぶ)はXMLファイルで書くのですが、YAESSの実行計画のJSONファイルを読み込んでXMLファイル(とイベントハンドラー)を生成したようです。
デモではafw2jos.shというシェルを実行していました。 

実際のAsakusaアプリケーションの実行には、yaess-phase.shを使ってフェーズ毎に実行しているようです。
ただ、フェーズ実行が失敗したときに途中のフェーズから再実行して大丈夫かどうかは何とも言えないので、JobSchedulerの再実行機能は使わない方が良さそうです。
そうなるとフェーズ単位で実行する意味はあまり無いので(どこまで進んだかの進捗状況は見られるけど)、普通にyaess-batch.shでバッチ単位で実行してもいいような気がしますが^^;
実際、複数バッチになる場合はバッチの呼び出しをスケジューリングする必要があるので、それだけでも充分役立ちます。


今回は運用周りの話が多かったですね。
なかなかAsakusaFWの運用を考えるところまでいかない(自分もやったことが無い^^;)ので、色々参考になったと思います。

コメント
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

アニメ『ウィザード・バリスターズ』

2014-04-06 10:56:44 | Weblog

前期(3月末で終わった)の日曜夜のアニメ三連続のラストがウィザード・バリスターズ。
ノラガミ』→『バディ・コンプレックス』→『ウィザード・バリスターズ 弁魔士セシル』

番組紹介欄で「弁魔士」という言葉を見て「なんだろうこれは?」と思い、それを知りたくて見始めたのがきっかけ。たぶん『ウィザード・バリスターズ』というタイトルだけだったら見てなかったと思う。(「ウィザード」というタイトルだから魔法ものなんだろうけど、魔法の世界でドンパチやるだけの学園物とかは(世界観的に)あまり面白くないので)

これもオープニング・エンディングの音楽が良くて。オープニングは前奏もサビも盛り上がっているし曲の終わり方もスパッとしていて全体的にすごい。特にオープニングの「満ち欠ける月が」の跳ねるような歌い方は、他では聞いた覚えが無い感じで印象に残っている。歌詞の「1000年過去でも未来でもなく選ばれた現在」も、自分も「自分がこの時代に生きているのは不思議、かつ客観的に見ればラッキー」と思っていただけに、同じことを言っている歌詞に出会えて感慨深い。
音楽と背景画像も上手く合わせていて、男の弁魔士を悪そうに見せたり、「血の色の花」の絵にもよよんが選ばれたのにも意味があったんだなーとか。
エンディングの背景がほとんどアニメーションしていないのも、哀愁ただよう感じで上手くフィットしてた。 

で、内容の方なんだけど。魔法使い用の法律・法廷があって、そこで弁護する職業が弁魔士なんですな。
魔法が現実にあったら、確かに魔法用の法律が出来ても不思議じゃない。こういう設定は好きだ。
けど、けっきょく第十条以外はあまりクローズアップされなかった気がするのがちょっと残念。
ロボットの格闘や魔法戦が話のクライマックスなのはちょっともったいない。アニメ的には見栄えよくしないといけないのかもしれないけどね…。 

最終回1つ前の作画なんかも(自分のようなアニメ素人が見ても)力尽きてた感じなのが残念。
こういうのってDVDで直されたりするんだろうか?

しかし、つい小説版も買ってしまったんだが、思った以上に重い内容だったな^^; アニメにつながる原因を描いたものである以上、仕方ないと納得できるけど。
そのあとがきに書かれてたけど、5年も前から企画作られてたんだなー。原作があるわけでもないアニメだと、そこまでするものなんだ。

面白いアニメは第2期を期待してしまうものなんだけど、ウィザード・バリスターズは悩ましい。
というのは、1期目は良い終わり方をした感があるから。たぶん母親の再審も通りそうだし、セシルが狙われた理由も一応解明したし、2期目で使えるような大きな謎は残っていなさそうな気がする。
もちろんシズムは結局何をしたかったのか?というような分からない事もあるし、使い魔って何?みたいな世界観の話とか魔導書とか法律(偏見)を変える可能性とかで話は作っていけると思うけど、
たぶん2期目が作られるとしたら、ルシフェルが敵に回るんじゃないかと思うんだよね。そうするとハッピーエンドにはならないような気がするから、今のまま終わりでもいいかも、と思ってしまうのだった^^; 

コメント
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする