How do you define implicit conversion in modern way? - scala

Stupid question, but none of the examples works for me; classic article "Pimp my Library" is buggy and even the simplest code has problems.
Btw. I assume you have to put conversion method in the object (a lot of snippets omit that part). According to PiS book it seems hanging implicit def is OK, but this gives me error as well.
object Minutes
{
implicit def toMinutes(x : Int) = new Minutes(x)
}
class Minutes(private val x : Int)
{
def minutes = x.toString+"m"
}
object MainApp {
def main(args : Array[String])
{
println(5.minutes)
...
The error -- "value minutes is not a member of Int".
Question
What am I missing? Scala 2.9.1.

All you need you to do is bring your implicit conversion into scope where you want to use it, so the compiler can find it...
def main(args : Array[String]) {
import Minutes._
println(5.minutes)
}

The implicit conversion must be in scope, e.g.
def main(args : Array[String]) {
import Minutes._
println(5.minutes)
...
}
There are other ways, too, e.g. using package objects.

You can get the example in the Pimp my library article to work as follows:
class RichArray[T: Manifest](value: Array[T]) {
def append(other: Array[T]): Array[T] = {
val result = new Array[T](value.length + other.length)
Array.copy(value, 0, result, 0, value.length)
Array.copy(other, 0, result, value.length, other.length)
result
}
}
implicit def enrichArray[T: Manifest](xs: Array[T]) = new RichArray[T](xs)
You need a context bound for T: [T: Manifest] is short for [T](implicit m: Manifest[T]). A Manifest is a way of passing the value of T to the method at runtime, when T is known. Normally the parameterized type information is used by the compiler to ensure type safety at compile time, but is not incorporated into the bytecode because the JVM can't handle it (type erasure). Scala collections changed in version 2.8 so that for performance reasons, Arrays are now not automatically wrapped by compiler magic, hence supplying a manifest for generic operations became necessary.
The other change is the (xs) argument for new RichArray[T]. I think that one's a typo.

Related

Return type with generic with bounds

I have the following code
import scala.concurrent.Future
class RequestType
class Read extends RequestType
class Write extends RequestType
object Main {
def main(args: Array[String]): Unit = {
}
def dbrequest[T <: RequestType](t: T): Future[T] = {
val dBRequest = new DBRequest
t match {
case r: Read => dBRequest.read(r)
case w: Write => dBRequest.write(w)
}
}
}
class DBRequest {
def read(r: Read): Future[Read] = {
Future(r)
}
def write(w: Write): Future[Write] = {
Future(w)
}
}
read and write method return a Future of type RequestType. If T is bounded and Future is covariant, then why is the compiler failing to conform type of Future[Read] or Future[Write] to Future[T]
Your code will compile with one small change.
def dbrequest[T <: RequestType](t: T): Future[RequestType] = {
So why is it that returning Future[RequestType] works and returning Future[T] doesn't, especially since T is bounded the way it is?
Think of it this way: T is resolved at compile time. With every invocation of dbrequest() the compiler turns T into either Read or Write. The match statement, on the other hand, is resolved at run time. So from the compiler's perspective the match statement returns both Read and Write.
As has been pointed out, you don't really need a type parameter in this code, as presented. The following simplification is equivalent.
def dbrequest(t: RequestType): Future[RequestType] = {
If T is bounded and Future is covariant, then why is the compiler failing to conform type of Future[Read] or Future[Write] to Future[T]
Your code would make sense if T was guaranteed to be Read or Write.
But it could Read with SomeTrait. Or a singleton type (so even making RequestType, Read and Write sealed wouldn't help). Etc. See my answer to Returning subclass of parameterized type in Scala for a solution (just replace Output in that question with Future).

Understanding implicit conversions

I'm reading Scala documentation of implicit conversions and decided to try it out:
object Main extends App {
val test = TestConversion(100)
test.its
}
class Test[T](val t : T) {
def its = println(t)
}
object Test {
def apply[T](t: T): Test[T] = new Test(t)
}
class TestConversion(v : Int) {
val value = v
}
object TestConversion{
implicit def implicitConversionTest2Int(ict : TestConversion): Test[Int] = Test(ict.value)
def apply(v : Int) = new TestConversion(v)
}
As it's said:
To define your own implicit conversions, you must first import
scala.language.implicitConversions (or invoke the compiler with
-language:implicitConversions). The feature must be explicitly enabled because it has pitfalls if used indiscriminately.
I tried it both in IntelliJ and online IdeOne and I didn't add anything special to make it compile.
What pitfalls it brings and why does it work without any imports?
You don't need to import anything.
The idea is that you can declare implicit conversion function wherever you want in the scope.
For example:
case class Coins(amount:Int)
case class Bills(amount:Int)
object Main {
implicit def billsToCoins(bills:Bills):Coins = Coins(bills.amount * 100)
def printCoins(coins:Coins) = println(s"You have ${coins.amount} coins." )
def main(args:Array[String]): Unit ={
printCoins(Bills(3))
}
}
I have declared here implicit function billsToCoins so it is available in scope of the main function. The only thing needed for the function to act as implicit converter is to have the implicit modifier, compiler will find it and use. You see that the printCoins function takes argument of the Coins type but I was able to pass the value of Bills type and it was successfully created.
Here is the console output:
You have 300 coins.
Process finished with exit code 0

Why does an implicit conversion on the constructor require 'this'?

Consider the following typical Scala 'pimp' code:
class PimpedA(a:A){
def pimp() = "hi"
}
implicit def pimpA(a:A) = new PimpedA(a)
new A(){
pimp() //<--- does not compile
}
However, changing it to:
new A(){
this.pimp()
}
Makes it work.
Shouldn't it be the same to the Scala compiler?
EDIT : Is there any solution that can make it work without having to add the this.?
Not at all. For it to work, pimp needs to be either an object or an imported member of a value, and it is neither. A class has an "implicit" import this._. It has not a mechanism that auto-prepends this to stuff to see if it compiles.
In this case you should give compiler a hint that pimp() is not a random function. When you write
this.pimp()
compiler know there isn't pimp function on class A so it's an error and before giving up it searches implicit conversion in scope and finds it.
pimpA(this).pimp()
And when you just call pimp() compiler doesn't know what object to pass to the pimpA(a: A) implicit function.
UPDATE
It is hard to understand what is your goal. I can only suggest to make PimpedA a typeclass (Pimp[T] in this example).
trait Pimp[T] {
def action(p: T): String
}
implicit object PimpA extends Pimp[A] {
override def action(p: A) = "some actions related to A"
}
def pimp[T: Pimp](p: T) = implicitly[Pimp[T]].action(p)
class A {
val foo = pimp(this)
}
scala> new A foo
res2: String = some actions related to A

Specs implicit conversion conflicts with Scala Predef

I have a type alias in my code like so:
type Time = Double
And I often in both tests and in applications pass Long values to functions that use this type. For instance:
def at(time : Time) : T = {
// Do Something
}
at(System.currentTimeMillis)
This code works fine unless run in my tests where I get the following error:
found : Long
required: com.github.oetzi.echo.Echo.Time
Note that implicit conversions are not applicable because they are ambiguous:
both method long2double in object Predef of type (x: Long)Double
and method longToDouble in trait NumericBaseMatchers of type (s: Long)Double
are possible conversion functions from Long to com.github.oetzi.echo.Echo.Time
After looking up NumericBaseMatchers it seems its part of the Specs testing framework (my tests are written in Specs 1). I tried running code to get the error in the interpreter and it was fine out side of the tests.
Is there any way I can somehow remove the ambiguity so I can pass Long to values to a Double/Time function? Why does Specs try and create its own LongToDouble conversion when Scala already provides this?
If you want to deactivate an inherited implicit conversion you can do this:
override def longToDouble(s: Long) = super.longToDouble(s)
For convenience if you add it to a new trait, you can mix-in your trait to your specification when needed:
trait NoConversion {
override def longToDouble(s: Long) = super.longToDouble(s)
}
class MySpecification extends NoConversion {
...
}
Try unimporting one of them.
import NumericBaseMatchers.{longToDouble => _}

Implicit conversion, import required or not?

I write
object MyString {
implicit def stringToMyString(s: String) = new MyString(s)
}
class MyString(str: String) {
def camelize = str.split("_").map(_.capitalize).mkString
override def toString = str
}
object Parse {
def main(args: Array[String]) {
val x = "active_record".camelize
// ...
}
}
in my program. This causes a compiling error. After I inserted
import MyString.stringToMyString
Then it works.
From Odersky's Programming in Scala I got that implicit conversion in the companion object of the source or expected target types don't need to be imported.
implicit conversion in the companion
object of the source or expected
target types don't need to be
imported.
True enough. Now, the method camelize is defined on the class MyString, and, indeed, there is an implicit conversion to MyString inside its object companion. However, there is nothing in the code telling the compiler that MyString is the expected target type.
If, instead, you wrote this:
val x = ("active_record": MyString).camelize
then it would work, because the compiler would know you expect "active_record" to be a MyString, making it look up the implicit conversion inside object MyString.
This might look a bit restrictive, but it actually works in a number of places. Say, for instance, you had:
class Fraction(num: Int, denom: Int) {
...
def +(b: Fraction) = ...
...
}
And then you had a code like this:
val x: Fraction = ...
val y = x + 5
Now, x does have a + method, whose expected type is Fraction. So the compiler would look, here, for an implicit conversion from Int to Fraction inside the object Fraction (and inside the object Int, if there was one, since that's the source type).
In this situation you need the import because the compiler doesn't know where you pulled out the camelize method from. If the type is clear, it will compile without import:
object Parse {
def foo(s: MyString) = s.camelize
def main(args: Array[String]) {
val x = foo("active_record")
println(x.toString)
}
}
See Pimp my library pattern, based on Martin's article:
Note that it is not possible to put defs at the top level, so you can’t define an implicit conversion with global scope. The solution is to place the def inside an object, and then import it, i.e.
object Implicits {
implicit def listExtensions[A](xs : List[A]) = new ListExtensions(xs)
}
And then at the top of each source file, along with your other imports:
import Implicits._
I tried the Rational class example in Programming in Scala book, put an implicit method in its companion object:
object Rational {
implicit def intToRational(num: Int) =
new Rational(num)
}
but the code
2 + new Rational(1, 2)
does not work. For the conversion to happen, the single identifier rule applies, i.e., you need to import the explicit method into scope even though it is defined in the companion object.