Saya bisa menyimpan indeks Polygon di Scene saat ini, indeks titik yang diseret dalam Polygon, dan menggantinya setiap waktu. Tetapi pendekatan ini tidak skala - ketika tingkat komposisi pergi ke 5 dan lebih jauh, boilerplate akan menjadi tak tertahankan.
Anda memang benar, pendekatan ini tidak berskala jika Anda tidak bisa menyiasati boilerplate . Secara khusus, pelat untuk membuat Adegan baru dengan bagian kecil berubah. Namun, banyak bahasa fungsional menyediakan konstruksi untuk menangani manipulasi struktur bersarang semacam ini: lensa.
Lensa pada dasarnya adalah pengambil dan penyetel untuk data tidak berubah. Lensa memiliki fokus pada beberapa bagian kecil dari struktur yang lebih besar. Diberikan lensa, ada dua hal yang dapat Anda lakukan dengannya - Anda dapat melihat sebagian kecil dari nilai struktur yang lebih besar, atau Anda dapat mengatur bagian kecil dari nilai struktur yang lebih besar ke nilai baru. Misalnya, Anda memiliki lensa yang berfokus pada item ketiga dalam daftar:
thirdItemLens :: Lens [a] a
Jenis itu berarti struktur yang lebih besar adalah daftar hal-hal, dan bagian kecil adalah salah satunya. Dengan lensa ini, Anda dapat melihat dan mengatur item ketiga dalam daftar:
> view thirdItemLens [1, 2, 3, 4, 5]
3
> set thirdItemLens 100 [1, 2, 3, 4, 5]
[1, 2, 100, 4, 5]
Alasan lensa berguna adalah karena mereka adalah nilai yang mewakili getter dan setter, dan Anda dapat mengabstraksikan mereka dengan cara yang sama seperti Anda dapat nilai lainnya. Anda dapat membuat fungsi yang mengembalikan lensa, misalnya listItemLens
fungsi yang mengambil angka n
dan mengembalikan lensa yang melihat n
item ke dalam daftar. Selain itu, lensa dapat disusun :
> 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]]
Setiap lensa merangkum perilaku untuk melintasi satu tingkat struktur data. Dengan menggabungkannya, Anda dapat menghilangkan pelat ketel untuk melintasi beberapa tingkat struktur kompleks. Misalnya, seandainya Anda memiliki scenePolygonLens i
yang melihat i
Poligon ke dalam suatu Scene, dan polygonPointLens n
yang melihat nth
Titik dalam Poligon, Anda dapat membuat konstruktor lensa untuk fokus pada titik tertentu yang Anda pedulikan di seluruh adegan seperti:
scenePointLens i n = lensCompose (polygonPointLens n) (scenePolygonLens i)
Sekarang anggaplah pengguna mengklik titik 3 poligon 14 dan memindahkannya 10 piksel ke kanan. Anda dapat memperbarui adegan Anda seperti:
lens = scenePointLens 14 3
point = view lens currentScene
newPoint = movePoint 10 0 point
newScene = set lens newPoint currentScene
Ini dengan baik berisi semua pelat untuk melintasi dan memperbarui adegan di dalamnya lens
, yang perlu Anda perhatikan adalah apa yang ingin Anda ubah titiknya. Anda dapat lebih lanjut mengabstraksi ini dengan lensTransform
fungsi yang menerima lensa, target, dan fungsi untuk memperbarui tampilan target melalui lensa:
lensTransform lens transformFunc target =
current = view lens target
new = transformFunc current
set lens new target
Ini mengambil fungsi dan mengubahnya menjadi "pembaru" pada struktur data yang rumit, menerapkan fungsi hanya pada tampilan dan menggunakannya untuk membangun tampilan baru. Jadi kembali ke skenario memindahkan titik ke-3 dari poligon ke-14 ke 10 piksel yang tepat, yang dapat dinyatakan dalam bentuk lensTransform
seperti ini:
lens = scenePointLens 14 3
moveRightTen point = movePoint 10 0 point
newScene = lensTransform lens moveRightTen currentScene
Dan hanya itu yang Anda butuhkan untuk memperbarui seluruh adegan. Ini adalah ide yang sangat kuat dan bekerja dengan sangat baik ketika Anda memiliki beberapa fungsi yang bagus untuk membuat lensa yang melihat bagian-bagian dari data yang Anda pedulikan.
Namun ini semua sangat luar biasa saat ini, bahkan di komunitas pemrograman fungsional. Sulit untuk menemukan dukungan perpustakaan yang baik untuk bekerja dengan lensa, dan bahkan lebih sulit untuk menjelaskan bagaimana mereka bekerja dan apa manfaatnya bagi rekan kerja Anda. Ambil pendekatan ini dengan sebutir garam.