আমার প্রথম পছন্দটি সাধারণত পুনরাবৃত্তি ব্যবহার করা হবে। এটি কেবলমাত্র পরিমিতভাবে কম কমপ্যাক্ট, সম্ভাব্যতর দ্রুত (অবশ্যই ধীর নয়) এবং প্রারম্ভিক সমাপ্তির পরে যুক্তি আরও সুস্পষ্ট করে তুলতে পারে। এক্ষেত্রে আপনার নেস্টেড ডিফস দরকার যা কিছুটা বিশ্রী:
def sumEvenNumbers(nums: Iterable[Int]) = {
def sumEven(it: Iterator[Int], n: Int): Option[Int] = {
if (it.hasNext) {
val x = it.next
if ((x % 2) == 0) sumEven(it, n+x) else None
}
else Some(n)
}
sumEven(nums.iterator, 0)
}
আমার দ্বিতীয় পছন্দটি ব্যবহার করা হবে return, যেহেতু এটি অন্য সমস্ত কিছু অক্ষত রাখে এবং আপনাকে কেবল সেই ভাঁজটি মোড়ানো প্রয়োজন defযাতে আপনার কিছু থেকে ফিরে আসতে পারে - এই ক্ষেত্রে আপনার ইতিমধ্যে একটি পদ্ধতি রয়েছে, তাই:
def sumEvenNumbers(nums: Iterable[Int]): Option[Int] = {
Some(nums.foldLeft(0){ (n,x) =>
if ((n % 2) != 0) return None
n+x
})
}
যা এই বিশেষ ক্ষেত্রে পুনরাবৃত্তির চেয়ে অনেক বেশি সংক্ষিপ্ত (যদিও আমরা পুনরাবৃত্তির সাথে বিশেষত দুর্ভাগ্য হয়েছিলাম যেহেতু আমাদের পুনরাবৃত্ত / পুনরুক্তি করতে হয়েছিল)। ঝাঁপিয়ে পড়া নিয়ন্ত্রণ প্রবাহ হ'ল অন্য সমস্ত জিনিস যখন সমান হয় তা এড়াতে এমন এক জিনিস, তবে এখানে তা নেই। যেখানে এটি মূল্যবান সে ক্ষেত্রে এটি ব্যবহারে কোনও ক্ষতি হবে না।
যদি আমি প্রায়শই এটি করতাম এবং এটি কোনও পদ্ধতির মাঝখানেই চাইতাম (যাতে আমি কেবল রিটার্ন ব্যবহার করতে পারি না) তবে আমি সম্ভবত স্থানীয়-বহিরাগত নিয়ন্ত্রণের প্রবাহ তৈরি করতে ব্যতিক্রম হ্যান্ডলিংটি ব্যবহার করব। এটি হ'ল, সর্বোপরি, এটি কী ভাল এবং ত্রুটি পরিচালনা করা কেবল এটি কার্যকর সময় নয়। একমাত্র কৌশল হ'ল স্ট্যাক ট্রেস তৈরি করা এড়ানো (যা সত্যই ধীর) এবং এটি সহজ কারণ বৈশিষ্ট NoStackTraceএবং তার শিশু বৈশিষ্ট্যগুলি ControlThrowableইতিমধ্যে এটি আপনার জন্য করে। স্কেলা ইতিমধ্যে এটি অভ্যন্তরীণভাবে ব্যবহার করে (বাস্তবে, এটি ভাঁজের অভ্যন্তর থেকে রিটার্নটি কার্যকর করে!)। আসুন আমরা নিজের তৈরি করি (বাসা বাঁধতে পারে না, যদিও কেউ এটি ঠিক করতে পারে):
import scala.util.control.ControlThrowable
case class Returned[A](value: A) extends ControlThrowable {}
def shortcut[A](a: => A) = try { a } catch { case Returned(v) => v }
def sumEvenNumbers(nums: Iterable[Int]) = shortcut{
Option(nums.foldLeft(0){ (n,x) =>
if ((x % 2) != 0) throw Returned(None)
n+x
})
}
এখানে অবশ্যই ব্যবহার returnকরা ভাল, তবে মনে রাখবেন যে আপনি যে shortcutকোনও জায়গায় পুরোপুরি গুছিয়ে রাখতে পারেন না, যে কোনও জায়গায় রাখতে পারেন ।
আমার জন্য পরবর্তী লাইনটি ভাঁজগুলি পুনরায় বাস্তবায়ন করা হবে (হয় নিজেই বা এটির একটি লাইব্রেরি সন্ধান করা) যাতে এটি প্রারম্ভিক সমাপ্তির ইঙ্গিত দিতে পারে। এটি করার দুটি প্রাকৃতিক উপায় হ'ল মূল্য প্রচার করা নয় বরং একটি Optionমান যুক্ত রয়েছে যেখানে Noneসমাপ্তির ইঙ্গিত দেয়; বা দ্বিতীয় সূচক ফাংশন ব্যবহার করতে যা সম্পূর্ণরূপে সংকেত দেয়। কিম স্টেবেলের দেখানো স্ক্যালাজ আলস্য ভাঁজ ইতিমধ্যে প্রথম কেসটি কভার করে, তাই আমি দ্বিতীয়টি দেখাব (একটি পরিবর্তনীয় বাস্তবায়ন সহ):
def foldOrFail[A,B](it: Iterable[A])(zero: B)(fail: A => Boolean)(f: (B,A) => B): Option[B] = {
val ii = it.iterator
var b = zero
while (ii.hasNext) {
val x = ii.next
if (fail(x)) return None
b = f(b,x)
}
Some(b)
}
def sumEvenNumbers(nums: Iterable[Int]) = foldOrFail(nums)(0)(_ % 2 != 0)(_ + _)
(আপনি পুনরাবৃত্তি, রিটার্ন, অলসতা ইত্যাদির মাধ্যমে সমাপ্তি বাস্তবায়ন করেন কিনা তা আপনার উপর নির্ভর করে))
আমি মনে করি যে এটি মূল যুক্তিসঙ্গত রূপগুলি কভার করে; এছাড়াও কিছু অন্যান্য বিকল্প রয়েছে, তবে আমি নিশ্চিত না যে কেউ এই ক্ষেত্রে সেগুলি কেন ব্যবহার করবে। ( Iteratorএটি যদি একটি থাকে তবে নিজেই এটি ভালভাবে কাজ করবে findOrPrevious, কিন্তু এটি না করে এবং অতিরিক্ত কাজ এটি হাতে ব্যবহার করার জন্য লাগে যে এটি এখানে ব্যবহার করার একটি নির্বোধ বিকল্প করে))