Pimp my library on Joda LocalDate does not work - scala

Here I am adding a new method to to LocalDate:
object EnhancedDate {
implicit class EnhancedDate(start: org.joda.time.LocalDate) {
/** Generates dates between start and end - inclusive */
def to(end: org.joda.time.LocalDate): IndexedSeq[org.joda.time.LocalDate] = {
val numberOfDays = Days.daysBetween(start, end.plusDays(1)).getDays()
for (f <- 0 to numberOfDays) yield start.plusDays(f)
}
}
}
and now using it:
import cats.effect.IO
import EnhancedDate.EnhancedDate
def loadCadUsdRates: IO[Map[String, CadInUsd]] = IO {
val start = new org.joda.time.LocalDate(startYear,1,1)
val end = new org.joda.time.LocalDate(endYear+1,1,1).minusDays(1)
start to end map(f) toMap
}
Function f doesn't really matter; you can use identity for all it's worth bc the results are the same.
I use Idea and everything is fine in the IDE (no red underlyings) but when I run it I get this error:
Error:(104, 9) value to is not a member of org.joda.time.LocalDate
start to end map(f) toMap
Now I've used pimp my library before and I'm pretty sure this is the right way to do it, but there must be something about joda date that is incompatible with it... Have you tried pimping Joda LocalDate.. I do not know why this is not working

I'm not exactly sure what is going on here but it's something to do with the declaration being a module with the same name as the implicit class within it. This means that you have two identifiers in scope, both called EnhancedDate and I assume that this must cause resolution ambiguity. It's certainly nothing to do with Joda. One definite workaround is to place your implicit class inside the nearest package object.
package object myPackage {
implicit class EnhancedDate(start: org.joda.time.LocalDate) { ... }
}
Here's a demonstration of it not working:
scala> :paste
// Entering paste mode (ctrl-D to finish)
object Foo {
implicit class Foo(s: String) { def foo = println(s"Foo: $s") }
}
// Exiting paste mode, now interpreting.
defined object Foo
scala> import Foo._
import Foo._
scala> "hey".foo
<console>:14: error: value foo is not a member of String
"hey".foo
^
Here is it working:
scala> object Bar {
| implicit class Foo(s: String) { def foo = println(s"Foo: $s") }
| }
defined object Bar
scala> import Bar._
import Bar._
scala> "hey".foo
Foo: hey

Related

Scala: How can an import prevent finding an implicit value?

