私は、(いくつか、例えば5から10の)オプションの存在に基づいてオブジェクトに変更を適用したい場合があります。私は命令的にそれを行うにしたのであれば基本的には、どのような私が目指してることは次のとおりです。左から右への引数型の推論
var myObject = ...
if (option.isDefined) {
myObject = myObject.modify(option.get)
}
if (option2.isDefined) {
myObject = myObject.someOtherModification(option2.get)
}
(ご注意:多分私のオブジェクトは、多分、それはここでのポイントではないではない、可変である。)
私は(...擬似コード)私のような、これを書いている流暢な方法を実装しようとした場合、それは立派に見えると思った:
myObject.optionally(option, _.modify(_))
.optionally(option2, _.someOtherModification(_))
だから私はIntelliJのがハイライト表示されませんサンプルコード、使用を開始エラーとして表示されますが、実際には作成されません。今
class MyObject(content: String) {
/** Apply a transformation if the optional is present */
def optionally[A](optional: Option[A], operation: (A, MyObject) => MyObject): MyObject =
optional.map(operation(_, this)).getOrElse(this)
/** Some possible transformation */
def resized(length : Int): MyObject = new MyObject(content.substring(0, length))
}
object Test {
val my = new MyObject("test")
val option = Option(2)
my.optionally(option, (size, value) => value.resized(size))
}
、私の場合には、それは本当にように見えるんどのようなので、MyObject
タイプは、いくつかの外部のAPIであるので、私は助けるために暗黙的な変換を作成しました:
// Out of my control
class MyObject(content: String) {
def resized(length : Int): MyObject = new MyObject(content.substring(0, length))
}
// What I did : create a rich type over MyObject
class MyRichObject(myObject: MyObject) {
def optionally[A](optional: Option[A], operation: (A, MyObject) => MyObject): MyObject = optional.map(operation(_, myObject)).getOrElse(myObject)
}
// And an implicit conversion
object MyRichObject {
implicit def apply(myObject: MyObject): MyRichObject = new MyRichObject(myObject)
}
そして、
object Test {
val my = new MyObject("test")
val option = Option(2)
import MyRichObject._
my.optionally(option, (size, value) => value.resized(size))
}
今回はIntelliJで失敗し、コンパイル中に0の型は不明です: Error:(8, 26) missing parameter type my.optionally(option, (size, value) => value.resized(size))
それを動作させるために、私ができる:
- 積極
size
の引数の型を指定します。my.optionally(option, (size: Int, value) => value.resized(size))
カレーバージョン
optionally
を書き換え
誰も本当に悪いですが、私が聞いてもいいかもしれません:
- カリーバージョンが動作することを理由があるが、多引数のバージョンがパラメータ化型を推論するために失敗するようで、
- は、それが実際の種類
- となどを指定せずに動作するように書くこともできますボーナス(これは意見に基づいているかもしれませんが)、どのように書くのでしょうか?(
foldLeft
の一連のオプションが私の心に浮かんでいます...)?、移動することですあなたが唯一のオブジェクトの作成から1種類を管理する場合は、object Test { val my = new MyObject("test") val option = Some(2) my.optionally[Int](option, (size, value) => value.resized(size)) }
別の方法:
私は、MyObject(一般化:パラメータ化された型を変換可能にすることによって、反対側のパラメータ化されたメソッドを排除する)ではなく、Optional型にimplicitsを逆転させる考えが好きです。私はあなたの結論に同意する:カレー風のバージョンは、少なくとも良いものに見える。目撃者の種類(https://stackoverflow.com/questions/8524878/implicit-conversion-vs-type-class?rq=1)で試してみたいことがあると思いました – GPI
http://pchiusano.blogspotも参照してください。 hk/2011/05/making-most-of-scalas-extremely-limited.htmlあなたが観察した型推論の制限について – PH88
それを掘り下げてくれてありがとう。私には分かりませんが、最初の実装例では(暗黙のうちに)、実際にはうまくいきます... – GPI