I am trying to execute the below code in intellij and getting error. Please help
code
package retcalc
object RetCalc extends App {
def futureCapital(interestRate: Double, nbOfMonths: Int, netIncome: Int, currentExpenses:
Int, initialCapital: Double): Double = {
val monthlySavings = netIncome - currentExpenses
def nextCapital(accumulated: Double, month: Int): Double =
accumulated * (1 + interestRate) + monthlySavings
(0 until nbOfMonths).foldLeft(initialCapital)(nextCapital)
}
}
Test Case
package retcalc
import org.scalactic.{Equality, TolerantNumerics, TypeCheckedTripleEquals}
import org.scalatest.{Matchers, WordSpec}
class RetCalcSpec extends WordSpec with Matchers with TypeCheckedTripleEquals {
implicit val doubleEquality: Equality[Double] =
TolerantNumerics.tolerantDoubleEquality(0.0001)
"RetCalc.futureCapital" should {
"calculate the amount of savings I will have in n months" in {
val actual = RetCalc.futureCapital(
interestRate = 0.04 / 12, nbOfMonths = 25 * 12,
netIncome = 3000, currentExpenses = 2000,
initialCapital = 10000)
val expected = 541267.1990
actual should ===(expected)
}
}
}
Error
overloaded method should with alternatives:
(inv: org.scalautils.TripleEqualsInvocationOnInterval[Double])Unit <and>
[U](inv: org.scalautils.TripleEqualsInvocation[U])(implicit constraint: org.scalautils.EqualityConstraint[Double,U]): Unit <and>
(notWord: RetCalcSpec.this.NotWord)RetCalcSpec.this.ResultOfNotWordForNumeric[Double] <and>
(rightMatcherGen1: RetCalcSpec.this.MatcherGen1[Double,org.scalautils.Equality])(implicit equality: org.scalautils.Equality[Double]): Unit <and>
(rightMatcherX3: org.scalatest.matchers.Matcher[Double])Unit
cannot be applied to (org.scalactic.TripleEqualsSupport.TripleEqualsInvocation[Double])
actual should ===(expected)
----scalaVersion := "2.13.6"----
with below I am unable to import Matchers and WordSpec
Scala 3.2.x went through modularisation process so imports changed a bit, so with
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % "test"
try the following imports
import org.scalactic.{Equality, TolerantNumerics, TypeCheckedTripleEquals}
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.matchers.should.Matchers
class RetCalcSpec extends AnyWordSpec with Matchers with TypeCheckedTripleEquals { ...
I was also not able to replicate the issue with ScalaTest 3.1.0, so you could try that pre-modularisation version if you wish to keep the imports you have currently.
I believe that === is not a usable matcher here.
The last line should read:
actual shouldBe expected
Related
I have some code that works in Scala 2.{10,11,12,13} that I'm now trying to convert to Scala 3. Scala 3 does Enumeration differently than Scala 2. I'm trying to figure out how to convert the following code that interacts with play-json so that it will work with Scala 3. Any tips or pointers to code from projects that have already crossed this bridge?
// Scala 2.x style code in EnumUtils.scala
import play.api.libs.json._
import scala.language.implicitConversions
// see: http://perevillega.com/enums-to-json-in-scala
object EnumUtils {
def enumReads[E <: Enumeration](enum: E): Reads[E#Value] =
new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsString(s) => {
try {
JsSuccess(enum.withName(s))
} catch {
case _: NoSuchElementException =>
JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
}
case _ => JsError("String value expected")
}
}
implicit def enumWrites[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
implicit def enumFormat[E <: Enumeration](enum: E): Format[E#Value] = {
Format(EnumUtils.enumReads(enum), EnumUtils.enumWrites)
}
}
// ----------------------------------------------------------------------------------
// Scala 2.x style code in Xyz.scala
import play.api.libs.json.{Reads, Writes}
object Xyz extends Enumeration {
type Xyz = Value
val name, link, unknown = Value
implicit val enumReads: Reads[Xyz] = EnumUtils.enumReads(Xyz)
implicit def enumWrites: Writes[Xyz] = EnumUtils.enumWrites
}
As an option you can switch to jsoniter-scala.
It supports enums for Scala 2 and Scala 3 out of the box.
Also it has handy derivation of safe and efficient JSON codecs.
Just need to add required libraries to your dependencies:
libraryDependencies ++= Seq(
// Use the %%% operator instead of %% for Scala.js and Scala Native
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "2.13.5",
// Use the "provided" scope instead when the "compile-internal" scope is not supported
"com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "2.13.5" % "compile-internal"
)
And then derive a codec and use it:
import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._
implicit val codec: JsonValueCodec[Xyz.Xyz] = JsonCodecMaker.make
println(readFromString[Xyz.Xyz]("\"name\""))
BTW, you can run the full code on Scastie: https://scastie.scala-lang.org/Evj718q6TcCZow9lRhKaPw
i am writing a macro to get annotations from a 'Class'
inline def getAnnotations(clazz: Class[?]): Seq[Any] = ${ getAnnotationsImpl('clazz) }
def getAnnotationsImpl(expr: Expr[Class[?]])(using Quotes): Expr[Seq[Any]] =
import quotes.reflect.*
val cls = expr.valueOrError // error: value value is not a member of quoted.Expr[Class[?]]
val tpe = TypeRepr.typeConstructorOf(cls)
val annotations = tpe.typeSymbol.annotations.map(_.asExpr)
Expr.ofSeq(annotations)
but i get an error when i get class value from expr parameter
#main def test(): Unit =
val cls = getCls
val annotations = getAnnotations(cls)
def getCls: Class[?] = Class.forName("Foo")
is it possible to get annotations of a Class at compile time by this macro ?!
By the way, eval for Class[_] doesn't work even in Scala 2 macros: c.eval(c.Expr[Class[_]](clazz)) produces
java.lang.ClassCastException:
scala.reflect.internal.Types$ClassNoArgsTypeRef cannot be cast to java.lang.Class.
Class[_] is too runtimy thing. How can you extract its value from its tree ( Expr is a wrapper over tree)?
If you already have a Class[?] you should use Java reflection rather than Scala 3 macros (with Tasty reflection).
Actually, you can try to evaluate a tree from its source code (hacking multi-staging programming and implementing our own eval instead of forbidden staging.run). It's a little similar to context.eval in Scala 2 macros (but we evaluate from a source code rather than from a tree).
import scala.quoted.*
object Macro {
inline def getAnnotations(clazz: Class[?]): Seq[Any] = ${getAnnotationsImpl('clazz)}
def getAnnotationsImpl(expr: Expr[Class[?]])(using Quotes): Expr[Seq[Any]] = {
import quotes.reflect.*
val str = expr.asTerm.pos.sourceCode.getOrElse(
report.errorAndAbort(s"No source code for ${expr.show}")
)
val cls = Eval[Class[?]](str)
val tpe = TypeRepr.typeConstructorOf(cls)
val annotations = tpe.typeSymbol.annotations.map(_.asExpr)
Expr.ofSeq(annotations)
}
}
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.{Driver, util}
import dotty.tools.io.{VirtualDirectory, VirtualFile}
import java.net.URLClassLoader
import java.nio.charset.StandardCharsets
import dotty.tools.repl.AbstractFileClassLoader
object Eval {
def apply[A](str: String): A = {
val content =
s"""
|package $$generated
|
|object $$Generated {
| def run = $str
|}""".stripMargin
val sourceFile = util.SourceFile(
VirtualFile(
name = "$Generated.scala",
content = content.getBytes(StandardCharsets.UTF_8)),
codec = scala.io.Codec.UTF8
)
val files = this.getClass.getClassLoader.asInstanceOf[URLClassLoader].getURLs
val depClassLoader = new URLClassLoader(files, null)
val classpathString = files.mkString(":")
val outputDir = VirtualDirectory("output")
class DriverImpl extends Driver {
private val compileCtx0 = initCtx.fresh
val compileCtx = compileCtx0.fresh
.setSetting(
compileCtx0.settings.classpath,
classpathString
).setSetting(
compileCtx0.settings.outputDir,
outputDir
)
val compiler = newCompiler(using compileCtx)
}
val driver = new DriverImpl
given Context = driver.compileCtx
val run = driver.compiler.newRun
run.compileSources(List(sourceFile))
val classLoader = AbstractFileClassLoader(outputDir, depClassLoader)
val clazz = Class.forName("$generated.$Generated$", true, classLoader)
val module = clazz.getField("MODULE$").get(null)
val method = module.getClass.getMethod("run")
method.invoke(module).asInstanceOf[A]
}
}
package mypackage
import scala.annotation.experimental
#experimental
class Foo
Macro.getAnnotations(Class.forName("mypackage.Foo")))
// new scala.annotation.internal.SourceFile("/path/to/src/main/scala/mypackage/Foo.scala"), new scala.annotation.experimental()
scalaVersion := "3.1.3"
libraryDependencies += scalaOrganization.value %% "scala3-compiler" % scalaVersion.value
How to compile and execute scala code at run-time in Scala3?
(compile time of the code expanding macros is the runtime of macros)
Actually, there is even a way to evaluate a tree itself (not its source code). Such functionality exists in Scala 3 compiler but is deliberately blocked because of phase consistency principle. So this to work, the code expanding macros should be compiled with a compiler patched
https://github.com/DmytroMitin/dotty-patched
scalaVersion := "3.2.1"
libraryDependencies += scalaOrganization.value %% "scala3-staging" % scalaVersion.value
// custom Scala settings
managedScalaInstance := false
ivyConfigurations += Configurations.ScalaTool
libraryDependencies ++= Seq(
scalaOrganization.value % "scala-library" % "2.13.10",
scalaOrganization.value %% "scala3-library" % "3.2.1",
"com.github.dmytromitin" %% "scala3-compiler-patched-assembly" % "3.2.1" % "scala-tool"
)
import scala.quoted.{Expr, Quotes, staging, quotes}
object Macro {
inline def getAnnotations(clazz: Class[?]): Seq[String] = ${impl('clazz)}
def impl(expr: Expr[Class[?]])(using Quotes): Expr[Seq[String]] = {
import quotes.reflect.*
given staging.Compiler = staging.Compiler.make(this.getClass.getClassLoader)
val tpe = staging.run[Any](expr).asInstanceOf[TypeRepr]
val annotations = Expr(tpe.typeSymbol.annotations.map(_.asExpr.show))
report.info(s"annotations=${annotations.show}")
annotations
}
}
Normally, for expr: Expr[A] staging.run(expr) returns a value of type A. But Class is specific. For expr: Expr[Class[_]] inside macros it returns a value of type dotty.tools.dotc.core.Types.CachedAppliedType <: TypeRepr. That's why I had to cast.
In Scala 2 this also would be c.eval(c.Expr[Any](/*c.untypecheck*/(clazz))).asInstanceOf[Type].typeSymbol.annotations because for Class[_] c.eval returns scala.reflect.internal.Types$ClassNoArgsTypeRef <: Type.
https://github.com/scala/bug/issues/12680
Consider the default codec as offered in the io package.
implicitly[io.Codec].name //res0: String = UTF-8
It's a "low priority" implicit so it's easy to override without ambiguity.
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //res1: String = US-ASCII
It's also easy to raise its priority level.
import io.Codec.fallbackSystemCodec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //won't compile: ambiguous implicit values
But can we go in the opposite direction? Can we create a low level implicit that disables ("ambiguates"?) the default? I've been looking at the priority equation and playing around with low priority implicits but I've yet to create something ambiguous to the default.
If I understand correctly you want to check at compile time that there is local implicit io.Codec ("higher-priority") or produce compile error otherwise. This can be done with macros (using compiler internals).
import scala.language.experimental.macros
import scala.reflect.macros.{contexts, whitebox}
object Macros {
def localImplicitly[A]: A = macro impl[A]
def impl[A: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
import c.universe._
val context = c.asInstanceOf[contexts.Context]
val global: context.universe.type = context.universe
val analyzer: global.analyzer.type = global.analyzer
val callsiteContext = context.callsiteTyper.context
val tpA = weakTypeOf[A]
val localImplicit = new analyzer.ImplicitSearch(
tree = EmptyTree.asInstanceOf[global.Tree],
pt = tpA.asInstanceOf[global.Type],
isView = false,
context0 = callsiteContext.makeImplicit(reportAmbiguousErrors = true),
pos0 = c.enclosingPosition.asInstanceOf[global.Position]
) {
override def searchImplicit(
implicitInfoss: List[List[analyzer.ImplicitInfo]],
isLocalToCallsite: Boolean
): analyzer.SearchResult = {
if (isLocalToCallsite)
super.searchImplicit(implicitInfoss, isLocalToCallsite)
else analyzer.SearchFailure
}
}.bestImplicit
if (localImplicit.isSuccess)
localImplicit.tree.asInstanceOf[c.Tree]
else c.abort(c.enclosingPosition, s"no local implicit $tpA")
}
}
localImplicitly[io.Codec].name // doesn't compile
// Error: no local implicit scala.io.Codec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
localImplicitly[Codec].name // US-ASCII
import io.Codec.fallbackSystemCodec
localImplicitly[Codec].name // UTF-8
import io.Codec.fallbackSystemCodec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
localImplicitly[Codec].name // doesn't compile
//Error: ambiguous implicit values:
// both value betterCodec in object App of type => scala.io.Codec
// and lazy value fallbackSystemCodec in trait LowPriorityCodecImplicits of type => //scala.io.Codec
// match expected type scala.io.Codec
Tested in 2.13.0.
libraryDependencies ++= Seq(
scalaOrganization.value % "scala-reflect" % scalaVersion.value,
scalaOrganization.value % "scala-compiler" % scalaVersion.value
)
Still working in Scala 2.13.10.
Scala 3 implementation
import scala.quoted.{Expr, Quotes, Type, quotes}
import dotty.tools.dotc.typer.{Implicits => dottyImplicits}
inline def localImplicitly[A]: A = ${impl[A]}
def impl[A: Type](using Quotes): Expr[A] = {
import quotes.reflect.*
given c: dotty.tools.dotc.core.Contexts.Context =
quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
val typer = c.typer
val search = new typer.ImplicitSearch(
TypeRepr.of[A].asInstanceOf[dotty.tools.dotc.core.Types.Type],
dotty.tools.dotc.ast.tpd.EmptyTree,
Position.ofMacroExpansion.asInstanceOf[dotty.tools.dotc.util.SourcePosition].span
)
def eligible(contextual: Boolean): List[dottyImplicits.Candidate] =
if contextual then
if c.gadt.isNarrowing then
dotty.tools.dotc.core.Contexts.withoutMode(dotty.tools.dotc.core.Mode.ImplicitsEnabled) {
c.implicits.uncachedEligible(search.wildProto)
}
else c.implicits.eligible(search.wildProto)
else search.implicitScope(search.wildProto).eligible
val searchImplicitMethod = classOf[typer.ImplicitSearch]
.getDeclaredMethod("searchImplicit", classOf[List[dottyImplicits.Candidate]], classOf[Boolean])
searchImplicitMethod.setAccessible(true)
def implicitSearchResult(contextual: Boolean) =
searchImplicitMethod.invoke(search, eligible(contextual), contextual)
.asInstanceOf[dottyImplicits.SearchResult]
.tree.asInstanceOf[ImplicitSearchResult]
implicitSearchResult(true) match {
case success: ImplicitSearchSuccess => success.tree.asExprOf[A]
case failure: ImplicitSearchFailure =>
report.errorAndAbort(s"no local implicit ${Type.show[A]}: ${failure.explanation}")
}
}
Scala 3.2.0.
Sort of, yes.
You can do this by creating a 'newtype'. I.e. a type that is simply a proxy to io.Codec, and wraps the instance. This means that you also need to change all your implicit arguments from io.Codec to CodecWrapper, which may not be possible.
trait CodecWraper {
def orphan: io.Codec
}
object CodecWrapper {
/* because it's in the companion, this will have the highest implicit resolution priority. */
implicit def defaultInstance: CodecWrapper =
new CodecWrapper {
def orphan = new io.Codec { /* your default implementation here */ }
}
}
}
import io.Codec.fallbackSystemCodec
implicitly[CodecWrapper].orphan // io.Codec we defined above - no ambiguity
Because of the odd behaviour in method foo I cannot write methods like bar,
which I need:
import breeze.linalg.DenseMatrix
import breeze.linalg.DenseVector
class Test {
val dim = 3
val X:DenseMatrix[Double] = DenseMatrix.rand(dim,dim)
val u:DenseVector[Double] = DenseVector.fill(dim){1.0}
def foo:Unit = {
val i=0;
val row_i:DenseVector[Double] = X(i,::).t // OK
val s = u(i)+u(i) // OK
val j:Integer = 0
val row_j:DenseVector[Double] = X(j,::).t // does not compile (A)
val a = u(j)+u(j) // does not compile (B)
}
def bar(i:Integer):Double = u(i)+u(i) // does not compile (C)
}
Is there a workaround?
Thanks in advance for all replies.
Compilation errors:
(A) could not find implicit value for parameter canSlice:
breeze.linalg.support.CanSlice2[breeze.linalg.DenseMatrix[Double],Integer,collection.immutable.::.type,Result]
not enough arguments for method apply: (implicit canSlice:
breeze.linalg.support.CanSlice2[breeze.linalg.DenseMatrix[Double],Integer,collection.immutable.::.type,Result])
Result in trait TensorLike. Unspecified value parameter canSlice.
(B), (C)
could not find implicit value for parameter canSlice:
breeze.linalg.support.CanSlice[breeze.linalg.DenseVector[Double],Integer,Result]
not enough arguments for method apply: (implicit canSlice: breeze.linalg.support.CanSlice[breeze.linalg.DenseVector[Double],Integer,Result])Result
in trait TensorLike. Unspecified value parameter canSlice.
First off: convert your Integer to Int . That would take care of at least the first compilation error. Following update to your code does compile
import breeze.linalg.DenseMatrix
import breeze.linalg.DenseVector
import breeze.linalg.DenseMatrix
import breeze.linalg.DenseVector
class Test {
val dim = 3
val X:DenseMatrix[Double] = DenseMatrix.rand(dim,dim)
val u:DenseVector[Double] = DenseVector.fill(dim){1.0}
def foo:Unit = {
val i=0;
val row_i:DenseVector[Double] = X(i,::).t // OK
val s = u(i)+u(i) // OK
val j:Int = 0
val row_j:DenseVector[Double] = X(j,::).t // does not compile (A)
val a = u(j)+u(j) // does not compile (B)
}
def bar(i:Int):Double = u(i)+u(i) // does not compile (C)
}
From the repl:
// Exiting paste mode, now interpreting.
import breeze.linalg.DenseMatrix
import breeze.linalg.DenseVector
defined class Test
So your other errors also disappear for me (scala 2.11.8). Let me know if you have further issues.
I want to return list of json objects based on my case class objects.
Following is my spray router, which returns list of 'Appointment' objects.
trait GatewayService extends HttpService with SLF4JLogging {
import com.sml.apigw.protocols.AppointmentProtocol._
import spray.httpx.SprayJsonSupport._
implicit def executionContext = actorRefFactory.dispatcher
val router =
pathPrefix("api" / "v1") {
path("appointments") {
get {
complete {
val a = new Appointment("1", "2")
val l = List(a, a, a, a)
l
}
}
}
}
}
}
Following is the 'AppointmentProtocol'
import spray.json.DefaultJsonProtocol
case class Appointment(id: String, patient: String)
object AppointmentProtocol extends DefaultJsonProtocol {
implicit val appointmentFormat = jsonFormat2(Appointment.apply)
}
It gives the compilation error 'expression type of List[Appointment] doesn't confirms to expected type toResponseMarshallable'
Maybe you missed something in your example, but my brain-based compiler is telling me that your code should throw a compilation error since any directive in Spray requires a result of type Route, as i can see you have a List[Appointment]. Please read this article on Routes. Your route structure should be completed with complete, so i assume the this way would solve your issue:
get {
val a = new Appointment("1", "2")
val l = List(a, a, a, a)
complete(l)
}
Please note a complete directive which wraps the list. This should help, otherwise please provide the tree with resolved implicits by compiling your code with the flag -Xprint:typer, that should show where the problem with implicits is.
I think that you should use this library spray-json depending on your version of spay this will be your import and do not forget to add the imports to your code:
import MyJsonProtocol._
import spray.json._
for that be sure that you have imported:
libraryDependencies += "io.spray" %% "spray-json" % "1.3.2"
THen you can conver an object whith this, I also have problems having the case class in the same file but this was using testing:
case class Color(name: String, red: Int, green: Int, blue: Int)
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val colorFormat = jsonFormat4(Color)
}
import MyJsonProtocol._
import spray.json._
val json = Color("CadetBlue", 95, 158, 160).toJson
val color = json.convertTo[Color]
and the list:
val jsonAst = List(1, 2, 3).toJson
This are extracted examples from the spray-json github project