I could use suggestions debugging an implicit:
I want to use the implicit, x:
type T
trait HasT {
implicit def x: T = ...
}
But I also need a wildcard import from some package foo. I've tried two different ways of introducing both:
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
and
class UseT {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
Both fail with "could not find" (not "ambiguous implicits values").
This happens while implicit identifier x: T is accessible at the point of method call via either inheritance or importing.
My workaround is to rebind x to an implicit val before the import. Both of the following work:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
and
implicit val x2: T = x
import foo._
implicitly[T] // works!
What value could possibly be in foo to cause this behavior?
My first guess is that there is some competing implicit in foo, but if it were higher priority, the following implicitly would still work, and if it were an ambiguous implicit, I'd be getting a different a different error.
edit: Miles Sabin's guess was correct! I found the shadowing implicit: timeColumnType. I still don't completely understand how this works given Som Snytt's observation that the shadowing implicit was wildcard imported (lower priority) while the shadowed was inherited (part of highest priority), so I'll leave the whole post here for posterity.
retracted: A second guess, offered by miles sabin, is implicit shadowing. I've since clarified my post to exclude that possibility. That case would be consistent with my errors if I had tried package hasT extends HasT; import hasT._, but As som-snytt points out, those two cases would not result in shadowing.
In my specific case, this can be confirmed by changing the name of the implicit I'm trying to use.
(This is false. I likely missed a publishLocal or reload while using this test to verify.)
context: I'm actually trying to use slick. The implicit T above is actually a column type mapping:
import slick.driver.JdbcProfile
class Custom { ... } // stored as `Long` in postgres
trait ColumnTypes {
val profile: JdbcProfile
import profile.api._ // this is `foo` above
type T = profile.BaseColumnType[Custom]
implicit def customColumnType: T =
MappedColumnType.base[Custom, Long](_.toLong, Custom.fromLong)
}
class DatabaseSchema(val profile: JdbcProfile) extends ColumnTypes {
// `implicitly[T]` does not fail here.
import profile.api._ // this is also `foo` above
// `implicitly[T]` fails here, but it's needed for the following:
class CustomTable(tag: Tag) extends Table[Custom](tag, "CUSTOMS") {
// following fails unless I rebind customColumnType to a local implicit
def custom = column[Custom]("CUSTOM")
def * = custom
}
}
The type of api/foo is JdbcProfile.API. The offending implicit is probably here, but I can't tell why. I'll try blocking some of those from being imported and see if I can narrow it down.
I think it's most likely that foo contains a definition named x. When (wildcard) imported from foo it shadows the local definition,
scala> object foo { val x: Boolean = true }
defined object foo
scala> implicit val x: Int = 23
x: Int = 23
scala> implicitly[Int]
res0: Int = 23
scala> import foo._
import foo._
scala> implicitly[Int]
<console>:17: error: could not find implicit value for parameter e: Int
implicitly[Int]
^
This is clearly a bug in implicit search.
First, eligible are all identifiers x that can be accessed at the
point of the method call without a prefix and that denote an implicit
definition or an implicit parameter. An eligible identifier may thus
be a local name, or a member of an enclosing template, or it may be
have been made accessible without a prefix through an import clause.
In the example, unprefixed x refers to the inherited symbol. X.x is not accessible without a prefix.
Implicit search is fumbling the import.
$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { def x: Int = 42 }
trait T { def x: Int = 17 }
object Y extends T {
import X._
def f = x
}
// Exiting paste mode, now interpreting.
defined object X
defined trait T
defined object Y
scala> Y.f
res0: Int = 17
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X._
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
<pastie>:19: error: could not find implicit value for parameter e: Int
def f: Int = implicitly[Int]
^
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X.{x => _, _} // avoids bug, but is redundant
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
defined object X
defined trait T
defined object Y
scala>
The other example using the REPL is scoped this way:
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { def x: Int = 42 }
object Y { implicit def x: Int = 17 }
object Z {
import Y.x
def f = {
import X._
x
}
}
// Exiting paste mode, now interpreting.
<pastie>:19: error: reference to x is ambiguous;
it is imported twice in the same scope by
import X._
and import Y.x
x
^
Where x is not available at all, and the implicit is correctly excluded.
Just to confirm:
$ scala -Xlog-implicits
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X._
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
<console>:17: x is not a valid implicit value for Int because:
candidate implicit method x in object X is shadowed by method x in trait T
def f: Int = implicitly[Int]
^
<console>:17: x is not a valid implicit value for Int because:
candidate implicit method x in object X is shadowed by method x in trait T
def f: Int = implicitly[Int]
^
<console>:17: error: could not find implicit value for parameter e: Int
def f: Int = implicitly[Int]
^
scala>
Probably https://issues.scala-lang.org/browse/SI-9208

scala assignment operator _= not working in trait

Here is the code:
trait MacApp {
def dockerIcon_=(s: String) = println("setting docker icon...")
}
object Main extends App with MacApp {
dockerIcon = "apple"
}
The scalac complains this:
Main.scala:6: error: not found: value dockerIcon
dockerIcon = "apple"
^
one error found
I see scala-swing library use _= a lot, e.g., https://github.com/scala/scala-swing/blob/2.0.x/src/main/scala/scala/swing/Label.scala#L28
Thanks!
You need both getter and setter:
scala> :pa
// Entering paste mode (ctrl-D to finish)
trait MacApp {
def dockerIcon_=(s: String) = println("setting docker icon...")
def dockerIcon = 42
}
object Main extends App with MacApp {
dockerIcon = "apple"
}
// Exiting paste mode, now interpreting.
defined trait MacApp
defined object Main
scala> Main main null
setting docker icon...
http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#assignments
Your expectations about the pair of members are established earlier at:
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#variable-declarations-and-definitions
You're trying to assign to a function? I don't think that _= Swing code is using an operator, I think it's just an odd name...possibly for some obscure Java compatibility reason that escapes me at the moment.
But def defines a function, not a value, so you can't assign to it; you have to call it. Check out this console fragment:
scala> def text_=(s: String) = s + "foo"
text_$eq: (s: String)String
scala> text_=("bar")
res3: String = barfoo

How to fix this typeclass example?

This is a follow-up to my previous question:
Suppose I create the following test converter.scala:
trait ConverterTo[T] {
def convert(s: String): Option[T]
}
object Converters {
implicit val toInt: ConverterTo[Int] =
new ConverterTo[Int] {
def convert(s: String) = scala.util.Try(s.toInt).toOption
}
}
class A {
import Converters._
def foo[T](s: String)(implicit ct: ConverterTo[T]) = ct.convert(s)
}
Now when I tried to call foo in REPL it fails to compile:
scala> :load converter.scala
Loading converter.scala...
defined trait ConverterTo
defined module Converters
defined class A
scala> val a = new A()
scala> a.foo[Int]("0")
<console>:12: error: could not find implicit value for parameter ct: ConverterTo[Int]
a.foo[Int]("0")
^
import Converters._ in class A does not cut it. You can remove it and the code will still compile. The moment the compiler needs to find in actual implicit is not in class A, where foo is just declared.
The compiler needs to find a ConverterTo[Int] in implicit scope at the moment you call a.foo[Int](..) that is in the REPL. So this is where the import needs to be.
Had object Converters and trait ConverterTo been named the same (so there would be a companion object) the import would not be needed.

Scala macro get enclosing line

I have the following macro
object Example {
def doIt(s: String): String = macro doItImpl
def doItImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = {
import c.{ universe => u }
import u._
???
}
}
Instead of the ??? I would like to inspect the line where the method doIt was called to check if the result of the method was used (in an assignment, method call or whatever). If the result is not used I respond with an error-message.
Call-example:
val s: String = doIt("Hallo") // alright
doIt("Hallo") // ERROR!
Is there a simple way to get the Tree of the whole line?
For completeness, here's a lightly adapted version of the solution I mention above:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object Example {
def doIt(s: String): String = macro doItImpl
def doItImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = {
import c.universe._
c.enclosingClass.collect {
case ValDef(_, name, _, rhs) if rhs.pos == c.macroApplication.pos =>
c.literal(s"Okay, defining a variable named ${name.decoded}.")
}.headOption.getOrElse(
c.abort(c.enclosingPosition, "Not a valid application.")
)
}
}
Now in a REPL:
scala> import Example._
import Example._
scala> object Test1 { val x = doIt("foo") }
defined module Test1
scala> Test1.x
res0: String = Okay, defining a variable named x.
And in the case that we don't have an definition:
scala> object Test2 { doIt("foo") }
<console>:13: error: Not a valid application.
object Test2 { doIt("foo") }
^
As expected. See the comments on the question linked above for some caveats, but unless your real use case is much more complicated, this approach should work fine.

