मैं सिर्फ देखा है कि आप निराकार की तरह कोई पुस्तकालयों चाहता था। यदि यह कोई सांत्वना है तो यह एक लाइब्रेरी है जो स्काला को अंततः मैक्रोज़ को प्रतिबिंबित करेगी, इसलिए यह चावल को फिर से शुरू किए बिना आपको शुद्ध स्केल के करीब के करीब है।
मुझे लगता है कि मेरे पास ऐसा कुछ हो सकता है जो इससे मदद कर सके। यह एक तरह का भारी समाधान है, लेकिन मुझे लगता है कि यह वही करेगा जो आप पूछ रहे हैं।
यह स्थैतिक एनोटेशन बनाने के लिए शानदार स्कैलेटाटा (http://www.scalameta.org) लाइब्रेरी का उपयोग करता है। आप अपनी केस क्लास को एनोटेट करेंगे और यह इनलाइन मैक्रो आपके कमांड लाइन तर्कों के लिए उपयुक्त स्कोप पार्सर उत्पन्न करेगा।
आपके build.sbt को मैक्रो पैराडाइज प्लगइन के साथ-साथ स्केलेमेटा लाइब्रेरी की आवश्यकता होगी। आप इन्हें अपने प्रोजेक्ट में जोड़ सकते हैं।
addCompilerPlugin("org.scalameta" % "paradise" % paradise cross CrossVersion.full)
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % meta % Provided,
)
एक बार जब आप अपने निर्माण करने के लिए उन deps जोड़ लिया है क्या आप मैक्रो के लिए एक अलग प्रोजेक्ट बनाने के लिए होगा।
एक पूरा एसबीटी परियोजना परिभाषा की तरह
lazy val macros = project
.in(file("macros"))
.settings(
addCompilerPlugin("org.scalameta" % "paradise" % paradise cross CrossVersion.full),
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % "1.8.0" % Provided,
)
)
मॉड्यूल में ही "मैक्रो" नाम दिया गया है, तो विचार करेंगे, तो एक वर्ग बना सकते हैं और यहां स्थिर एनोटेशन है।
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.meta._
@compileTimeOnly("@Opts not expanded")
class Opts extends StaticAnnotation {
inline def apply(defn: Any): Any = meta {
defn match {
case q"..$mods class $tname[..$tparams] ..$ctorMods (...$paramss) extends $template" =>
val opttpe = Type.Name(tname.value)
val optName = Lit.String(tname.value)
val opts = paramss.flatten.map {
case param"..${_} $name: ${tpeopt: Option[Type]} = $expropt" =>
val tpe = Type.Name(tpeopt.get.toString())
val litName = Lit.String(name.toString())
val errMsg = Lit.String(s"${litName.value} is required.")
val tname = Term.Name(name.toString())
val targ = Term.Arg.Named(tname, q"x")
q"""
opt[$tpe]($litName)
.required()
.action((x, c) => c.copy($targ))
.text($errMsg)
"""
}
val stats = template.stats.getOrElse(Nil) :+ q"def options: OptionParser[$opttpe] = new OptionParser[$opttpe]($optName){ ..$opts }"
q"""..$mods class $tname[..$tparams] ..$ctorMods (...$paramss) {
import scopt._
..$stats
}"""
}
}
}
इसके बाद आप अपना मुख्य मॉड्यूल अपने मैक्रोज़ मॉड्यूल पर निर्भर करेंगे। तो फिर तुम तो जैसे अपने मामले कक्षाएं टिप्पणी कर सकते हैं ...
@Opts
case class Options(name: String, job: String, age: Int, netWorth: Double, job_title: String)
यह तो संकलन समय पर scopt परिभाषाओं में शामिल करने के लिए अपने मामले वर्ग का विस्तार होगा। यहां एक जेनरेट क्लास ऊपर से जैसा दिखता है।
case class Options(name: String, job: String, age: Int, netWorth: Double, job_title: String) {
import scopt._
def options: OptionParser[Options] = new OptionParser[Options]("Options") {
opt[String]("name").required().action((x, c) => c.copy(name = x)).text("name is required.")
opt[String]("job").required().action((x, c) => c.copy(job = x)).text("job is required.")
opt[Int]("age").required().action((x, c) => c.copy(age = x)).text("age is required.")
opt[Double]("netWorth").required().action((x, c) => c.copy(netWorth = x)).text("netWorth is required.")
opt[String]("job_title").required().action((x, c) => c.copy(job_title = x)).text("job_title is required.")
}
}
यह आपको बॉयलर प्लेट की बचत हो जाना चाहिए, और इनलाइन मैक्रो की अधिक ज्ञान के साथ किसी के लिए कृपया मुझे बताओ करने के लिए मैं इस बेहतर कैसे लिख सकता है के लिए स्वतंत्र महसूस, के बाद से मैं इस पर एक विशेषज्ञ नहीं हूँ।
आप इस बारे में उचित ट्यूटोरियल और दस्तावेज़ीकरण http://scalameta.org/tutorial/#Macroannotations पर देख सकते हैं मुझे इस दृष्टिकोण के बारे में आपके किसी भी प्रश्न का उत्तर देने में भी खुशी है!
मुझे लगता है कि "स्कैला विकल्प पार्सर" से आपका मतलब है [स्कॉप्ट] (https://github.com/scopt/scopt)? – thibr
यदि आप ऐसा करना चाहते हैं तो आप खुद को बेकार बना देंगे। आप 'LabelledGeneric' जैसे कुछ ढूंढ रहे हैं। – Alec
@ एलेक, पहियों को फिर से कार्यान्वित करना पूरी तरह से स्वीकार्य है, जब तक मुझे केवल कोड का एक छोटा टुकड़ा लिखना पड़ेगा। – zinking