मान लीजिए मैं इस तरह फाइलों के साथ, तीन उप-परियोजनाओं के साथ एक स्काला परियोजना है:पठन संसाधनों
foo/src/main/scala/Foo.scala
foo/src/main/resources/foo.txt
bar/src/main/scala/Bar.scala
bar/src/main/resources/bar.txt
baz/src/main/scala/Baz.scala
baz/src/main/resources/baz.txt
Foo.scala
एक सरल मैक्रो कि किसी दिए गए पथ पर एक संसाधन पढ़ता शामिल हैं:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object Foo {
def countLines(path: String): Option[Int] = macro countLines_impl
def countLines_impl(c: Context)(path: c.Expr[String]) = {
import c.universe._
path.tree match {
case Literal(Constant(s: String)) => Option(
this.getClass.getResourceAsStream(s)
).fold(reify(None: Option[Int])) { stream =>
val count = c.literal(io.Source.fromInputStream(stream).getLines.size)
reify(Some(count.splice))
}
case _ => c.abort(c.enclosingPosition, "Need a literal path!")
}
}
}
संसाधन खोला जा सकता है, तो countLines
लाइनों की संख्या देता है; अन्यथा यह खाली है।
object Bar extends App {
println(Foo.countLines("/foo.txt"))
println(Foo.countLines("/bar.txt"))
println(Foo.countLines("/baz.txt"))
}
और::
object Baz extends App {
println(Foo.countLines("/foo.txt"))
println(Foo.countLines("/bar.txt"))
println(Foo.countLines("/baz.txt"))
}
संसाधनों की सामग्री को वास्तव में इस सवाल के प्रयोजनों के लिए कोई फर्क नहीं पड़ता
अन्य दो स्काला स्रोत फ़ाइलों सिर्फ इस मैक्रो कहते हैं।
यह एक Maven परियोजना है, तो मैं आसानी से इसे कॉन्फ़िगर कर सकते हैं ताकि जड़ परियोजना तीन उप-परियोजनाओं एकत्रित और baz
bar
, जो foo
पर निर्भर करता है पर निर्भर करता है। गोर विवरण के लिए this Gist देखें।
मैवेन के साथ सब कुछ अपेक्षित काम करता है। Bar
foo
और bar
के लिए संसाधनों देख सकते हैं:
Some(1)
Some(2)
None
और Baz
उन सभी को देख सकते हैं:
Some(1)
Some(2)
Some(3)
अब मैं एसबीटी के साथ एक ही बात की कोशिश:
import sbt._
import Keys._
object MyProject extends Build {
lazy val root: Project = Project(
id = "root", base = file("."),
settings = commonSettings
).aggregate(foo, bar, baz)
lazy val foo: Project = Project(
id = "foo", base = file("foo"),
settings = commonSettings
)
lazy val bar: Project = Project(
id = "bar", base = file("bar"),
settings = commonSettings,
dependencies = Seq(foo)
)
lazy val baz: Project = Project(
id = "baz", base = file("baz"),
settings = commonSettings,
dependencies = Seq(bar)
)
def commonSettings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.10.2",
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _)
)
}
लेकिन अब Bar
केवल foo
में संसाधन देख सकते हैं:
Some(1)
None
None
और Baz
केवल foo
और bar
देख सकते हैं:
Some(1)
Some(2)
None
यहाँ क्या हो रहा है? यह एसबीटी बिल्ड फ़ाइल मुझे मेवेन कॉन्फ़िगरेशन का एक सुंदर शाब्दिक अनुवाद प्रतीत होता है। मुझे bar
प्रोजेक्ट में कंसोल खोलने में कोई समस्या नहीं है और उदाहरण के लिए /bar.txt
पढ़ना है, तो मैक्रो को कॉल करते समय इन परियोजनाओं को अपने संसाधन क्यों नहीं देख सकते हैं?
@ 0__: 13,
<+=
और<++=
नया मैक्रो आधारित सिंटेक्स के लिए अनावश्यक (और गैर-दस्तावेजी) धन्यवाद कर रहे हैं धन्यवाद, मैं उल्लेख किया जाना चाहिए था कि-हाँ, वे वहाँ हो (और गैर से उपलब्ध हैं कंसोल और परियोजना स्रोत में मैक्रो कोड दोनों)। –मैक्रो विशेषज्ञ नहीं, लेकिन यह एक वर्ग लोडर मुद्दा आईएमओ होना चाहिए। वास्तव में 'this.getClass.getResourceAsStream' निष्पादित क्या बिंदुओं पर है? शायद आपको क्लास लोडर संदर्भ के रूप में संदर्भ या कुछ और उपयोग करने की आवश्यकता है? कोई सुराग नहीं ... –
@ 0__: मुझे लगता है कि यह ऐसा कुछ है, लेकिन मेरे किसी भी झुकाव ने समाधान नहीं मारा, और तथ्य यह है कि यह मेवेन मामले में अपेक्षित काम करता है, मुझे लगता है कि यह कुछ आसान होना चाहिए। –