goo blog サービス終了のお知らせ 

ひしだまの変更履歴

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

HadoopでWordCount(Scala)

2011-07-24 23:59:41 | PG(Scala)

いろんな人が書いているけれども、HadoopのMapReduceを使ってWordCount。をScalaで書いてみた

素のMapReduceだからどうしても面倒な部分はあるんだけど、Scalaの機能を使って多少は便利に書ける。
で、そういった簡単な便利機能はSHadoopだのScalaHadoopだのといったライブラリーで実現されている。
…どちらも更新日が古くて、あまり更新されていないみたいだけど(苦笑)

まぁそれでも自分で書いてみると面白いネタが出てくるもので。
型が同一であることをチェックしてみたくてGeneralized Type Constraintsを初めて使ってみたし。(これでめぼしい記号はだいたい網羅したかなぁ?w)


mesos Spark

2011-07-23 03:22:36 | PG(Scala)

Scalaで分散処理が書けるライブラリー(だと思う)Sparkでプログラムを書いてみた。
サンプルを見ると、普通のScalaのコレクション操作と同じ感じで書けるのが素晴らしい。
(まだバージョン0.3なので、足りない関数は多いけど。特にsumとsortは欲しいところ。あとキーを指定した結合)

お題は、Cascadingでも書いた偏差値の算出。これって何段かの処理が必要になるから、題材には良い感じなんだよね~。
無理矢理感のあるコーディングをしてしまったけれど、それでもかなり簡単に書けた。
ただ、Windows上の単独環境では動作したけど、実際に分散環境で動かしたわけではないので、これで正しいのかは分からない^^;(…分散環境欲しいなぁ)

しかし、とりあえず出来上がったソースのサイズを見ても、プログラミングにかかった時間(1日もかかってない。Sparkの勉強開始から数えても3~4日)を考えても、CascadingよりSparkの方が楽なのは確か。これは期待大だ(笑)

なお、SparkではHadoop(というかHDFS)のファイルも扱えるみたいだが、実際に分散させるにはMesosを入れないとダメなようで、MesosはUNIXにしか対応してなくてC++でコンパイルする必要があるので、試せない><(…UNIX環境欲しいなぁ)

ところで、MesosとかSparkって、それで検索しても関係ないものがいっぱいひっかかるので、大変(苦笑)
そう考えると、ほんとHadoopは秀逸な命名だよ!


Scalaの関数(Function)とか

2011-07-18 23:15:53 | PG(Scala)

久しぶりにScalaについてウェブページを書きまくった感じw

関数に関しては、今まで見聞きした内容をかなり詰め込んだ。
関数リテラルや関数の型は他のページに書いていたものと変わらないけれど、関数オブジェクトの話とかカリー化とかFunction・PartialFunctionトレイトとか。
まぁ、例によって合っているかどうか自信ないけど…。

他に、「単純にJavaより便利だよー」というネタを書こうと思って、Dateの話とかソート方法の話を書いてみた。
デバッグログ出力もその一環のつもりだったんだけど、あまりまとまりがつかなかった…。


『Scala実践プログラミング』

2011-06-28 23:02:29 | PG(Scala)

Scala実践プログラミング』を一通り読み終わった。

Scalaの初心者がステップアップするには、そしてJavaからScalaへの移行を考えるにはとても良い本だと思う。
上級者にとっても、デザインパターンとか継続とか、他のScala本ではあまり見られない(と思う)内容は興味深いのではないかな?


まずはさらっと1章でインストールと簡単な使い方、2章で基本的な文法のおさらい。基本なので他のScala本でも触れられている事だけれども、けっこう色々網羅されているし、「あれ、こんなのも出来たんだ!」という発見もある。ただ、みっちり詰まっているので、Scalaを全く知らない人には少々厳しい気もする^^;

で、3章から徐々に本領発揮。関数型言語の特徴について。
4章、ちょっとだけだけど他言語との比較。Javaとの比較はよく聞くけれど、HaskellやらOCamlやらとの比較は初めて見た。コーディング例も載ってて、まぁ見慣れてないから違和感あるわな^^; 頭も硬くなってきてるし、やっぱり慣れているALGOL系(C言語やJava)に近いScalaが分かりやすいやw

で、5章・6章・8章のテーマが良い。この辺りがタイトルの「実践」をイメージしている感じ。
JavaからScalaへの移行を考えると、当然現在Javaで行っている業務・やり方がScalaでどうなるのかが気になるだろう。コンパイル方法・IDE・コーディング規約・テスト方法・Webフレームワーク、そういったものに触れられている。実際に業務に使うなら、どれも重要なポイント。
(自分は最近Scalaの勉強をしてきたけれど、「Scalaの文法」を勉強してきたのであって、実際的な使い方はあまり考えてなかったなーと感じた)
(しかし、IntelliJが見事にスルーされているのは何故だ!?w)
それぞれ文量が少ないのが惜しいけれど、まぁそこを深堀りしていったら、別の本が書けちゃうだろうな^^;
9章のScalaとJavaの連携も、実際に業務で使うときには気にかけなければならないポイント。

