by shigemk2

当面は技術的なことしか書かない

flatMapいろいろ

flatten + mapというふうに解釈されるflatMapだけど、たぶんいろいろな使い方があったりする。 期待する動作をやらせたいのであればflattenとmapを組み合わせてもいいし、逆にmapだけ、flattenだけでもよかったりする。 このあたりの挙動がよくわかっていない。

flatMapの中の関数の戻り値はscala.collection.GenTraversableOnce[?]だったりするらしいので、そこらへんの挙動に躓いてお亡くなりになることもある。

scala> List("1,1,1","2","3").flatMap(_.split(","))
res0: List[String] = List(1, 1, 1, 2, 3)

scala> List("1,1,1","2","3").map(_.split(","))
res1: List[Array[String]] = List(Array(1, 1, 1), Array(2), Array(3))

scala> Seq(Seq("hello", "world"), Seq("good", "morning")).flatMap(_.mkString(" ").toUpperCase)
res2: Seq[Char] = List(H, E, L, L, O,  , W, O, R, L, D, G, O, O, D,  , M, O, R, N, I, N, G)

scala> Seq(Seq("hello", "world"), Seq("good", "morning")).map(_.mkString(" ").toUpperCase)
res3: Seq[String] = List(HELLO WORLD, GOOD MORNING)

scala> Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => x.size } // error
<console>:11: error: type mismatch;
 found   : Int
 required: scala.collection.GenTraversableOnce[?]
       Seq(Seq(1,2,3), Seq(), Seq(5,6)) flatMap { x => x.size } // error
                                                         ^

scala> Seq(Seq(1,2,3), Seq(), Seq(5,6)) map { x => x.size }
res5: Seq[Int] = List(3, 0, 2)

qiita.com

AWScalaを使ってみたい

github.com

READMEに則った使い方。putでファイルをS3に転送して、転送データをもとにURLとかを取得している。

import awscala._, s3._

implicit val s3 = S3()

val buckets: Seq[Bucket] = s3.buckets
val bucket: Bucket = s3.createBucket("unique-name-xxx")
val summaries: Seq[S3ObjectSummary] = bucket.objectSummaries

bucket.put("sample.txt", new java.io.File("sample.txt"))

val s3obj: Option[S3Object] = bucket.getObject("sample.txt")

s3obj.foreach { obj =>
  obj.publicUrl // http://unique-name-xxx.s3.amazonaws.com/sample.txt
  obj.generatePresignedUrl(DateTime.now.plusMinutes(10)) // ?Expires=....
  bucket.delete(obj) // or obj.destroy()
}

雑な使い方。バケットにファイルをアップロードするサンプル。

import awscala._, s3._

val bucketName = "バケットネーム"
val accessKey = "アクセスキー"
val secretKey = "シークレットキー"
implicit val region = Region.どこか
implicit val s3 = S3(Credentials(accessKey, secretKey))
val bucket: Bucket = s3.bucket(bucketName).get
bucket.put("sample.txt", new java.io.File("sample.txt"))

ちなみにこのライブラリはACLまわりが実装されていないのでこの方法で画像をアップロードしてもブラウザから画像を見ることはできないし、大きなファイル(10GB以上とか)をダウンロードしたりアップロードしようとしたりしてもEntityTooLargeエラーだかなんだかになる。