मैं वर्तमान दृश्य में बहुभुज के सूचकांकों को संग्रहीत कर सकता था, बहुभुज में खींचे गए बिंदु का सूचकांक और हर बार इसे बदल सकता हूं। लेकिन यह दृष्टिकोण पैमाना नहीं है - जब रचना का स्तर 5 और आगे जाता है, तो बॉयलरप्लेट असहनीय हो जाएगा।
यदि आप बॉयलरप्लेट के आसपास नहीं पहुंच सकते तो आप बिल्कुल सही हैं । विशेष रूप से, एक छोटे सबपार्टर के साथ एक नया दृश्य बनाने के लिए बॉयलरप्लेट बदल गया। हालांकि, कई कार्यात्मक भाषाएं इस तरह के नेस्टेड संरचना हेरफेर से निपटने के लिए एक निर्माण प्रदान करती हैं: लेंस।
एक लेंस मूल रूप से अपरिवर्तनीय डेटा के लिए एक गेट्टर और सेटर है। एक लेंस में एक बड़ी संरचना के कुछ छोटे हिस्से पर ध्यान दिया जाता है। एक लेंस को देखते हुए, वहाँ दो चीजें आप इसके साथ क्या कर सकते हैं कर रहे हैं - आप कर सकते हैं देखने बड़ा संरचना का एक मूल्य के छोटे से हिस्से हैं, या आप कर सकते हैं सेट का एक नया मान एक बड़ा संरचना का एक मूल्य के छोटे से हिस्से। उदाहरण के लिए, मान लें कि आपके पास एक लेंस है जो किसी सूची में तीसरे आइटम पर केंद्रित है:
thirdItemLens :: Lens [a] a
उस प्रकार का अर्थ है कि बड़ा ढांचा चीजों की एक सूची है, और छोटा सा हिस्सा उन चीजों में से एक है। इस लेंस को देखते हुए, आप सूची में तीसरा आइटम देख और सेट कर सकते हैं:
> view thirdItemLens [1, 2, 3, 4, 5]
3
> set thirdItemLens 100 [1, 2, 3, 4, 5]
[1, 2, 100, 4, 5]
कारण लेंस उपयोगी हैं क्योंकि वे गेटर्स और सेटर का प्रतिनिधित्व करने वाले मूल्य हैं , और आप उन्हें उसी तरह से सार कर सकते हैं जिस तरह से आप अन्य मूल्यों को देख सकते हैं। आप फ़ंक्शंस कर सकते हैं जो लेंस लौटाते हैं, उदाहरण के लिए एक listItemLens
फ़ंक्शन जो एक नंबर लेता है 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]]
प्रत्येक लेंस डेटा संरचना के एक स्तर को पार करने के लिए व्यवहार को एनकैप्सुलेट करता है। उन्हें जोड़कर, आप जटिल संरचनाओं के कई स्तरों को पार करने के लिए बॉयलरप्लेट को समाप्त कर सकते हैं। उदाहरण के लिए, मान लें 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
यह अच्छी तरह से अंदर एक दृश्य lens
को बदलने और अद्यतन करने के लिए सभी बॉयलरप्लेट में शामिल है , आपको केवल इस बात की परवाह करनी है कि आप किस बिंदु को बदलना चाहते हैं। आप एक साथ इस सार को आगे कर सकते हैं lensTransform
समारोह है कि एक लेंस, लक्ष्य, और एक को स्वीकार करता है समारोह लेंस के माध्यम से लक्ष्य को ध्यान में रखते अद्यतन करने के लिए:
lensTransform lens transformFunc target =
current = view lens target
new = transformFunc current
set lens new target
यह एक फ़ंक्शन लेता है और इसे एक जटिल डेटा संरचना पर "अपडेटर" में बदल देता है, फ़ंक्शन को केवल दृश्य पर लागू करता है और एक नया दृश्य बनाने के लिए इसका उपयोग करता है। तो वापस 14 वें बहुभुज के तीसरे बिंदु को दाईं ओर 10 पिक्सेल तक ले जाने के परिदृश्य में जा रहा है, जिसे इस प्रकार व्यक्त किया जा सकता lensTransform
है:
lens = scenePointLens 14 3
moveRightTen point = movePoint 10 0 point
newScene = lensTransform lens moveRightTen currentScene
और बस आपको पूरे दृश्य को अपडेट करना होगा। यह एक बहुत शक्तिशाली विचार है और बहुत अच्छी तरह से काम करता है जब आपके पास अपने डेटा के टुकड़ों को देखने के लिए लेंस के निर्माण के लिए कुछ अच्छे कार्य हैं।
हालाँकि, यह सभी बहुत ही आकर्षक सामग्री है, यहाँ तक कि कार्यात्मक प्रोग्रामिंग समुदाय में भी। लेंस के साथ काम करने के लिए अच्छा पुस्तकालय समर्थन मिलना मुश्किल है, और यह भी बताना मुश्किल है कि वे कैसे काम करते हैं और आपके सहकर्मियों को क्या लाभ हैं। नमक के एक दाने के साथ इस दृष्टिकोण को लें।