স্কালায় একাধিক কেস ক্লাস মেলে


100

আমি কয়েকটি কেস ক্লাসের সাথে মিলে যাচ্ছি এবং দুটি ক্ষেত্রে একইভাবে পরিচালনা করতে চাই। এটার মতো কিছু:

abstract class Foo
case class A extends Foo
case class B(s:String) extends Foo
case class C(s:String) extends Foo


def matcher(l: Foo): String = {
  l match {
    case A() => "A"
    case B(sb) | C(sc) => "B"
    case _ => "default"
  }
}

তবে আমি যখন এটি করি তখন ত্রুটিটি পাই:

(fragment of test.scala):10: error: illegal variable in pattern alternative
    case B(sb) | C(sc) => "B"

আমি এটিকে কাজ করে নিতে পারি আমি বি এবং সি এর সংজ্ঞা থেকে পরামিতিগুলি সরিয়ে ফেলি তবে কীভাবে আমি প্যারামগুলির সাথে মেলে পারি?

উত্তর:


145

দেখে মনে হচ্ছে আপনি স্ট্রিং প্যারামিটারগুলির মানগুলির যত্ন নিচ্ছেন না, এবং বি এবং সি একই আচরণ করতে চান, তাই:

def matcher(l: Foo): String = {
  l match {
    case A() => "A"
    case B(_) | C(_) => "B"
    case _ => "default"
  }
}

আপনার যদি অবশ্যই, অবশ্যই, অবশ্যই প্যারামিটারটি বের করতে হবে এবং তাদের সাথে একই কোড ব্লকে চিকিত্সা করতে হবে:

def matcher(l: Foo): String = {
  l match {
    case A() => "A"
    case bOrC @ (B(_) | C(_)) => {
      val s = bOrC.asInstanceOf[{def s: String}].s // ugly, ugly
      "B(" + s + ")"
    }
    case _ => "default"
  }
}

যদিও আমি অনুভব করি যে এটি কোনও পদ্ধতির মধ্যে ফ্যাক্ট করা অনেক পরিষ্কার er

def doB(s: String) = { "B(" + s + ")" }

def matcher(l: Foo): String = {
  l match {
    case A() => "A"
    case B(s) => doB(s)
    case C(s) => doB(s)
    case _ => "default"
  }
}

যদিও আমার উদাহরণটি এটি দেখায় না আমি সেই সমস্ত প্যারামগুলির প্রয়োজন। দেখে মনে হচ্ছে আমাকে কেবল একটি অবজেক্ট ব্যবহার করতে হবে। ধন্যবাদ!
টিমডিজনি

4
"কেস এ (অস্ট্রিং) | কেস বি (এস্ট্রিং) => প্রিন্টলন (এস্ট্রিং)" এর কোনও কারণ স্কেল অনুমতি দেয় না? যতক্ষণ না এস্ট্রিংয়ের ধরণ A এবং B উভয়ের জন্য সমান, ততক্ষণ এটির অনুমতি দেওয়া উচিত। আপনার শেষ উদাহরণটি দেখে মনে হচ্ছে বি এবং সি ক্ষেত্রে নকল না করা ভাল।
জেমস মুর

37
আমি তোমাকে আরও একটি যেতে হবে। আমি মনে করি যে এ (এক্স) এবং বি (এক্স) যা কিছু উত্পাদিত করে টাইপ সিস্টেমে টাইপটি উপরের সীমানায় সেট case A(x) | B(x) => println(x)করা থাকলে মঞ্জুরি দেওয়া ভাল হবে x
মিচ ব্লিভিন্স

4
@ মিচব্লেইনস: আপনি ইস্যু.স্কালা- lang.org/browse/SUGGEST-25 (বিকল্প প্যাটার্নে পরিবর্তনশীল বাঁধাইয়ের অনুমতি দিন)
এরিক কাপলুন


9

