टर्नेरी ऑपरेटर के समान?:


94

मैं इस तरह से निर्माण से बचने की कोशिश कर रहा हूं:

val result = this.getClass.getSimpleName
if (result.endsWith("$")) result.init else result

ठीक है, इस उदाहरण में then और elseशाखा सरल है, लेकिन आप जटिल छवि बना सकते हैं। मैंने निम्नलिखित का निर्माण किया:

object TernaryOp {
  class Ternary[T](t: T) {
    def is[R](bte: BranchThenElse[T,R]) = if (bte.branch(t)) bte.then(t) else bte.elze(t)
  }
  class Branch[T](branch: T => Boolean) {
    def ?[R] (then: T => R) = new BranchThen(branch,then)
  }
  class BranchThen[T,R](val branch: T => Boolean, val then: T => R)
  class Elze[T,R](elze: T => R) {
    def :: (bt: BranchThen[T,R]) = new BranchThenElse(bt.branch,bt.then,elze)
  }
  class BranchThenElse[T,R](val branch: T => Boolean, val then: T => R, val elze: T => R)
  implicit def any2Ternary[T](t: T) = new Ternary(t)
  implicit def fct2Branch[T](branch: T => Boolean) = new Branch(branch)
  implicit def fct2Elze[T,R](elze: T => R) = new Elze(elze)
}

परिभाषित किया गया है कि, मैं उपरोक्त सरल उदाहरण को बदल सकता हूं:

this.getClass.getSimpleName is {s: String => s.endsWith("$")} ? {s: String => s.init} :: {s: String => s}

लेकिन मैं कैसे छुटकारा पा सकता हूं s: String => ? मुझे ऐसा कुछ चाहिए:

this.getClass.getSimpleName is {_.endsWith("$")} ? {_.init} :: {identity}

मुझे लगता है कि कंपाइलर को निम्न प्रकार के अतिरिक्त सामान की आवश्यकता होती है।


चूंकि मेरे पास वास्तव में मेरे उत्तर में ऐसा नहीं था - इसका कारण यह है कि आपको परेशानी हो रही है कि टाइप इंफ़ेक्शन बाएं से दाएं सबसे अच्छा काम करता है, लेकिन आप ऑपरेटर प्राथमिकता के कारण अपने टोकन को दाएं से बाएं एक साथ बाँध रहे हैं। यदि आप अपने सभी कथन शब्दों (एक ही मिसाल के साथ) बनाते हैं और जिस तरह से चीजों को एक साथ समूह में बदलते हैं, आपको वह निष्कर्ष मिलेगा जो आप चाहते हैं। (यानी आपके पास HasIs, कक्षाएं IsWithCondition, ConditionAndTrueCaseजो अभिव्यक्ति के कुछ हिस्सों को बाएं से दाएं तक
बनाएंगी

मैंने अनजाने में बाएं से दाएं प्रकार के अनुमान का तरीका अपनाया, लेकिन विधि नामों के संचालक पूर्वता और सहानुभूति के साथ अटक गया, विशेष रूप ?से किसी भी अन्य अल्फ़ान्यूम चार से पहले एक विधि नाम के रूप में पहले चार और :बाएं सहयोगी के लिए। इसलिए मुझे नई विधि के नामों पर पुनर्विचार करना होगा ताकि बाएं से दाएं काम कर रहे प्रकार की खोज हो सके। धन्यवाद!
पीटर शमिज़

जवाबों:


28

हम गठबंधन कर सकते हैं कि स्काला में एक टर्नरी ऑपरेटर को कैसे परिभाषित किया जाए जो अग्रणी टोकन को संरक्षित करता है? इस विकल्प के जवाब में वैल्यू रैपिंग एक अच्छा पैटर्न है? लेना

scala>   "Hi".getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res0: String = String

scala> List.getClass.getSimpleName |> {x => x.endsWith("$") ? x.init | x}
res1: String = List

क्या यह आपकी आवश्यकताओं के लिए पर्याप्त है?


मेरे मन में जो कुछ है उसके बहुत करीब। अच्छा दृष्टिकोण। मैं उस बारे में सोचूंगा। बहुत पहले कोड से बचने का मेरा कारण valनिम्नलिखित if-स्टेटमेंट के लिए अस्थायी नहीं होने में अधिक संक्षिप्त होना था : इसे एक पंक्ति में समझदारी से करें, जैसे कि एक के दिमाग में है।
पीटर शमित्ज़

125

से टोनी मॉरिस लैम्ब्डा ब्लॉग :

मैं इस सवाल को बहुत सुनता हूं। हाँ यह करता है। इसके बजाय c ? p : q, यह लिखा हैif(c) p else q

यह बेहतर नहीं हो सकता है। शायद आप इसे जावा के समान सिंटैक्स का उपयोग करके लिखना चाहते हैं। अफसोस की बात है, आप नहीं कर सकते। इसका कारण यह है कि :एक वैध पहचानकर्ता नहीं है। डरो नहीं, |है! क्या आप इसके लिए समझौता करेंगे?

c ? p | q

फिर आपको निम्नलिखित कोड की आवश्यकता होगी। =>तर्कों पर कॉल-बाय-नाम ( ) एनोटेशन पर ध्यान दें। जावा के टर्नरी ऑपरेटर को फिर से लिखने के लिए इस मूल्यांकन रणनीति की आवश्यकता है। यह जावा में ही नहीं किया जा सकता है।

case class Bool(b: Boolean) {   
  def ?[X](t: => X) = new {
    def |(f: => X) = if(b) t else f   
  } 
}

object Bool {   
  implicit def BooleanBool(b: Boolean) = Bool(b) 
}

यहां एक नया ऑपरेटर का उपयोग करके एक उदाहरण है जिसे हमने अभी परिभाषित किया है:

object T {   val condition = true

  import Bool._

  // yay!   
  val x = condition ? "yes" | "no"
}

मज़े करो ;)


