খুব বেশি দিন আগে আমি জাবার পরিবর্তে স্কালা ব্যবহার শুরু করেছি। আমার জন্য ভাষাগুলির মধ্যে "রূপান্তর" প্রক্রিয়ার অংশটি Either(পরীক্ষিত) Exceptionএর পরিবর্তে গুলি ব্যবহার করতে শিখছিল । আমি কিছুক্ষণের জন্য এইভাবে কোডিং করছি, তবে সম্প্রতি ভাবতে শুরু করেছি যে এটি কি আরও ভাল উপায়।
একটা প্রধান সুবিধা Eitherবেশি হয়েছে Exceptionভাল পারফরম্যান্স হয়; একটি Exceptionস্ট্যাক-ট্রেস তৈরির প্রয়োজন এবং নিক্ষেপ করা হচ্ছে। যতদূর আমি বুঝতে পারি, যদিও, নিক্ষেপ করা Exceptionদাবী অংশ নয়, তবে স্ট্যাক-ট্রেস তৈরি করা।
তবে তারপরে, কেউ সর্বদা Exceptionএর সাথে নির্মাণ / উত্তরাধিকারী হতে scala.util.control.NoStackTraceপারে এবং আরও অনেক কিছু, আমি প্রচুর ক্ষেত্রে দেখতে পাচ্ছি যে যেখানে Eitherসত্যিকারের বাম দিকটি আসলে Exception(পারফরম্যান্স বৃদ্ধির পক্ষে)।
অন্য একটি সুবিধা Eitherহ'ল সংকলক-সুরক্ষা; স্কালা সংকলকটি হ্যান্ডেল না করা Exception(জাভা সংকলকটির বিপরীতে) সম্পর্কে অভিযোগ করবে না । তবে যদি আমি ভুল না হয়ে থাকি তবে এই সিদ্ধান্তটি একই কারণে যুক্তিযুক্ত যা এই বিষয়ে আলোচিত হচ্ছে, তাই ...
সিনট্যাক্সের ক্ষেত্রে, আমার কাছে মনে হচ্ছে- Exceptionস্টাইলটি আরও পরিষ্কার। নিম্নলিখিত কোড ব্লক পরীক্ষা করুন (উভয় একই কার্যকারিতা অর্জন করে):
Either শৈলী:
def compute(): Either[String, Int] = {
val aEither: Either[String, String] = if (someCondition) Right("good") else Left("bad")
val bEithers: Iterable[Either[String, Int]] = someSeq.map {
item => if (someCondition(item)) Right(item.toInt) else Left("bad")
}
for {
a <- aEither.right
bs <- reduce(bEithers).right
ignore <- validate(bs).right
} yield compute(a, bs)
}
def reduce[A,B](eithers: Iterable[Either[A,B]]): Either[A, Iterable[B]] = ??? // utility code
def validate(bs: Iterable[Int]): Either[String, Unit] = if (bs.sum > 22) Left("bad") else Right()
def compute(a: String, bs: Iterable[Int]): Int = ???
Exception শৈলী:
@throws(classOf[ComputationException])
def compute(): Int = {
val a = if (someCondition) "good" else throw new ComputationException("bad")
val bs = someSeq.map {
item => if (someCondition(item)) item.toInt else throw new ComputationException("bad")
}
if (bs.sum > 22) throw new ComputationException("bad")
compute(a, bs)
}
def compute(a: String, bs: Iterable[Int]): Int = ???
আধুনিক রূপ আমার জন্য অনেক ক্লিনার, এবং কোড (চালু পারেন প্যাটার্ন-তুল্য ব্যর্থতা হ্যান্ডলিং Eitherবা try-catch) উভয় ক্ষেত্রেই বেশ স্পষ্ট।
সুতরাং আমার প্রশ্নটি হল - কেন Eitherওভার (চেকড) ব্যবহার করবেন Exception?
হালনাগাদ
উত্তরগুলি পড়ার পরে, আমি বুঝতে পারি যে আমি আমার দ্বিধাটির মূল উপস্থাপন করতে ব্যর্থ হয়েছি। আমার উদ্বেগ অভাবের সাথে নয়try-catch ; যে কোনও একটি Exceptionদিয়ে "ধরা" দিতে পারে Try, বা catchএর ব্যতিক্রমটি মোড়ানোর জন্য ব্যবহার করতে পারেLeft ।
সঙ্গে আমার প্রধান সমস্যা Either/Try আসে যখন আমি যে পথ ধরে অনেক বিন্দুতে ব্যর্থ হতে পারে কোড লিখতে; এই পরিস্থিতিতে, যখন কোনও ব্যর্থতার মুখোমুখি হয়, তখন আমার পুরো কোড জুড়ে সেই ব্যর্থতাটি প্রচার করতে হবে, এইভাবে কোডের পথটিকে আরও জটিল করে তোলা হয়েছে (যেমন পূর্বোক্ত উদাহরণগুলিতে দেখানো হয়েছে)।
Exceptionএস ব্যবহার না করে কোড ভাঙার অন্য উপায় আছে return(যা আসলে স্কালায় অন্য একটি "ট্যাবু")। কোডটি এখনও Eitherপদ্ধতির চেয়ে পরিষ্কার হবে, এবং Exceptionশৈলীর চেয়ে কিছুটা কম পরিষ্কার হওয়ার পরেও , অ-ধরায়দের কোনও ভয় নেই Exception।
def compute(): Either[String, Int] = {
val a = if (someCondition) "good" else return Left("bad")
val bs: Iterable[Int] = someSeq.map {
item => if (someCondition(item)) item.toInt else return Left("bad")
}
if (bs.sum > 22) return Left("bad")
val c = computeC(bs).rightOrReturn(return _)
Right(computeAll(a, bs, c))
}
def computeC(bs: Iterable[Int]): Either[String, Int] = ???
def computeAll(a: String, bs: Iterable[Int], c: Int): Int = ???
implicit class ConvertEither[L, R](either: Either[L, R]) {
def rightOrReturn(f: (Left[L, R]) => R): R = either match {
case Right(r) => r
case Left(l) => f(Left(l))
}
}
মূলত return Leftপ্রতিস্থাপন throw new Exception, এবং উভয়ই অন্তর্নিহিত পদ্ধতি rightOrReturnহ'ল স্ট্যাকটি স্বয়ংক্রিয় ব্যতিক্রম প্রচারের পরিপূরক।
Try। Eitherবনাম সম্পর্কে অংশটি Exceptionকেবল বলেছে যে Eitherপদ্ধতির অন্যান্য ক্ষেত্রে "অ-ব্যতিক্রমী" হলে এস ব্যবহার করা উচিত। প্রথমত, এটি একটি খুব, খুব অস্পষ্ট সংজ্ঞা ইমো। দ্বিতীয়ত, এটি কি সিনট্যাক্স পেনাল্টিটির পক্ষে মূল্যবান? আমি বলতে চাইছি, Eitherতারা যদি উপস্থিত সিনট্যাক্সের ওভারহেডের জন্য না হয় তবে সত্যই এটি ব্যবহার করতে আমার আপত্তি হবে না ।
Eitherআমার কাছে মোনাদের মতো দেখাচ্ছে। মনডগুলি সরবরাহ করে এমন কার্যকরী রচনা সুবিধাগুলির প্রয়োজন হলে এটি ব্যবহার করুন। বা, সম্ভবত না ।
Eitherনিজেই কোনও মোনাদ নয়। অভিক্ষেপ পারেন ডানে না বামে পাশ থেকে একটি একসংখ্যা, কিন্তু Eitherনিজে নয়। যদিও আপনি এটি বাম দিক বা ডানদিকে "বাইসিং" করে একটি মোনাদ তৈরি করতে পারেন । যাইহোক, তারপর আপনি একটি উভয় পক্ষের একটি নির্দিষ্ট শব্দার্থক দেওয়া Either। স্কালার Eitherমূলত নিরপেক্ষ ছিল, তবে সম্প্রতি পক্ষপাতদুষ্ট ছিল, সুতরাং আজকাল এটি আসলে একটি মোনাদ, তবে "একাকীকরণ" এর অন্তর্নিহিত সম্পত্তি Eitherনয় বরং এটি পক্ষপাতদুষ্ট হওয়ার ফলস্বরূপ।