7章のデザインパターン、目の付け所が面白い。Javaのデザインパターンの置き換えと、Scala独特のパターン。(自分はJavaのデザインパターンもあまり理解してないんだけどね(爆))
7-2-6『Generalized Type Constraints』(これ、日本語では何て言うんだろう?)で、「<:<」の使い方が初めて理解できた!
Builderパターンとか、格好よすぎるw 値のコピー部分が似たソースになっているので、ここを統一できればもっと良さげ。case classのcopyメソッドを使えばいけるか…?

10章がライブラリーの紹介ということで、Actorと継続。Actorは他でもよく紹介されているけれども、継続はあまり無い気がする。(継続はやっぱり難しい(苦笑) 使い方だけはなんとなくイメージできた、といったところか…。しかも実際に使われてたら、ソースを見たときに動作を絶対誤解しそうだ。Scalaが仕事で使われだしたら、コーディング規約で真っ先に制限されそう(爆))
ライブラリーという題だったので、STMとかAkkaとかscalazとか(聞いたことはあるけどよく知らないもの)も採り上げられていればなーと思ったけれども、標準に入ってない(?)ライブラリーの紹介は雑誌とかの方が向いているかな。

最後、Appendix(よく使うメソッドの一覧)も隠れた高評価だと思う。
仕事でJavaを使う初心者によく言う事があって、それは「StringやList・Map等のよく使うクラスは、API(メソッド一覧)を全部見ておけ!」ということ。初心者は自分が知ってる数少ないメソッドを駆使して事を成し遂げようとするんだけど、(努力するのは良い事だけど、コードが膨らんで見通しが悪くなったりバグが入ったりするので、)提供されている機能を知って、それを使うべき。
Scalaの場合、特にコレクションのメソッドがやたら多くてさすがに大変なので^^;、「まずはこの本のAppendixを全部見とけ」って一言で言えるのはとても良いと思う(笑)


Scalaのへんなとこ?

2011-06-12 04:10:20 | PG(Scala)

kaminamiさんの「ここがヘンだよScala言語」がなかなか興味深いネタを扱っていたので、自分も(Scala勉強中なので詳しくはないけれど)ちょっと意見を書きたくなったw


if式の返り値

自分はScala2.8から勉強を始めたので それより前の事は知らないけれど、以前のバージョンでは「if(true) "a"」がUnitのインスタンスである()を返していたらしい。そりゃ僕も変だと思う^^;(個々人の直感から外れた動作は「変」と表現されてしまうのですな)

「if(false) "a"」の戻り値は()になるので、このif式の戻り値の型は、"a"(String)と()(Unit)の共通の型となる。Scala2.8ではAnyになるが、2.7ではUnitになる仕様だったのだろう。
(あるいは、elseが無いということは式というより文という使い方なので、whileとかに倣ってUnitにしていた?)

そういえば、"a"とか123がUnitに変換される仕組みもよく分からないなー。
「def f():Int = "a"」はコンパイルエラーになるが、「def f():Unit = "a"」は通る。StringからUnitへの暗黙変換がどこかにあるのか?


除外インポート

import java.sql.{ _, Array => _}」ってやつ。Arrayだけ除外できる。
Scalaは何か記号を使う箇所では、「_」を駆使するよね(笑)
じゃあここではどんな記号を使うべきかと問われたら、意外と悩むんじゃないかと思うけど。
そして、構文ごとに使う記号がまちまちになって、複雑とか言われちゃうんだろうなぁ。


typeと別名インポート

確かに、typeだけあれば別名インポート要らないかも?
と思ったけど、「type MMap = scala.collection.mutable.Map」って書けないんだよねぇ。typeでは型パラメーターを指定しないといけないから。
あ、「type MMap[A,B] = scala.collection.mutable.Map[A,B]」ってすればいいだけか(汗)
でもこれだと、Mapのコンパニオンオブジェクトが呼べない…。(「MMap[String,String]()」とか出来ない)


forのネスト

for(i <- 0 to 10; j <-0 to 10; k <- 0 to 10)」がどういうループか?
セミコロン区切りで3つに分かれてるから、C言語みたいに各ブロックとかで特殊な事をしてるのかもしれないし、でもi・j・kって書かれてるから三重ループのような気もするし?
うーん、他の言語で見かけない構文は、その言語の構文を勉強しないと分からないわなぁ。


for内包表記中のifとif式

forの括弧内で「if」を見かけたときにはビックリしたね(笑) 本体部分でifを書けばいいじゃんって思ったし。
「for(i <- 0 to 10 if i % 2 == 0) hoge」→
「for(i <- 0 to 10){ if(i % 2 == 0) hoge}」

for式がforeachとかに変換されると知って、ifがfilterメソッドになるんだったら、for式の構文上も「filter」というキーワードにすれば…とか思ったけど、英語圏の人にとってはifの方が分かりやすいのかもなーとも思う。


forとforEach

自分はJavaは知ってるけど関数型の考え方はさっぱりなので、forの構文無しでいきなりforeach使えって言われたら、敷居は高かっただろうなー。


タプルのインデックス