हाँ, मैं इस से पहले देखा है, लेकिन अंतर यह है कि एक मैं में एक तर्क के रूप (का मूल्यांकन) मेरी पहली अभिव्यक्ति के मूल्य है thenऔर elseखंड।
पीटर शमिज़

5
मैंने if(c) p else qदृष्टिकोण लिया ... ब्रेसिज़ की कमी ने मुझे एक स्पर्श असहज बना दिया, लेकिन यह सिर्फ एक स्टाइल की बात है
rjohnston

17

रेक्स केर का जवाब मूल स्काला में व्यक्त किया गया है:

"Hi".getClass.getSimpleName match {
  case x if x.endsWith("$") => x.init
  case x => x
}

हालांकि मुझे यकीन नहीं है कि अगर आप निर्माण करना चाहते हैं तो आप किस हिस्से का अनुकूलन करना चाहते हैं।


बहुत सीधे तरीके से। कभी-कभी एक दैनिक उपयोग मैच / केस स्टेटमेंट के बारे में भूल जाता है। मैं सिर्फ एक पंक्ति टर्नरी if then elseमुहावरे से जुड़ा रहा, लेकिन यह वास्तव में हल करने के लिए एक बुद्धिमान तरीका है।
पीटर शमित्ज़

1
पैटर्न दो से अधिक शाखाओं से आसानी से मेल खाता है।
राफेल


0

चूँकि: अपने आप से एक मान्य ऑपरेटर नहीं होगा, जब तक आप ठीक नहीं होते, जब तक कि वह हमेशा पीछे की टिक के साथ भागने से नहीं बचता :, आप किसी अन्य व्यक्ति के साथ जा सकते हैं, जैसे "।" जैसा कि ऊपर दिए गए उत्तर में है। लेकिन एक बकरी के साथ एल्विस के बारे में कैसे? ::

implicit class Question[T](predicate: => Boolean) {
  def ?(left: => T) = predicate -> left
}
implicit class Colon[R](right: => R) {
  def ::[L <% R](pair: (Boolean, L)): R = if (q._1) q._2 else right
}
val x = (5 % 2 == 0) ? 5 :: 4.5

यदि आपके पास मान हैं तो निश्चित रूप से यह फिर से काम नहीं करेगा, क्योंकि उनके पास :: ऑपरेटर खुद हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.