Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a simple way to define a string constant to be the contents of a file at compile-time (in Scala)?

Tags:

scala

I would like to define a Scala val to be a String whose value is the entire contents of a text file, as read at compile time. So, after compilation, this should just behave as a string constant.

I have the feeling that this should be simple with, e.g., Scala macros, but so far I couldn't work out how to get the String value out simply.

like image 482
Alex Summers Avatar asked Dec 20 '25 16:12

Alex Summers


2 Answers

You could make an sbt source generation task that executes at compile time; here's a simple example copied from those docs. It wouldn't be hard to extend this as needed to just dump file contents into a object's val field.

sourceGenerators in Compile += Def.task {
  val file = (sourceManaged in Compile).value / "demo" / "Test.scala"
  IO.write(file, """object Test extends App { println("Hi") }""")
  Seq(file)
}.taskValue
like image 59
Daenyth Avatar answered Dec 22 '25 07:12

Daenyth


The simple macro. This probably exists as an example somewhere. But I need the exercise.

scala> import reflect.macros.blackbox.Context
import reflect.macros.blackbox.Context

scala> import language.experimental.macros
import language.experimental.macros

scala> import scala.io._
import scala.io._

scala> :pa
// Entering paste mode (ctrl-D to finish)

class S(val c: Context) {
import c._, universe._
def smac(file: c.Expr[String]): c.Expr[String] = file.tree match {
case Literal(Constant(s: String)) =>
val res = Source.fromFile(s, "UTF-8").getLines.mkString("\n")
c.Expr[String](Literal(Constant(res)))
}}

// Exiting paste mode, now interpreting.

defined class S

scala> def f(file: String): String = macro S.smac
defined term macro f: (file: String)String

scala> f("text.txt")
res3: String = Now is the time for jumping over dogs.

Or, quasiquoting the result:

class S(val c: Context) {
import c._, universe._
def smac(file: c.Expr[String]) = file.tree match {
case Literal(Constant(s: String)) =>
val res = Source.fromFile(s, "UTF-8").getLines.mkString("\n")
q"$res"
}}
like image 39
som-snytt Avatar answered Dec 22 '25 06:12

som-snytt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!