[解決済み] ネストした構造体をよりきれいに更新する方法
質問
次の2つがあるとします。
case class
があるとします。
case class Address(street: String, city: String, state: String, zipCode: Int)
case class Person(firstName: String, lastName: String, address: Address)
というインスタンスがあり、次の
Person
クラスのインスタンスです。
val raj = Person("Raj", "Shekhar", Address("M Gandhi Marg",
"Mumbai",
"Maharashtra",
411342))
ここで、もし私が
zipCode
の
raj
とすれば
val updatedRaj = raj.copy(address = raj.address.copy(zipCode = raj.address.zipCode + 1))
ネストのレベルが上がると、これはさらに醜くなります。もっときれいな方法はないでしょうか(Clojureの
update-in
のような)きれいな方法はありますか?
どのように解決するのですか?
ファスナー
ヒュッテ・ジッパー
は、不変のデータ構造の便利な走査と'突然変異'を提供します。ScalazはZipperを
Stream
(
ファスナー
) と
Tree
(
scalaz.TreeLoc
). ジッパーの構造は、代数式の記号的微分のような方法で、元のデータ構造から自動的に導出できることがわかりました。
しかし、これはScalaのケースクラスでどのように役立つのでしょうか?さて、Lukas Rytz は最近 をプロトタイプ化しました。 この拡張は,アノテーションされた case class に対して自動的にジッパーを作成します.彼の例をここに再現してみる。
scala> @zip case class Pacman(lives: Int = 3, superMode: Boolean = false)
scala> @zip case class Game(state: String = "pause", pacman: Pacman = Pacman())
scala> val g = Game()
g: Game = Game("pause",Pacman(3,false))
// Changing the game state to "run" is simple using the copy method:
scala> val g1 = g.copy(state = "run")
g1: Game = Game("run",Pacman(3,false))
// However, changing pacman's super mode is much more cumbersome (and it gets worse for deeper structures):
scala> val g2 = g1.copy(pacman = g1.pacman.copy(superMode = true))
g2: Game = Game("run",Pacman(3,true))
// Using the compiler-generated location classes this gets much easier:
scala> val g3 = g1.loc.pacman.superMode set true
g3: Game = Game("run",Pacman(3,true)
ですから、コミュニティはこの努力を継続し、コンパイラに統合するよう、Scalaチームを説得する必要があります。
ちなみに、Lukasは最近
を公開しました。
DSL を使ってユーザがプログラム可能なパックマンのバージョンを発表しました。彼は修正されたコンパイラを使ったようには見えませんが、私はどんな
@zip
の注釈が見当たらないからです。
ツリーのリライト
他の状況では、ある戦略(トップダウン、ボトムアップ)に従って、データ構造全体に何らかの変換を適用し、構造内のある点での値に対して一致するルールに基づいて、変換したい場合があります。古典的な例としては、ある言語のASTを、評価、簡略化、情報収集のために変換することが挙げられます。 Kiama サポート リライト の例を参照してください。 リライターテスト を、そしてこの ビデオ . 以下は、食欲をそそるスニペットです。
// Test expression
val e = Mul (Num (1), Add (Sub (Var ("hello"), Num (2)), Var ("harold")))
// Increment every double
val incint = everywheretd (rule { case d : Double => d + 1 })
val r1 = Mul (Num (2), Add (Sub (Var ("hello"), Num (3)), Var ("harold")))
expect (r1) (rewrite (incint) (e))
なお、Kiama 外に出る を実現するために、型システムの外に出ています。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン