অপরিবর্তনীয় কাঠামো এবং গভীর রচনা স্তরক্রম


9

আমি একটি জিইউআই অ্যাপ্লিকেশন বিকাশ করছি, গ্রাফিক্সের সাথে ভারী কাজ করছি - উদাহরণের স্বার্থে আপনি ভেক্টর সম্পাদক হিসাবে এটি সম্পর্কে ভাবতে পারেন। সমস্ত ডেটা স্ট্রাকচারগুলিকে অপরিবর্তনীয় করে তোলা খুব লোভনীয় - তাই আমি প্রায় চেষ্টা ছাড়াই পূর্বাবস্থায় / পুনরায় করা, অনুলিপি / পেস্ট এবং আরও অনেক কিছুই পেতে পারি।

সরলতার জন্য, আমি নিম্নলিখিত উদাহরণটি ব্যবহার করব - বহুভুজ আকারগুলি সম্পাদনা করতে অ্যাপ্লিকেশনটি ব্যবহৃত হয়, সুতরাং আমার কাছে "বহুভুজ" অবজেক্ট রয়েছে যা কেবল অপরিবর্তনীয় পয়েন্টগুলির তালিকা:

Scene -> Polygon -> Point

এবং তাই আমার প্রোগ্রামে আমার কেবলমাত্র একটি পরিবর্তনীয় পরিবর্তনশীল আছে - এটি বর্তমান সিন অবজেক্টকে ধারণ করে। আমি যে সমস্যাটি শুরু করেছি যখন আমি পয়েন্ট টেনে আনার বাস্তবায়ন করার চেষ্টা করি - পরিবর্তনীয় সংস্করণে, আমি কেবল কোনও Pointবস্তুকে দখল করি এবং এর স্থানাঙ্কগুলি পরিবর্তন করতে শুরু করি। অপরিবর্তনীয় সংস্করণে - আমি আটকে আছি। আমি Polygonবর্তমানের সূচকগুলি, Sceneটানা পয়েন্ট ইনডেক্সের ইনডিকেস সংরক্ষণ করতে Polygonএবং প্রতিবার এটি প্রতিস্থাপন করতে পারতাম । তবে এই পদ্ধতির স্কেল হয় না - যখন কম্পোজিশনের মাত্রা 5 এবং আরও চলে যায়, বয়লারপ্লেটটি অসহনীয় হয়ে উঠবে।

আমি নিশ্চিত যে এই সমস্যাটি সমাধান করা সম্ভব - সর্বোপরি, এখানে হ্যাজেল রয়েছে সম্পূর্ণরূপে স্থাবর কাঠামো এবং আইও মোনাড সহ। তবে আমি কীভাবে খুঁজে পাচ্ছি না।

আপনি কি আমাকে ইঙ্গিত দিতে পারেন?


@ জোব - এখনই এটি কীভাবে কাজ করে এবং এটি আমাকে অনেক ব্যথা দেয়। সুতরাং আমি বিকল্প পদ্ধতির সন্ধান করছি - এবং
অপ্রয়োজনীয়তা

@ রোগাচ: আপনি কি আপনার বয়লারপ্লেট কোড সম্পর্কে আরও ব্যাখ্যা করতে পারেন?
rwong

উত্তর:


9

আমি বহুভুতের সূচকগুলি বর্তমান দৃশ্যে সংরক্ষণ করতে পারতাম, বহুভুতের টানা পয়েন্টের সূচক এবং প্রতিবার এটি প্রতিস্থাপন করতে পারি। তবে এই পদ্ধতির স্কেল হয় না - যখন কম্পোজিশনের মাত্রা 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দেখলে একটি লেন্স দেয় returns 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

এবং আপনাকে কেবল পুরো দৃশ্যটি আপডেট করতে হবে। এটি একটি খুব শক্তিশালী ধারণা এবং যখন আপনার যত্ন নেওয়া আপনার ডেটার অংশগুলি দেখার জন্য লেন্স তৈরির জন্য কিছু সুন্দর ফাংশন থাকে তখন এটি খুব ভাল কাজ করে works

তবে এটি বর্তমানে কার্যকরী প্রোগ্রামিং সম্প্রদায়ের মধ্যে খুব সুন্দর জিনিস রয়েছে। লেন্স দিয়ে কাজ করার জন্য ভাল গ্রন্থাগার সমর্থন পাওয়া মুশকিল, এবং তারা কীভাবে কাজ করে এবং আপনার সহকর্মীদের কী কী সুবিধা রয়েছে তা ব্যাখ্যা করা আরও বেশি কঠিন। লবণ একটি দানা সঙ্গে এই পদ্ধতির গ্রহণ করুন।


দুর্দান্ত ব্যাখ্যা! এখন আমি লেন্স কি কি পেতে!
ভিনসেন্ট লেক্রুবিয়ার

13

আমি ঠিক একই সমস্যাটিতে কাজ করেছি (তবে কেবল 3 টি কম্পোজিশনের স্তর সহ)। প্রাথমিক ধারণাটি ক্লোন করা, তারপরে পরিবর্তন করা । অপরিবর্তনীয় প্রোগ্রামিং শৈলীতে, ক্লোনিং এবং পরিবর্তন একসাথে ঘটতে হবে, যা কমান্ড অবজেক্টে পরিণত হয় ।

নোট করুন যে পরিবর্তনীয় প্রোগ্রামিং স্টাইলে ক্লোনিং যেভাবেই করা দরকার ছিল:

  • পূর্বাবস্থায় ফেরানো / পুনরায় করার অনুমতি দেওয়ার জন্য
  • ডিসপ্লে সিস্টেমটির একই সাথে "সম্পাদনার আগে" এবং "সম্পাদনার সময়" মডেলটি ওভারল্যাপ করা (ভূতের লাইন হিসাবে) প্রদর্শিত হতে পারে, যাতে ব্যবহারকারী পরিবর্তনগুলি দেখতে পারে।

পরিবর্তনীয় প্রোগ্রামিং শৈলীতে,

  • বিদ্যমান কাঠামোটি গভীর-ক্লোনযুক্ত
  • ক্লোন অনুলিপিটিতে পরিবর্তনগুলি করা হয়
  • ডিসপ্লে ইঞ্জিনটি ভুত-লাইনে পুরানো কাঠামো, এবং ক্লোনড / পরিবর্তিত কাঠামোর রঙে রেন্ডার করতে বলা হয়।

অপরিবর্তনীয় প্রোগ্রামিং শৈলীতে,

  • প্রতিটি ব্যবহারকারীর ক্রিয়া যা ডেটা পরিবর্তনের ফলস্বরূপ ফলাফলকে "কমান্ড" এর অনুক্রমে ম্যাপ করা হয়।
  • একটি কমান্ড অবজেক্ট হ'ল সংশোধন প্রয়োগ করতে হবে ঠিক কী, এবং মূল কাঠামোর একটি রেফারেন্স।
    • আমার ক্ষেত্রে, আমার কমান্ড অবজেক্টটি কেবলমাত্র পয়েন্ট সূচকটি পরিবর্তন করতে হবে এবং নতুন স্থানাঙ্কগুলি স্মরণ করে। (অর্থাত্ খুব হালকা ওজন, কারণ আমি দৃut়ভাবে পরিবর্তনযোগ্য স্টাইল অনুসরণ করছি না))
  • যখন কোনও কমান্ড অবজেক্টটি কার্যকর করা হয়, এটি কাঠামোর একটি সংশোধিত গভীর-অনুলিপি তৈরি করে, নতুন কপির মধ্যে পরিবর্তনটি স্থায়ী করে তোলে।
  • ব্যবহারকারী আরও সম্পাদনা করার সাথে সাথে আরও কমান্ড অবজেক্ট তৈরি হবে।

1
অপরিবর্তনীয় ডেটা কাঠামোর গভীর অনুলিপি কেন তৈরি করবেন? আপনাকে কেবল পরিবর্তিত বস্তু থেকে মূল পর্যন্ত রেফারেন্সগুলির "মেরুদণ্ড" অনুলিপি করতে হবে এবং তেহ মূল কাঠামোর অবশিষ্ট অংশগুলির রেফারেন্সগুলি বজায় রাখতে হবে।
মনিকা

3

গভীরভাবে অপরিবর্তনীয় বস্তুর সুবিধা রয়েছে যে কোনও কিছুকে গভীর-ক্লোনিং করার জন্য কেবল একটি রেফারেন্স অনুলিপি করা প্রয়োজন। তাদের অসুবিধা আছে যে গভীরভাবে-ঘৃণিত বস্তুতে এমনকি একটি ছোট্ট পরিবর্তন আনার জন্য প্রতিটি বস্তুর ভিতরে এটি বাসা বাঁধার জন্য একটি নতুন উদাহরণ তৈরি করা প্রয়োজন। মিউটেবল অবজেক্টগুলির সুবিধা রয়েছে যে কোনও অবজেক্ট পরিবর্তন করা সহজ - কেবল এটি করুন - তবে কোনও বস্তুর গভীর ক্লোনিংয়ের জন্য একটি নতুন অবজেক্ট তৈরি করা দরকার যা প্রতিটি নেস্টেড অবজেক্টের গভীর ক্লোন ধারণ করে। সবচেয়ে খারাপ, যদি কেউ কোনও বস্তুকে ক্লোন করে পরিবর্তন করতে চান, সেই বস্তুকে ক্লোন করুন, অন্য পরিবর্তন করুন, ইত্যাদি পরিবর্তনগুলি যত বড় বা ছোট হোক না কেন তার প্রতিটি সংরক্ষিত সংস্করণের জন্য পুরো শ্রেণিবিন্যাসের একটি অনুলিপি রাখতে হবে to বস্তুর অবস্থা কদর্য।