Retrieve the name of the value a Scala macro invocation will be assigned to

I'm attempting to write a macro that would wrap a function and deducting a parameter from the value its invocation will be assigned to.
object TestMacros {
def foo(name: String): String = name.toUpper
def bar = macro barImpl
def barImpl(c: Context): c.Expr[String] = {
import c.universe._
//TODO extract value name (should be baz)
c.Expr[String](Apply(
Select(newTermName("TestMacros"), newTermName("foo")), // Probably wrong, just typed it quickly for demonstration purposes
List(Literal(Constant("test"))))) // Should replace test by value name
}
}
object TestUsage {
val baz = bar // should be BAZ
}
I don't know if this is clear enough. I've investigated both c.prefix and c.macroApplication without success. I'm using Scala 2.10.2 without the macro-paradise compiler plugin.
This is very possible. I know, because I've done something like it before. The trick is to search the enclosing tree for a value whose right-hand side has the same position as the macro application:
import scala.language.experimental.macros
import scala.reflect.macros.Context
object TestMacros {
def foo(name: String): String = name.toUpperCase
def bar = macro barImpl
def barImpl(c: Context): c.Expr[String] = {
import c.universe._
c.enclosingClass.collect {
case ValDef(_, name, _, rhs)
if rhs.pos == c.macroApplication.pos => c.literal(foo(name.decoded))
}.headOption.getOrElse(
c.abort(c.enclosingPosition, "Not a valid application.")
)
}
}
And then:
scala> object TestUsage { val baz = TestMacros.bar }
defined module TestUsage
scala> TestUsage.baz
res0: String = BAZ
scala> class TestClassUsage { val zab = TestMacros.bar }
defined class TestClassUsage
scala> (new TestClassUsage).zab
res1: String = ZAB
Note that you can apply foo at compile-time, since you know the name of the val at compile-time. If you wanted it to be applied at runtime that would also be possible, of course.
I had a similar problem when I wanted to simplify some property initializations. So your code helped me to find out how that is possible, but I got deprecation warnings. As scala macros evolve the enclosingClass got deprecated in Scala 2.11. The documentation states to use c.internal.enclosingOwner instead. The quasiquotes feature makes things easier now - my sample to retrieve just the name as in val baz = TestMacros.getName looks like this:
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
object TestMacros {
def getName(): String = macro getNameImpl
def getNameImpl(c: Context)() = {
import c.universe._
val term = c.internal.enclosingOwner.asTerm
val name = term.name.decodedName.toString
// alternatively use term.fullName to get package+class+value
c.Expr(q"${name}")
}
}