বেশ কয়েকটি উপায় আছে যা আমি দেখতে পাচ্ছি যে আপনি পরে কী করছেন তা অর্জন করতে, যদি আপনার কেস ক্লাসগুলির মধ্যে কিছু সাধারণতা থাকে। প্রথমত কেস ক্লাসগুলি এমন একটি বৈশিষ্ট্য প্রসারিত করে যা সাধারণতা ঘোষণা করে, দ্বিতীয়টি একটি কাঠামোগত ধরণ ব্যবহার করে যা আপনার কেস শ্রেণির প্রসারিত করার প্রয়োজনকে সরিয়ে দেয়।

 object MuliCase {
   abstract class Foo
   case object A extends Foo

   trait SupportsS {val s: String}

   type Stype = Foo {val s: String}

   case class B(s:String) extends Foo
   case class C(s:String) extends Foo

   case class D(s:String) extends Foo with SupportsS
   case class E(s:String) extends Foo with SupportsS

   def matcher1(l: Foo): String = {
     l match {
       case A        => "A"
       case s: Stype => println(s.s); "B"
       case _        => "default"
     }
   }

   def matcher2(l: Foo): String = {
     l match {
       case A            => "A"
       case s: SupportsS => println(s.s); "B"
       case _            => "default"
     }
   }

   def main(args: Array[String]) {
     val a = A
     val b = B("B's s value")
     val c = C("C's s value")

     println(matcher1(a))
     println(matcher1(b))
     println(matcher1(c))

     val d = D("D's s value")
     val e = E("E's s value")

     println(matcher2(d))
     println(matcher2(e))
   }
 }

কাঠামোগত ধরণের পদ্ধতিটি মুছে ফেলার বিষয়ে একটি সতর্কতা উত্পন্ন করে যা বর্তমানে আমি কীভাবে নির্মূল করব তা নিশ্চিত নই।


6

ঠিক আছে, এটি আসলে বোঝায় না, তাই না? বি এবং সি পারস্পরিক একচেটিয়া, সুতরাং sb বা sc আবদ্ধ হয়ে যান, তবে কোনটি জানেন না, তাই কোনটি ব্যবহার করবেন তা সিদ্ধান্ত নিতে আপনার আরও নির্বাচনের যুক্তির প্রয়োজন হবে (প্রদত্ত যে তারা একটি অপশন [স্ট্রিং] তে আবদ্ধ ছিল, না) একটি স্ট্রিং)। সুতরাং এই কিছুই লাভ হয় না:

  l match {
    case A() => "A"
    case B(sb) => "B(" + sb + ")"
    case C(sc) => "C(" + sc + ")"
    case _ => "default"
  }

অথবা এটা:

  l match {
    case A() => "A"
    case _: B => "B"
    case _: C => "C"
    case _ => "default"
  }

বি বা সি মিলেছে কিনা সেদিকে খেয়াল না রাখলে কী হবে? নিম্নলিখিত কোডটিতে বলুন: args match { case Array("-x", hostArg) => (hostArg, true); case Array(hostArg, "-x") => (hostArg, true) }তবে, আমি দেখতে পাচ্ছি যে এটি সাধারণ ঘটনা নয় এবং স্থানীয় পদ্ধতি তৈরি করা একটি বিকল্প। যাইহোক, যদি বিকল্পটি সুবিধাজনক হয় তবে কেস বিকল্প থাকার ক্ষেত্রে সামান্যই পয়েন্ট আছে। প্রকৃতপক্ষে, কিছু এমএল উপভাষায় আপনার অনুরূপ বৈশিষ্ট্য রয়েছে এবং আপনি এখনও ভেরিয়েবলগুলি বাঁধতে পারেন, যতক্ষণ প্রতিটি ভেরিয়েবল উভয় বিকল্পের ক্ষেত্রে একই ধরণের সাথে আবদ্ধ থাকে।
ব্লেসরব্ল্যাডে

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