এমন একটি পদ্ধতির যা বিবেচনা করার মতো হতে পারে তা হ'ল পরিবর্তিত এবং গভীরভাবে-পরিবর্তনীয় ডেরাইভেটিভ প্রকারের সাথে একটি বিমূর্ত "মায়াম্পটেবল" ধরণের সংজ্ঞা দেওয়া। এই জাতীয় সমস্ত ধরণের একটি AsImmutableপদ্ধতি বৈশিষ্ট্যযুক্ত হবে ; কোনও পদ্ধতির গভীর-অপরিবর্তনীয় উদাহরণে সেই পদ্ধতিটি কল করা সহজভাবে সেই দৃষ্টান্তটি ফিরিয়ে আনবে। একটি পরিবর্তনীয় উদাহরণ হিসাবে এটি কল একটি গভীর-অস্থাবর উদাহরণ ফিরে আসবে যার বৈশিষ্ট্যগুলি মূলতে তাদের সমতুল্যের গভীর-অপরিবর্তনীয় স্ন্যাপশট ছিল। পরিবর্তনীয় সমপরিমাণের সাথে অপরিবর্তনীয় প্রকারগুলি এমন একটি AsMutableপদ্ধতিতে খেলাধুলা করে , যা এমন একটি পরিবর্তনীয় দৃষ্টান্ত তৈরি করবে যার বৈশিষ্ট্যগুলি মূলগুলির সাথে মিলে।

কোনও নেস্টেড অবজেক্টকে গভীরভাবে পরিবর্তনযোগ্য বস্তুর পরিবর্তনের জন্য প্রথমে বাহ্যিক অপরিবর্তনীয় বস্তুর পরিবর্তক হিসাবে পরিবর্তন করা উচিত, তারপরে জিনিসটি সম্বলিত সম্পত্তির পরিবর্তে পরিবর্তনযোগ্য ইত্যাদির মাধ্যমে প্রতিস্থাপন করা প্রয়োজন তবে একই অংশে বারবার পরিবর্তন করা উচিত সামগ্রিক অবজেক্টের কোনও অতিরিক্ত অবজেক্ট তৈরি করার প্রয়োজন হবে না যতক্ষণ না AsImmutableকোনও মিউটেবল অবজেক্টকে কল করার চেষ্টা করা হয়েছিল (যা পার্শ্ব পরিবর্তনযোগ্য বস্তুগুলিকে পরিবর্তনযোগ্য করে দেবে, তবে একই ডেটা ধারণ করে অপরিবর্তনীয় বস্তুগুলি ফিরিয়ে দেবে)।

সাধারণ তবে উল্লেখযোগ্য অপ্টিমাইজেশান হিসাবে, প্রতিটি পরিবর্তনীয় অবজেক্ট তার সম্পর্কিত অপরিবর্তনীয় ধরণের কোনও অবজেক্টের ক্যাশেড রেফারেন্স ধরে রাখতে পারে এবং প্রতিটি অপরিবর্তনীয় টাইপের তার GetHashCodeমানটিকে ক্যাশে করা উচিত । AsImmutableকোনও পরিবর্তনযোগ্য অবজেক্টকে কল করার সময় , কোনও নতুন অপরিবর্তনীয় বস্তু ফেরার আগে, এটি ক্যাশেড রেফারেন্সের সাথে মিলবে কিনা তা পরীক্ষা করুন। যদি তা হয় তবে ক্যাশেড রেফারেন্সটি ফিরিয়ে দিন (নতুন অপরিবর্তনীয় বস্তুকে ত্যাগ করা)। অন্যথায় নতুন অবজেক্টটি ধরে রাখতে ক্যাশেড রেফারেন্স আপডেট করুন এবং এটি ফেরত দিন। এটি হয়ে গেলে বারবার কল করুনAsImmutableকোনও হস্তক্ষেপ মিউটেশন ছাড়াই একই বস্তুর উল্লেখ পাওয়া যাবে। এমনকি যদি কেউ নতুন দৃষ্টান্ত তৈরির ব্যয় না বাঁচায় তবে কেউ সেগুলি রাখার স্মৃতি ব্যয় এড়াতে পারবেন। তদ্ব্যতীত, অপরিবর্তনীয় বস্তুর মধ্যে সাম্যের তুলনা খুব দ্রুত করা যেতে পারে যদি বেশিরভাগ ক্ষেত্রে আইটেমগুলির সাথে তুলনা করা হয় তবে রেফারেন্স-সমান বা বিভিন্ন হ্যাশ কোড থাকে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.