配列とかリストとかの先頭要素の添字は0なのに、Tupleは1から始まる。「t._1」みたいな。
これは自分も疑問に思った。(JDBCのResultSetも1から始まるのは気に入らない。BASICじゃないんだからさーw)

ただ、関数型言語ではタプルは1から始まるのが一般的らしい?
「ある言語内で(0オリジンに)統一する」のと、「(他言語も含めた)一般的な法則に従う」のと、どちらを採るかという話。


overrideの有無

自分は、抽象メソッドを実装するときにもoverrideを付けるべきだと思う。
「class B extends A { def name = ~ }」というソースを見たとき、nameが親クラスで宣言されているのか、自クラス専用なのか、そのソースだけでは判断できない。
オーバーライドしているのであれば、勝手にメソッド名を変えることは出来ない。
まぁ、抽象メソッドだったとすれば、変えたらコンパイルエラーになるので分かるんだけど…。IDEのリファクタリング機能がまだ期待できないので、簡単に変えられない。JavaでEclipseなら、けっこう気軽に名称変更するんだけど。


インスタンス生成時のnewの有無

最初分からなかったなぁ。newの要るケースと要らないケース。Java脳では、newしない事はありえないしなぁ。
分かってみれば、パターンは単純だけど。
(そういやC++もnewを使わないでインスタンス生成できるなぁ。あれも意味合いがけっこう違うが)


コンストラクター

classのブロック内に記述したコードが直接コンストラクターになるっていうのは、すごいアイデアだと思ったね!(コロンブスの卵的な意味で)
いわば、Javaのインスタンス初期化子の考え方を拡張したもの。コンストラクターが1つしか無いなら、def this()みたいなコードが不要で、すっきりする。(コンストラクター内のローカル変数が定義できないけど^^;)
一方、「どのコンストラクターも全てthisという名前にする」となっていたら、統一が取れているとも言える。


プレースホルダー

関数で各引数を1回しか使わない場合はプレースホルダー「_」が使える。
「_ < _」は「(a,b) => a < b」と同じだけど、引数の使用順序を変えたり2回以上使いたい場合は、どんな記号であれ一種類では表現できないよね。
「_1 < _2」みたいな表記が出来れば順序を変える事も2回以上使うことも可能だけど、数値を入れている時点で、引数の順序に依存してる(苦笑)
つまり、変数名を明示的に付けない限り、順序依存になるのはやむなし?(なるべく順序に依存すべきではない、という考え方には賛成なんだけど)

(しかしメソッド呼び出しなんかも、引数名を指定する形式にしない限り、順序に依存してるな…)


特殊なメソッドの書き方

一部のメソッド名に特別な意味があるのは自分も本当はあまり好きじゃない。それこそ用途毎にアノテーションとか付けるべきじゃないかと思う。
(JavaでRuntimeExceptionの派生クラスはthrowsが不要とか、特定のクラス名が言語仕様に入っているのは変だと思う)

と思ったけど、例えばapplyメソッドの代わりに@applyみたいなアノテーションがあったとして、「@apply apply1()」と「@apply apply2()」の2つが定義されていたら、呼び出し側でメソッド名を省略すると、どちらが呼ばれるべきか分からなくなるな(苦笑)
しかも親クラスで@apply付きのメソッドを定義してたりしたら…。


似ているキーワード

NoneNothingNullnullNilって、字面は似てるのかもしれないけど、全然別物で使い方も違うし、非常に分かりやすい。

それならListの::とかfuture(scala.concurrent.ops.futureとscala.actors.Futures.future)の違いの方がよっぽど分かりづらい。(てかfutureの違いは自分には分からない(汗))


パラメーター境界で右結合

Scalaのメソッドでは、メソッド名の末尾がコロンだと右結合になる。
これを「Scalaのメソッドでは」でなく「Scalaでは」という覚え方をしてしまうと、パラメーター境界の「<:」も気になるかも^^;

ちなみにJavaの言語仕様書の型の説明で初めて「<:」とかを見た気がするが、そのときはさっぱり理解できんかった(爆)


コンパニオンの参照

個々のクラス(インスタンス)から、コンパニオンオブジェクトのインスタンスを取得すること。
これは欲しいかも。
ついでに、Enumerationで、列挙子から列挙クラス(オブジェクト)を取得する方法も欲しいかも。(Enumeration自体、評判悪いようだけど…)


unsignedが無い

Javaにも無いからなぁ。Scalaには、JavaVMから独立してScalaVM作って欲しいな(笑)
(そのときにunsignedが入るかどうかは知らないけど、型消去は無くなるでしょう)


大抵の事は、何かしらそうなっている理由があるわけで。

ただ、その説明を聞いたときに「なるほど!」と思う人と「(理解できん)複雑だ」と思う人と、「分かったけどやっぱり複雑だ」という事柄があるんだろうなぁ。
あと、「説明を聞かないと理解できないようなものは「複雑だ」」とか「説明をじっくり見てる暇が無くて、ぱっと見た感じ複雑」という人もいるかも。

差し当たり、モナドって複雑だよね(爆)