I have a generic function that looks like so
def getFromCacheOrCallService[T: ClassTag](cacheKey: String, duration: Duration = cacheDefaultDuration)(
callServiceToFetchValue: => Try[T]
): Try[T]
and Im trying to figure out how to mock this function in a way that will always call callServiceToFetchValue and use it instead. I have this so far
doAnswer(invocation => {
invocation.getArgumentAt(1, classOf[() => Try[marketplace]])()
}).when(marketplaceCache).cacheable(any(), any())(any())(any())
Which if I understand what Im doing correctly should call the function passed, but whenever I try to run I get this error
Invalid use of argument matchers!
4 matchers expected, 3 recorded:
Why is it saying it expects 4 matchers? I have 4 matchers, I dont understand what the problem is.
It's not the curried function that's the problem, it's the pass-by-name parameter.
Mockito doesn't support it very well, and I am not aware of any good workarounds aside from actually declaring that parameter as an actual function () => Try[T]
(or, perhaps, String => Try[T] - it actually looks a bit weird without the key being passed it).
For anyone who ran into a similiar problem the solution I ended up with was changing the defintion of getFromCacheOrCallService to
def getFromCacheOrCallService[T: ClassTag](cacheKey: String, duration: Duration = cacheDefaultDuration)(
callServiceToFetchValue:() => Try[T]
): Try[T]
And then it worked. However since most of the time I was passing in functions like
def getFromCacheOrCallService("key", Duration(10, MINUTES)(callServiceToFetchValue(SomeInput))
I had to change it to
def getFromCacheOrCallService("key", Duration(10, MINUTES)({ () => callServiceToFetchValue(SomeInput)} )
Related
I'm getting some unexpected behavior when using a call by name function in Scala. Can anybody explain the difference here?
class Button( act: => Unit) {def fire = act}
def foo() {println("foo got called")}
val x= new Button(foo)
x.fire
val y= new Button(foo _)
y.fire
x.fire causes foo to be called.
y.fire does not.
Why?
What function is being passed to y?
Thanks!
You should probably define your class a bit differently.
class Button( act: () => Unit) {def fire = act()}
Notice you are now taking in a Function0[Unit] instead of a call-by-name Unit value. This new definition has better typesaftey since it requires a function, while yours will accept any value, and will do nothing unless there are side effect required to evaluate the value passed in. We also now call the function passed in for its side effects instead of just returning it.
The problem with Unit is that when a unit is required any value can be provided which will be automatically discarded for a Unit. For example, with your code new Button(5) is valid, as is the code val x: Unit = 5.
The reason the first code class Button( act: => Unit) {def fire = act} "works", is you call the method foo, and pass the result into the Button constructor. Since it's a by-name parameter foo doesn't actually run until it's used. When you then use the Unit value passed into the class, the expression needs to be evaluated so foo is fun.
You second example is different however, adding the underscore (foo _) now means that you are passing in the method itself as a function, instead of calling the method and passing in the result as in your first example. It's perfectly fine to pass a function in to the constructor even thought the type now is not Unit since as discussed earlier any value can be discarded and replaced by Unit. When you evaluate the Unit value, there are no side effects this time since you don't run the method to get the unit, just create a function which is the discarded without being run. def fire = act
When you change the type to be a function.
class Button( act: () => Unit) {def fire = act()}
now only a () => Unit is a valid argument instead of anything, and the fire method runs that function.
Here is a possible explanation!
scala> foo _
res14: () => Unit = <function0>
scala> foo
foo got called
scala>
Can you see why now?
Because Button takes a (delayed) Unit as a constructor argument, you'd think that the call to new Button(foo _) wouldn't be allowed because () => Unit is not the same thing as =>Unit. But it turns out that => Unit is, essentially, the universal accepter.
new Button()
new Button(99)
new Button("str")
You'll get warnings, but these all compile and run, and you can invoke the fire method on them (but it won't do anything).
My code heavily uses Akka and untyped actors.
An example of typical logic is as follows:
val myFuture: Future[Any] = akka.pattern.AskSupport.ask(myActorRef, myMessage)
val completedLogic: Future[Unit] = myFuture.map(myFunction)
myFunction then contains a strongly typed signature as follows:
def myFunction(): (Option[MyStronglyTypedClass]) => Unit = {
(myOption: Option[MyStronglyTypedClass]) => myOption foreach (myObject => // do some logic
}
I know that myFuture will always contain an instance of MyStronglyTypedClass or null for this particular actor. I will also know this for other actor/future/function combinations.
My problem comes when I look to create an implicit conversion from the Future[Any] to the Option[MyStronglyTypedClass] or Option[MyOtherStronglyTypedClass]
The implicit conversion will just do a null check and one other piece of logic before creating the Option
How do I go about performing this implicit conversion from Any to a subtype, or is it even possible?
You should, instead, convert to Future[Option[MyStronglyTypedClass]]:
def asMyStronglyTypedClass(x: Any): Option[MyStronglyTypedClass] = x match {
case null => None
case ...
}
// this will fail if myFuture fails or asMyStronglyTypedClass throws
val typedFuture = myFuture.map(asMyStronglyTypedClass)
and do what you want with this future. E.g.
typedFuture.onSuccess(myFunction)
EDIT: I missed you already have a map. In this case the issue is that you don't need to convert Future[Any] to Option, but its result (i.e. Any). You can write e.g. myFuture.map(asMyStronglyTypedClass).map(myFunction) or myFuture.map(x => myFunction(asMyStronglyTypedClass(x))). You could also make asMyStronglyTypedClass implicit and write myFuture.map(x => myFunction(x)). I still think it isn't a good idea, as it could get applied somewhere you don't expect.
If you really want to write myFuture.map(myFunction), you'll need a different implicit conversion to make the compiler understand:
implicit def contraMap(f: Option[MyStronglyTypedClass] => Unit): Any => Unit =
x => f(asMyStronglyTypedClass(x))
Of course, these can be made generic over your types, as mentioned in the comments.
Impliciy converting from Any to something else is something that you should never do because it effectively switches off Scala's type system. Converting the type of a future in a safe fashion can be done using
myFuture.mapTo[Option[MyStronglyTypedClass]]
What is type of this block: callback: => Unit?
How I can assign it to Option? In other words how to update following code so it doesn't have any compilation errors?
var onEventCallback: Option[() => Unit] = None
def onEvent(callback: => Unit) {
onEventCallback = Some(callback) // HERE compilation error: Some[Unit] doesn't conform to Option[() => Unit]
}
Ok. I solved it using Some(callback _) instead of Some(callback). But why this work?
The compiler needs to know whether you want callback to be executed immediately or not. WIthout the underscore immediate execution is assumed, and the result is assigned to the Some. WIth the underscore, the compiler knows that it shouldn't execute callback to get the result but should treat it as the parameter to pass to the Some constructor (or rather, apply() method).
But why this work?
Sometimes you can think of by-name parameter as a function without arguments. Actually it is a Function0 after erasure phase in compiler. You could compile you code with -Xprint:erasure to see this:
def onEvent(callback: Function0): Unit = onEventCallback_=(new Some(callback))
I have a series of validation functions that returns an Option[Problem], if any, or None if no validation problems are found.
I would like to write a simple function that calls each validation function, stop and return the first not-None result.
Naturally I can write this method in the "java-style", but I would like to know if a better approach exists.
EDIT
This was the original Java solution:
validate01(arg);
validate02(arg);
validate03(arg);
...
Each method throws an exception in case of problem. I would stay away from the exceptions while I'm writing Scala.
As an example, let's say we want to validate a String. Our validation function takes a String and a list of validators, which are functions from String to Option[Problem]. We can implement it in a functional manner like this:
def firstProblem(validators: List[String => Option[Problem]], s:String) =
validators.view.flatMap(_(s)).headOption
This creates a new list by applying each validation function to the string and keeping the result only if it is a Some. We then take the first element of this List. Because of the call to view, the list will be computed only as needed. So as soon as the first Problem is found, no further validators will be called.
If you have finite and known at compile time number of validations you may use .orElse on Options:
def foo(x: Int): Option[Problem] = ...
def bar(x: Int): Option[Problem] = ...
...
def baz(x: Int): Option[Problem] = ...
foo(1) orElse bar(2) orElse .. baz(n)
Maybe you want--assuming the validation functions take no arguments
def firstProblem(fs: (() => Option[Problem])*) = {
fs.iterator.map(f => f()).find(_.isDefined).flatten
}
You'll get an existing Option[Problem] if there are any, or None if they all succeed. If you need to pass arguments to the functions, then you need to explain what those arguments are. For example, you could
def firstProblem[A](a: A)(fs: (A => Option[Problem])*) = /* TODO */
if you can pass the same argument to all of them. You would use it like this:
firstProblem(myData)(
validatorA,
validatorB,
validatorC,
validatorD
)
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.