ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Scalaコミュの配列のかけ算

  • mixiチェック
  • このエントリーをはてなブックマークに追加
ショウフウと申します。
最近scalaをはじめたのですが、どうもscalaっぽく?かけなくていろいろ四苦八苦しております。

いま配列のかけ算のソースを実装しようと思っているのですが、ど〜もうまい書き方が思いつかないため、ご教授頂けないかと思いまして。
※javaライブラリとかに配列のかけ算あったりするかもですが、scalaで書いてみたいなと。

例えば

1: var array1 = Array(1,2,3,4)
2: var array2 = Array(5,6,7,8)
3: var result = array1 * array2;
4: println(result)
-> Array(5, 12, 21, 32)

のようなソースを考えていて、あたりまえですがそのままだと3行目で
value * is not a member of Array[Int]
とおこられてしまいます。

var result = multi(array1 * array2)

のようにして、multiメソッド(独自メソッド)内で計算してしまえばよいのですが、このような方法ではなく、

var result = array1 * array2

のように計算させたいのですが、何か良い書き方はないでしょうか?

お忙しい所大変お手数ですが、ご教授頂ければ幸いです。

コメント(4)

一つの方法としては、Scalaの機能の一つであるimplicit conversionを使うというのが考えられます。
implicit conversionを使うと、既存のクラスにメソッドを追加したように見せかける事ができます。
たとえば以下のようなコードを書くことで、上で書かれていることを実現することができます。

class RichIntArray(self: Array[Int]) {
def *(another: Array[Int]): Array[Int] = {
assert(self.size == another.size)
self zip another map { case (x, y) => x * y }
//以下と同じ
//val result = new Array[Int](self.size)
//for(i <- 0 until self.size) {
// result(i) = self(i) * another(i)
//}
//result
}
}
implicit def extendArray(self: Array[Int]) = new RichIntArray(self)
val array1 = Array(1,2,3,4)
val array2 = Array(5,6,7,8)
val result = array1 * array2
println(result mkString ",")

ここで、肝となるのはimplicit defという定義で、implicitというキーワードを付けて
メソッドを定義すると、以降、その定義が有効な範囲で、Scalaコンパイラは
implicit defで定義されたメソッドの引数の型(ここではArray[Int])が持っていない
メソッド(ここでは*)の呼び出しを見つけると、implicit defで定義されたメソッド
(ここではextendArray)を適用して、*を呼び出せるようにしようと試みます。
結果として、上記のコードは内部で

val array1 = Array(1,2,3,4)
val array2 = Array(5,6,7,8)
val result = extendArray(array1) * array2
println(result mkString ",")

という風に変換され、プログラマからはあたかもArrayクラスに*メソッドが追加された
かのように見えます。
うぉ、まさしく希望通りのソースです。
実際ローカル上で、実行させてみてうまく動きました!

感謝です!!
捕捉ですが、このような既存のクラスへの拡張をライブラリ化したい場合、

object ArrayExtension {
class RichIntArray(self: Array[Int]) {
def *(another: Array[Int]): Array[Int] = {
assert(self.size == another.size)
self zip another map { case (x, y) => x * y }
//以下と同じ
//val result = new Array[Int](self.size)
//for(i <- 0 until self.size) {
// result(i) = self(i) * another(i)
//}
//result
}
}
implicit def extendArray(self: Array[Int]) = new RichIntArray(self)
}

のようにobjectでラップしてやって、拡張を使用したい箇所で、

import ArrayExtension._

のようにすることで、implicit conversionによるクラスの拡張を再利用することができます。
こういう使い方もたしかにできますね、なるほど。
object で囲むと確かに再利用する事になりますね。

早速こちらでソース実装ためしてみます!

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Scala 更新情報

Scalaのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング