Transforming Scala varargs into Java Object... varargs - scala

I have a Java class that logs stuff which has a method like this:
void info(Object message, Object... params);
In Scala, I've created a wrapper around such call that looks like this:
def info(msg: => String, params: Any*) {
log.info(msg, params);
}
When I call:
val host = "127.0.0.1"
val port = "1234"
info("Start on {0}:{1}", host, port)
I get:
"Started on WrappedArray(127.0.0.1, 1234):{1}"
Now, does anyone now how to convert params into an Object[] that can be consumed properly?
I tried to do:
def info(msg: => String, params: Any*)
log.info(msg, params.toList.toArray);
}
But that doesn't work:
"Started on [Ljava.lang.Object;#14a18d:{1}"
Similar thing happens when you do:
params.asInstanceOf[WrappedArray[Object]].array

Found the answer:
log.info(msg, params.map(_.asInstanceOf[AnyRef]) : _*)
The following returns a Seq[AnyRef] => params.map(_.asInstanceOf[AnyRef]), and the ': _*' part tells the compiler to pass it as varargs
Result:
"Started on 127.0.0.1:1234"
Besides, this solution deals with both AnyVals and AnyRefs

#Galder - there is an easier way which allows you to avoid the cumbersome asInstanceOf[Object] call:
def info(msg: => String, params: Any*) = log.info( msg.format(params : _*) );
In scala 2.7, the format(args : Any*) function is implicitly included via RichString (and has a sub-optimal implementation is terms of reflection for no good reason that I can see) whereas in 2.8 the method is included via StringLike and is implemented via a direct call to String.format(String, Object ...)
I understand that the reason why Java does not contain such a method is that it has an implication that "every String is a format String", which is not the case. happily, I'm willing to forgo the logical correctness for the more useable class which scala provides!

Related

Mocking a function with pass-by-name arguments

My actual use-case is unit testing code involving finagle FuturePool: I want to make sure, FuturePool.apply was actually invoked, so that the task was executed in the correct instance of the pool.
The problem I am running into however seems more generic, so I will illustrate it on an abstract example, not related to finagle or futures.
Suppose, I have these two classes:
class Foo {
def apply(f: => String) = f
}
class Bar(val foo: Foo) {
def doit(f: => String) = foo(f)
}
Bar has an instance of Foo, that knows how to run functions, and I want to test that it is actually using it for execution:
describe("Bar") {
it("should use the right foo") {
val foo = mock[Foo]
when(foo.apply(any)).thenAnswer( new Answer[String] {
def answer(invocation: InvocationOnMock): String =
invocation.getArgumentAt(0, classOf[Function0[String]]).apply()
})
new Bar(foo).doit("foo") should equal("foo")
}
}
This does not work: .doit return null, apparently, because mockito does not realize it was mocked. It seems that any is not matching Function0 in this case (replacing it with any[Function0[String]] does not help either.
I also tried it another way:
it("should Foo!") {
val foo = Mockito.spy(new Foo)
new Bar(foo).doit("foo") should equal("foo")
verify(foo).apply(any)
}
This also does not work, and kinda confirms my suspicion about any not working in this case:
Argument(s) are different! Wanted:
foo$1.apply(
($anonfun$apply$mcV$sp$7) <function0>
);
Actual invocation has different arguments:
foo$1.apply(
($anonfun$apply$mcV$sp$6) <function0>
);
Any ideas about a good way to get around this?
This signature:
def apply(f: => String)
is known as "call by name" where it passes an expression instead of an evaluated expression. This is very specific to Scala and not well supported with Mockito.
There is a host of workarounds to this:
Is there a way to match on a call-by-name argument of a Mockito mock object in Specs?
How to mock a method with functional arguments in Scala?
How do you mock scala call-by name in Mockito
The one by Eric looks the simplest and what you may want.

Scala - how to create a single implicit that can be used for a type constructor

I'm trying to write a method which uses the isEmpty method on types String, Option and List. These classes don't share a common base trait with that method, so I've tried to pass an implicit EmptyChecker in with them:
trait EmptyChecker[Field] {
def isEmpty(data: Field): Boolean
}
implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] {
def isEmpty(string: String): Boolean = string.isEmpty
}
def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = {
if (emptyChecker.isEmpty(field))
println("Empty")
else
println("Not empty")
}
printEmptiness("abc") // Works fine
The String empty checker works fine, but I've hit problems with making empty checkers for type constructors like Option and List.
For example, Option doesn't work:
implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] {
def isEmpty(option: Option[_]): Boolean = option.isEmpty
}
// Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]]
printEmptiness(Some(3))
printEmptiness[Option[Int]](Some(3))
If I use a specific Option[Int] checker, it works a little better, but is a bit ugly:
implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] {
def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty
}
// Fails like above:
printEmptiness(Some(3))
// Passes compilation:
printEmptiness[Option[Int]](Some(3))
So my question is: is it possible to make a single EmptyChecker for each Option and List type and have them work with my method without needing to explicitly declare the type whenever I call it? I'm trying to get a type safe duck typing effect.
I'm using scala 2.11.6.
Thanks in advance!
The source of your problem is that the type of Some(1) is Some[Int], not Option[Int]. There are a couple of ways around this; you can explicitly upcast the expression with a type ascription: printEmptiness(Some(3): Option[Int]). Alternatively, you can define a helper method to do this for you automatically, and if you're using Scalaz, there's one of these provided:
import scalaz.syntax.std.option._
printEmptiness(3.some)
Furthermore if you do use Scalaz, you may find looking at the PlusEmpty/ApplicativePlus/MonadPlus type classes useful.

Failing in a companion object's apply mehod

It's common for Scala classes to have apply and unapply methods in their companion object.
The behaviour of unapply is unambiguous: if its parameter is or can be transformed into a valid instance of the class, return a Some of it. Otherwise, return None.
To take a concrete example, let's imagine a Url case class:
object Url {
def apply(str: String): Url = ???
def unapply(str: String): Option[Url] = ???
}
case class Url(protocol: String, host: String, path: String)
If str is a valid URL, then unapply will return a Some[Url], otherwise None.
apply is a bit less clear to me, however: how should it react to str not being a valid URL?
Coming from the Java world, my first instinct is to throw an IllegalArgumentException, which would allow us to implement the companion object as:
object Url {
def apply(str: String): Url = ... // some function that parses a URI and throws if it fails.
def unapply(str: String): Option[Url] = Try(apply(str)).toOption
}
I understand that this is not considered terribly good practice in the functional world (as explained, for example, in this answer).
The alternative would be to have apply return an Option[Url], in which case it'd be a simple clone of unapply and better left unimplemented.
Is that the correct conclusion to reach? Should this type of potentially failing apply methods simply not be implemented? Is throwing, in this case, considered to be ok? Is there a third option that I'm not seeing?
This is a bit subjective, but I don't think you should do either.
Suppose you allow apply to fail, i.e. throw an exception or return an empty option. Then doing val url = Url(someString) might fail, despite looking awfully like a constructor. That's the whole problem: the apply method of a companion object should reliably construct new instances for you, and you simply cannot reliably construct Url instances from arbitrary Strings. So don't do that.
unapply should generally be used to take a valid Url object and return another representation with which you could create a Url again. As an example of this, look at the generated unapply method for case classes, which simply returns a tuple containing the arguments with which it was constructed. So the signature should actually be def unapply(url: Url): String.
So my conclusion is that neither should be used for the construction of a Url. I think it would be the most idiomatic to have a method def parse(str: String): Option[Url] to make explicit what you're actually doing (parsing the string) and that it might fail. You can then do Url.parse(someString).map(url => ...) to use your Url instance.
It's typically the responsibility of the user of the extractor to decide how to handle failure in the case of None, and the pattern matching syntax makes this reasonably convenient. Here's a slightly simpler example:
import scala.util.Try
object IntString {
def unapply(s: String) = Try(s.toInt).toOption
}
Now we can write any of the following:
def intStringEither(s: String): Either[String, Int] = s match {
case IntString(i) => Right(i)
case invalid => Left(invalid)
}
Or:
def intStringOption(s: String): Option[Int] = s match {
case IntString(i) => Some(i)
case _ => None
} // ...or equivalently just `= IntString.unapply(s)`.
Or:
def intStringCustomException(s: String): Int = s match {
case IntString(i) => i
case invalid => throw MyCustomParseFailure(invalid)
}
This flexibility is one of the nice things about unextractors, and if you're throwing (non-fatal) exceptions in the unapply you're short-circuiting that flexibility.

How to getClass implicitly

I'm writing a Scala wrapper over some Java code with a method signature like method(cl: Class[_], name: String) and many getClass methods in code looks not good:
Creator.create(getClass, "One")
Creator.create(getClass, "Two")
Creator.create(getClass, "Three")
Creator.create(getClass, "Four")
So can we somehow get enclosing class implicitly like Creator.create("some name")?
Answer 1.
In general I warmly discourage reflection. However, if you really want to do it, in Scala 2.9.1 you can use Manifest
def create[T:Manifest](name:String) = {
val klass:Class[_] = t.erasure
}
In scala 2.10 you should have a look to TypeTag.
Answer 2.
However, as I already said, the right approach would not be to use class but implicit builders
trait Builder[T]{
def build(name:String):T
}
def create[T](name:String)(implicit builder:Builder[T]) = {
builder.build(name)
}
in that way you can limit what you can create by importing only the right implicits in scope, you won't rely on reflection and you won't risk to get horrible RuntimeExceptions
Post comment answer
If your point is to avoid calling getClass at each invocation, you can do the following
def create(name:String)(implicit klass:Class[_]) {
}
And you can call it this way
implicit val klass1 = myInstance.getClass
create("hello")
create("goodbye")

def fn[String] seems to break Scala / java.lang.String compatibility

Hello there Stack Overflow,
I hope you'll help me with my very first question here :)
So I'm having a problem with Scala type inference. Here is the code:
object Problem {
def ok(fn: (String) => Unit) = fn("")
// type mismatch; found: java.lang.String("") required: String
def fail[String](fn: (String) => Unit) = fn("")
}
What kind of String does Scala expect here?
Note that this is a minimal example to explain my problem. The original issue appeared when I tried to implement a more complex interface (Play's Iteratee, to be precise), so, no, leaving out the [String] is not an option. (If anyone thinks that the actual code would help, I'll provide it.)
I tried def fail[java.lang.String] ... but then it says expected ], found ..
I did read Scala String vs java.lang.String - type inference which gives a good explanation on java.lang.String vs. scala.Predef.String, but I still could not come up with a solution for my specific problem.
Any ideas?
EDIT: So here is the original attempt how I tried to implement http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/iteratee/Iteratee.html only that I wrote String instead of T. (With T it compiles, and it makes sense!) My fail; obviously I was a bit overwhelmed by all the type parameters:
val stream = WS.url("url").get({ headers =>
(new Iteratee[Array[Byte], String] {
def fold[T](done: (String, Input[Array[Byte]]) => Promise[T],
cont: (Input[Array[Byte]] => Iteratee[Array[Byte], String]) => Promise[T],
error: (String, Input[Array[Byte]]) => Promise[T]): Promise[T] =
{
done("something", Input.Empty)
}
})
})
Regards,
Hendrik
When you write:
def fail[String](fn: (String) => Unit) = fn("")
The type parameter between square brackets String is just an arbitrary name that, in your case, will hide scala or java string. It is fully equivalent to:
def fail[T](fn: (T) => Unit) = fn("")
If you want to constrain the type to string, you just have to write:
def fail(fn: (String) => Unit) = fn("")
And it will work for scala and java strings (since they are the same).
This problem has nothing to do with Java vs Scala strings.
In the line def fail[String](fn: (String) => Unit) = fn("") you're definining a completely new type parameter and naming it String. This shadows the general definition.
A type paramter is needed if you intend to abstract over the type. You are not doing this in the fail example, and this should be dropped.
If you are overriding something that uses a type parameter, then you should specify this at the class level:
class A extends B[String]
Looking at the code for Iteratee, I'll guess you're trying to implement fold with its various done, cont and error functions. Fold only has one type paramter, which is used in the return type, so I'm not sure where this can come from. The input type parameters are specified on the class, so if you extend Iteratee[String, Unit] these should be provided.