I am working on a library which depends on Scala 2.9 but only for a minor feature. I would like to propose version compatible with 2.8, but I don't want to maintain two code branch. Since I'm using SBT, I would like to benefits from it cross-compilation features.
However I don't know is there is a way to provide an equivalent of conditional compilation, to include a piece of code only if Scala 2.9 is used. Reflexivity could be an option (but how?).
Edit: The features I am using in 2.9 are the new sys package object.
I got it with reflection. So if I want to get the sys.SystemProperties, I can do:
try {
val k = java.lang.Class.forName("scala.sys.package$")
val m = k.getMethod( "props" )
// etc.
} catch {
case _ => throw new UnsupportedOperationException("Only available with Scala 2.9")
}
But it is so boring and ugly that I think I will drop those features...
Read this blog post, which describes how to do it with metaprogramming:
http://michid.wordpress.com/2008/10/29/meta-programming-with-scala-conditional-compilation-and-loop-unrolling/
Related
I have created empty instance of my object and then initialise it using run time values. Implementation was based on scala.concurrent.util.Unsafe in Scala 2.11 and it worked fine.
I understand Unsafe is bad and hence has been deprecated in Scala 2.12.
If it's deprecated then what's equivalent of Unsafe in Scala 2.12?
Assuming you're running on a JVM where sun.misc.Unsafe is still available (this will limit which JVMs you can run on, but so did using scala.concurrent.util.Unsafe so no immediate loss):
val unsafeInstance = // use in place of Scala 2.11 usages of scala.concurrent.util.Unsafe.instance
classOf[sun.misc.Unsafe]
.getDeclaredFields
.filter(_.getType == classOf[sun.misc.Unsafe])
.headOption
.map { field =>
field.setAccessible(true)
field.get(null).asInstanceOf[sun.misc.Unsafe]
}
.getOrElse { throw new IllegalStateException("Can't find instance of sun.misc.Unsafe") }
Code is very slightly adapted from the Scala 2.11 source.
It's possible that this is an instance of spending so much time thinking about "could" that one didn't think about "should".
I just wonder if I have messed something up or is it just unavoidable pain of using Scala. I wanted to test out slick so I decided to run activator-play-slick-angularjs example from Lightbend. Unfortunatelly I get syntax errors while using
lazy protected val empTableQuery: TableQuery[EmployeeTable] = TableQuery[EmployeeTable]
in any possible way. In filtering examples, the type I am required by Scala plugin to use is Any e. g.
def delete(id: Int): Future[Int] = db.run { empTableQuery.filter(_.id === id).delete }
_.id part yields syntax error. I bet that I am just missing something because I can't imagine a single developer willing to work in 2017 without syntax assistance from IDE.
In case somebody met this problem in future - in this example EmployeeTable is defined with private[EmployeeTable] what makes in not visible in EmployeeRepository class. Just skip the private[EmployeeTable] part in class definition to make everything work smoothly.
Update
Play 2.0's Scala version will feature ANORM, which seems similar to Querulous in that both are JDBC wrappers and not ORMs. Here's ANORM query coercion at work with a parser combinator:
SQL("""
select * from Country c
join CountryLanguage l on l.CountryCode = c.Code
where c.code = 'FRA';
"""
).as(
str("name") ~< spanM(
by=str("code"), str("language") ~< str("isOfficial")
) ^^ {
case country~languages =>
SpokenLanguages(
country,
languages.collect { case lang~"T" => lang } headOption,
languages.collect { case lang~"F" => lang }
)
} ?
)
The multi-line query """ sql """ is nice, I like that, but the coercion, please, no ;-) In Groovy, bean coercion with the same query is a 1-liner:
List[Country] c = sql.rows("select * from country")?.collect{ it.toRowResult() as Country }
the null safe operator (?.might-be-null) in groovy is quite convenient, scala seems to require the Some() Option[] combo to deal with possible null outcomes. Do Scala coders like null handling in Scala?
I guess the general thrust of this post is: can Scala provide scripting language concision while retaining compiler type safe code? Given that Scala is perhaps more powerful/expressive than C# (unintentional flame), then a full blown Scala LINQ must be possible. Furthermore, since Scala straddles the functional and OO paradigms, then it must also be able to achieve Groovy level concision (for example, the 1-liner query-bean-coercion above).
If these assumptions are true, then why do the existing scala ORMs and jdbc wrappers require so much boilerplate compared to groovy and LINQ on C#? Obviously I am an idealist looking for bare bones DSLs where implementations are either incredibly concise, or closely mirror the underlying language they represent (as in LINQ-to-SQL).
Original
Have been taking a run through the various Scala ORMs (squeryl, daomapper, couple others will fill in later) and SQL helper frameworks (querulous so far)
Being new to Scala and strongly typed languages in general, one thing that leaps out at me is the need to specify the type (String, Int, etc.) of each column in every query result.
About to get on an overnight train here, but this struck me just now, so putting it out there (will add some examples when I get back online again to make this a bit of less of a ramble)
For now, a quick one from Querulous's readme on github:
val users = queryEvaluator.select("SELECT * FROM users WHERE id IN (?) OR name = ?", List(1,2,3), "Jacques") { row =>
new User(row.getInt("id"), row.getString("name"))
}
While I understand that the compiler needs to know the type of every "object" you work with, it seems non-DRY to have to specify "row.getInt('id')" when the domain class itself already declares that id is of type Int.
So, coming from a fair degree of ignorance, I will ask, why do Scala ORMs and SQL helper frameworks not provide developers with an implementation model that allows for inferred or implicit result sets?
Just to put in context, I am coming from Grails, which has an, imo, excellent domain/validation model among other framework nice-to-haves, but suffers from dynamic language time wasting fat-finger typing (startup time is painful as well) which is why I am exploring Scala frameworks.
See Scala Integrated Query as I understand it is scheduled to be integrated in the typesafe stack as Scala Language Integrated Connection Kit (SLICK)
In my quest to generate new code in a Scala compiler plugin, I have now created working classes. The next logical step is to put those classes in a new, non-existing package. In Java, a package is basically a directory name, but in Scala a package seems much more complicated. So far I haven't found/recognized an example where a compiler plugin creates a new package.
At my current level of understanding, I would think that I would need to create first a package symbol with:
parentPackage.newPackage(...)
// ...
and than later create a Tree for the package with PackageDef. But PackageDef doesn't take the symbol as parameter, as one would expect, and searching for:
Scala newPackage PackageDef
returned nothing useful. So it seems that I don't need to do those two steps together. Possibly one is done for my by the compiler, but I don't know which one. So far, what I have looks like this:
val newPkg = parentPackage.newPackage(NoPosition, newTermName(name))
newPkg.moduleClass.setInfo(new PackageClassInfoType(new Scope,
newPkg.moduleClass))
newPkg.setInfo(newPkg.moduleClass.tpe)
parentPackage.info.decls.enter(newPkg)
// ...
val newPkgTree = PackageDef(Ident(newPkg.name), List(ClassDef(...)))
I think my answer to your other question should answer this one as well:
How to add a new Class in a Scala Compiler Plugin?
There are a few cases of source incompatibilities with Scala 2.8.0. For example, creating an anonymous Seq once required defining the abstract def elements : Iterator[A], which is now called def iterator : Iterator[A].
To me, a "brute force" solution is to create two branches that align to the different major scala versions.
Are there general techniques so that code like this will compile under both systems?
// Note: this code resembles techniques used by xml.NodeSeq
trait FooSeq extends Seq[ Foo ] {
def internal : Seq[ Foo ]
def elements = internal.elements
def iterator = internal.iterator // Only compiles in 2.8
// need to remove for 2.7.X
}
There are a few cases where usage is simply different and you must change. But in almost all cases--such as the elements code above--the 2.7 style is simply deprecated in 2.8, not gone altogether. If you're okay leaving your 2.8 users with deprecation warnings (edit: if they compile your code, otherwise you'll just have the warnings yourself), just implement the new features in terms of the old:
def iterator = internal.elements
Otherwise, I would recommend what you call the brute force solution. Use a sufficiently clever VCS so that you don't actually have to write much code twice (Git, Bazaar, Mercurial) and branch.