ポリゴンのインデックスを現在のシーンに保存し、ドラッグしたポイントのインデックスをポリゴンに保存して、毎回置き換えることができます。しかし、このアプローチはスケーリングしません。構成レベルが5に達すると、ボイラープレートは耐えられなくなります。
あなたが絶対に正しい、あなたがボイラープレートを回避できない場合、このアプローチはスケーリングしません。具体的には、小さなサブパートでまったく新しいシーンを作成するためのボイラープレートが変更されました。ただし、多くの関数型言語は、この種の入れ子構造操作を処理するための構成体、つまりレンズを提供しています。
レンズは基本的に不変データのゲッターおよびセッターです。レンズは、大きな構造の一部に焦点を当てています。レンズが与えられた場合、それを使ってできることは2つあります。大きな構造の値の小さな部分を表示するか、大きな構造の値の小さな部分を新しい値に設定できます。たとえば、リストの3番目のアイテムに焦点を合わせるレンズがあるとします。
thirdItemLens :: Lens [a] a
そのタイプは、より大きな構造が物事のリストであり、小さなサブパートがそれらの物事の1つであることを意味します。このレンズを指定すると、リストの3番目の項目を表示および設定できます。
> view thirdItemLens [1, 2, 3, 4, 5]
3
> set thirdItemLens 100 [1, 2, 3, 4, 5]
[1, 2, 100, 4, 5]
レンズが役立つ理由は、レンズがゲッターとセッターを表す値であり、他の値と同じようにそれらを抽象化できるからです。レンズを返す関数を作成できます。たとえばlistItemLens
、数値を受け取り、リストのth番目のアイテムをn
表示するレンズを返す関数などn
です。さらに、レンズを構成することができます:
> firstLens = listItemLens 0
> thirdLens = listItemLens 2
> firstOfThirdLens = lensCompose firstLens thirdLens
> view firstOfThirdLens [[1, 2], [3, 4], [5, 6], [7, 8]]
5
> set firstOfThirdLens 100 [[1, 2], [3, 4], [5, 6], [7, 8]]
[[1, 2], [3, 4], [100, 6], [7, 8]]
各レンズは、データ構造の1つのレベルをトラバースするための動作をカプセル化します。それらを組み合わせることにより、複雑な構造の複数のレベルを横断するためのボイラープレートを排除できます。たとえば、あなたが持っていると仮定scenePolygonLens i
見ているi
シーンで目のポリゴンを、とpolygonPointLens n
見てそのnth
ポリゴン内のポイントを、あなたはそうのようなシーン全体に気にだけ、特定のポイントに焦点を合わせるためのレンズのコンストラクタを行うことができます。
scenePointLens i n = lensCompose (polygonPointLens n) (scenePolygonLens i)
ここで、ユーザーがポリゴン14のポイント3をクリックして、10ピクセル右に移動したとします。次のようにシーンを更新できます。
lens = scenePointLens 14 3
point = view lens currentScene
newPoint = movePoint 10 0 point
newScene = set lens newPoint currentScene
これには、Sceneをトラバースおよび更新するためのすべてのボイラープレートが含まれてlens
います。気をつけなければならないのは、ポイントを変更したいものだけです。することができますさらに抽象化してこのlensTransform
レンズを受け入れる機能、ターゲット、および機能レンズを通して対象のビューを更新します:
lensTransform lens transformFunc target =
current = view lens target
new = transformFunc current
set lens new target
これは関数を受け取り、それを複雑なデータ構造の「アップデーター」に変え、関数をビューにのみ適用し、それを使用して新しいビューを構築します。したがって、14番目のポリゴンの3番目のポイントを右の10ピクセルに移動するシナリオに戻ると、次のように表すことができますlensTransform
。
lens = scenePointLens 14 3
moveRightTen point = movePoint 10 0 point
newScene = lensTransform lens moveRightTen currentScene
シーン全体を更新するために必要なのはこれだけです。これは非常に強力なアイデアであり、関心のあるデータの一部を表示するレンズを構築するためのいくつかの優れた機能がある場合に非常にうまく機能します。
ただし、これは現在、関数型プログラミングコミュニティにおいても、かなりかなり存在しています。レンズを操作するための適切なライブラリサポートを見つけることは困難であり、レンズがどのように機能するか、同僚にどのような利点があるかを説明することはさらに困難です。塩の粒でこのアプローチを取ります。