Having trouble with curried parameter - scala

the code below runs perfectly fine if I simply make it a "case class". However, I certainly do not want that for a mutable object - but by changing it to a regular class, it no longer seems to understand the anonymous function parameter at the end. Not sure why I can't get past this, i've tried a few variations and can't understand why making it a case class works. (scala 2.10.2) - thanks
/**
*
* #param target - can be any large target number
* #param perPiece - at what percentage interval is todo called
* #param todo - passed current percentage complete
*/
class ProgressTool(target:Double, perPiece:Double) (todo: (Double)=>Unit) extends Mutable {
private[this] var lastUpdate:Double =0.0
def update(atPos:Double) = {
val step = atPos - lastUpdate
if (step/target >=perPiece) {
lastUpdate += step
todo(lastUpdate)
}
}
}
object TestProgressTool extends App {
val x = new ProgressTool(1000,.01) { x:Double =>
println("Hello "+ x)
}
}
missing arguments for constructor ProgressTool in class ProgressTool
val x = new ProgressTool(1000,.01) { x:Double =>
^

Not sure why it seems to work, but try this (note extra parentheses around constructor with first arguments):
object TestProgressTool extends App {
val x = (new ProgressTool(1000,.01)) { x:Double =>
println("Hello "+ x)
}
}

Using round parens around the second param list heals the code too and might be less surprising:
object TestProgressTool extends App {
val x = new ProgressTool(1000,.01) ({ x:Double =>
println("Hello "+ x)
})
}

Related

Application without the `apply` method?

I noticed the following code in org.scalacheck.Properties file:
/** Used for specifying properties. Usage:
* {{{
* property("myProp") = ...
* }}}
*/
class PropertySpecifier() {
def update(propName: String, p: Prop) = props += ((name+"."+propName, p))
}
lazy val property = new PropertySpecifier()
I'm not sure what is happening when property("myProp") = ... is invoked. There is no apply method in the class PropertySpecifier. So, what is being called here?
You may notice that the usage does not only show application but rather something else, the = sign. By having your class implement an update method you can let the compiler how the state of this class can be updated and allowing the property("myProp") = syntax.
You can find the same behavior on Arrays, where apply performs read access and update write access.
Here is a small example you can use to understand this:
final class Box[A](private[this] var item: A) {
def apply(): A =
item
def update(newItem: A): Unit =
item = newItem
}
val box = new Box(42)
println(box()) // prints 42
box() = 47 // updates box contents
println(box()) // prints 47

How do I get rid of my unchecked warning on implicit class with higher order function

I'm trying to write an auto-retrying transaction "monkey patch" on top of slick (1.0, unfortunately). In addition, i want it to only retry on certain types of exceptions. Unfortunately, I keep running issues of type erasure. From what I understand, what im trying to do is im ending up mixing runtime and compile time idioms, but at this point, im all out of ideas. Do i try using reflection?
object SessionSupport {
/**
* Patches the session object to add trnansaction serializable
* with automatic retry
*/
implicit class SlickSessionWrapper(session:Session) {
private val logger = LoggerFactory.getLogger(getClass)
val MAX_RETRIES = 3
// UNFORTUNATELY I CANT SEEM TO GET RID OF THE UNCHECKED WARNING.
// As such, the type check is alwasy going to "pass" for ANY throwable
def withRetryingSerializableTransaction[A, T <: Throwable ](f: => A)(implicit retryCt:Int = 0):A = {
val res:Try[A] = session.withTransaction {
session.conn.setTransactionIsolation(
java.sql.Connection.TRANSACTION_SERIALIZABLE
)
Try(f)
}
res match {
case Success(v) => v
case Failure(thr) => {
if(thr.isInstanceOf[T] && retryCt < MAX_RETRIES) { // type erasure here!!!
logger.debug(s"Caught ${thr.toString}, retrying")
withRetryingSerializableTransaction[A, T](f)(retryCt + 1)
} else {
logger.error(s"Caught ${thr.toString}. Rethrowing", thr)
throw thr
}
}
}
}
}
}
Yeah, you need reflection for this.
Change the declaration to
def withRetryingSerializableTransaction[A, T <: Throwable : Manifest]
and then, instead of thr.isInstanceOf[T], do manifest.runtimeClass.isInstance(thr)

Dynamic object method invocation using reflection in scala

I'm looking to create a way to dynamically call logic depending on template id within scala. So template id 1 calls logic a, template id 2 call logic b, etc. The logic will be diverse but will have the same inputs/outputs. Also the number of different template ids will get into the thousands and will not be known ahead of time, so a loose coupling feels the way to go.
I've started looking at reflection to do this using scala 2.11.1 and can statically use reflection when I know the logic to be used ahead of time but have not found the correct way to dynamically use reflection, so for example passing in template id 2 will call logic b.
Below is a cut down example showing how the static version works and the skeleton I have so far for the dynamic version.
package thePackage
import scala.reflect.runtime.{universe => ru}
trait theTrait { def theMethod(x: String): Unit }
// the different logic held in different objects
object object1 extends theTrait {
def theMethod(x: String) = { println("a " + x ) }
}
object object2 extends theTrait {
def theMethod(x: String) = { println("b " + x ) }
}
object object3 extends theTrait {
def theMethod(x: String) = { println("c " + x ) }
}
// run static/dynamic reflection methods
object ReflectionTest {
// "static" invocation calling object1.theMethod
def staticInvocation() = {
val m = ru.runtimeMirror(getClass.getClassLoader)
val im = m.reflect(thePackage.object1)
val method = ru.typeOf[thePackage.object1.type]
.decl(ru.TermName("theMethod")).asMethod
val methodRun = im.reflectMethod(method)
methodRun("test")
}
staticInvocation
// "dynamic" invocation using integer to call different methods
def dynamicInvocation( y: Integer) = {
val m = ru.runtimeMirror(getClass.getClassLoader)
val module = m.staticModule("thePackage.object" + y)
val im = m.reflectModule(module)
// stuck... static approach does not work here
}
dynamicInvocation(1)
dynamicInvocation(2)
dynamicInvocation(3)
}
What needs to be added/changed to the dynamicInvocation method to make this work, or should I be using a different approach?
You need to get an instance mirror for your module, on which you can reflect the method.
def dynamicInvocation( y: Integer) = {
val m = ru.runtimeMirror(getClass.getClassLoader)
val module = m.staticModule("thePackage.object" + y)
val im = m.reflectModule(module)
val method = im.symbol.info.decl(ru.TermName("theMethod")).asMethod
val objMirror = m.reflect(im.instance)
objMirror.reflectMethod(method)("test")
}
It seems that TermName method in above solution has been replaced by newTermName and also the info.decl seems to not work. Below line worked for me
val method = im.symbol.typeSignature.member(ru.newTermName("testMethod")).asMethod

When matching, do you create a variable on the fly in the case statement?

I'm looking at this scala code and confused where the variable partitionedData is coming from in the case Some(partitionedData) statement:
private def dispatchSerializedData(messages: Seq[KeyedMessage[K,Message]]): Seq[KeyedMessage[K, Message]] = {
val partitionedDataOpt = partitionAndCollate(messages)
partitionedDataOpt match {
case Some(partitionedData) =>
val failedProduceRequests = new ArrayBuffer[KeyedMessage[K,Message]]
try {
for ((brokerid, messagesPerBrokerMap) <- partitionedData) {
if (logger.isTraceEnabled)
messagesPerBrokerMap.foreach(partitionAndEvent =>
trace("Handling event for Topic: %s, Broker: %d, Partitions: %s".format(partitionAndEvent._1, brokerid, partitionAndEvent._2)))
val messageSetPerBroker = groupMessagesToSet(messagesPerBrokerMap)
val failedTopicPartitions = send(brokerid, messageSetPerBroker)
failedTopicPartitions.foreach(topicPartition => {
messagesPerBrokerMap.get(topicPartition) match {
case Some(data) => failedProduceRequests.appendAll(data)
case None => // nothing
}
})
}
} catch {
case t: Throwable => error("Failed to send messages", t)
}
failedProduceRequests
case None => // all produce requests failed
messages
}
}
During a match, do you create a variable on the fly? is it equal to partitionedDataOpt ?
partitionedDataOpt is an Option and can be either a Some(value) or a None (both are subtypes of Option)
If partitionedDataOpt is a Some Option, it wraps the actual value inside, and the pattern matching marks partitionedData as the value contained in the option. In that case you can name it however you want, and it is local to the matched case.
During a match, do you create a variable on the fly?
You can say so, I think partitionedData can be seen as a local val scoped in the case clause
is it equal to partitionedDataOpt ?
You can say it's equal to partitionedDataOpt.get if partitionedDataOpt has a value (e.g. a Some)
It is not unique to Options by the way Some and None are simply case classes extending Option (source)
/** Class `Some[A]` represents existing values of type
* `A`.
*
* #author Martin Odersky
* #version 1.0, 16/07/2003
*/
final case class Some[+A](x: A) extends Option[A] {
def isEmpty = false
def get = x
}
/** This case object represents non-existent values.
*
* #author Martin Odersky
* #version 1.0, 16/07/2003
*/
case object None extends Option[Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("None.get")
}

Access ScalaTest test name from inside test?

Is it possible to access the name of the currently executing test, from within a ScalaTest test? (And how would I do it?)
Background:
I'm testing that my Data Access Object eventually throws an OverQuotaException if a user e.g. creates too many pages. These tests take rather long to run. To feel happier, I'd like to print the progress to stdout — and since there are quite many tests, I'd like to include the test name in the output, so I know what test is currently being run.
(I didn't find any seemingly relevant function here: http://www.artima.com/docs-scalatest-2.0.M5/#org.scalatest.FreeSpec )
Example:
"QuotaCharger can" - {
"charge and decline quota consumers" - {
"charge a per site IP number (guest user)" in {
// ... Here, a guest user post very many comments until it's over quota.
// This takes a little while, and there are many similar tests.
// ---> Here <--- I'd like to access the string:
// "charge a per site IP number (guest user)",
// is that possible somehow?
}
The intended way to do that is to override withFixture and capture the test data. In this use case, it is better to override withFixture in fixture.FreeSpec so you can pass the test data into each test rather than using a var. Info on that is here:
http://www.artima.com/docs-scalatest-2.0.M5/org/scalatest/FreeSpec.html#withFixtureNoArgTest
When I saw your question this morning I realized ScalaTest should have a trait that does this, so I just added one. It will be in 2.0.M6, the next milestone release, but in the meantime you can use a local copy. Here it is:
import org.scalatest._
/**
* Trait that when mixed into a <code>fixture.Suite</code> passes the
* <code>TestData</code> passed to <code>withFixture</code> as a fixture into each test.
*
* #author Bill Venners
*/
trait TestDataFixture { this: fixture.Suite =>
/**
* The type of the fixture, which is <code>TestData</code>.
*/
type FixtureParam = TestData
/**
* Invoke the test function, passing to the the test function to itself, because
* in addition to being the test function, it is the <code>TestData</code> for the test.
*
* <p>
* To enable stacking of traits that define <code>withFixture(NoArgTest)</code>, this method does not
* invoke the test function directly. Instead, it delegates responsibility for invoking the test function
* to <code>withFixture(NoArgTest)</code>.
* </p>
*
* #param test the <code>OneArgTest</code> to invoke, passing in the
* <code>TestData</code> fixture
*/
def withFixture(test: OneArgTest) {
withFixture(test.toNoArgTest(test))
}
}
You would use it like this:
import org.scalatest._
class MySpec extends fixture.FreeSpec with TestDataFixture {
"this technique" - {
"should work" in { td =>
assert(td.name == "this technique should work")
}
"should be easy" in { td =>
assert(td.name == "this technique should be easy")
}
}
}
Create your own trait, let say RichFreeSpec.
trait RichFreeSpec extends Free {
protected final class RichFreeSpecStringWrapper(name: scala.Predef.String) {
def in(f: String => scala.Unit) {
def f2 = f(name)
new WordSpecStringWrapper(string).in(f2)
}
}
protected implicit def convertToRichFreeSpecStringWrapper(n: scala.Predef.String): = {
new RichFreeSpecStringWrapper(n)
}
}
Than just use:
"sth" in { testName =>
...
}
Of course, you can go further and implement the full name hierarchy.
You can use BeforeAndAfterEachTestData for what you need.
If you need access to the test case name in the beforeEach or afterEach method.
class MyTestSuite with AnyFunSuiteLike with BeforeAndAfterEachTestData {
override def beforeEach(testData: TestData): Unit = {
testData.name // do whatever.
super.beforeEach(testData)
}
}
If you need access to the test case name in the test case itself, then you can use a thread local approach
private val currentTestCaseName = new ThreadLocal[String]
override def beforeEach(testData: TestData): Unit = {
currentTestCaseName.set(testData.name)
super.beforeEach(testData)
}
test("fancy test") {
currentTestCaseName.get() // do whatever
}
Here's a solution. Extend this class instead of FreeSpec. License: CC0.
Edit: This doesn't work with concurrent tests though.
(The difference between this approach and the other answer, is that 1) here there's a currentTestName field, and in the other answer the test name is passed to the test body, and 2) this test name includes all test branch names concatenated + the actual test name, whereas the other answer's test name is exactly the test name (without test branch names).)
(Ooops, you'd need to use getOrElse ... instead of my lovely getOrDie.)
/**
* Adds a field `currentTestName` that you can use inside a FreeSpec test,
* if you for example have many tests that take rather long, and you wonder
* which one is currently running.
*/
trait RichFreeSpec extends FreeSpec {
private var _currentTestName: Option[String] = None
def currentTestName = _currentTestName getOrDie "DwE90RXP2"
protected override def runTest(testName: String, args: org.scalatest.Args) {
_currentTestName = Some(testName)
super.runTest(testName, args)
}
}
If the intent is to be able to access the test name from anywhere, as was suggested by #kajmanus in previous comments, a ThreadLocal fits the bill nicely.
You could define a case class to store the info you require for the current test context. e.g.,
case class TestContext(name: Option[String] = None)
object TestContext {
val currentTest: ThreadLocal[TestContext] =
ThreadLocal.withInitial(() => TestContext())
}
Then define a trait your various specs will extend. e.g.,
trait BaseFunSpec
extends AnyFunSpec
...
{
override protected def withFixture(test: NoArgTest): Outcome = {
try {
TestContext.currentTest.set(TestContext(name = Some(test.name)))
super.withFixture(test)
} finally {
TestContext.currentTest.remove()
}
}
}
Finally, you can access the current test context you've set for the current thread (which in this example is purely the test name) from anywhere within the current thread as needed. e.g.,
def cachedResults(bytes: Array[Byte], fileType: String): Unit = {
TestContext.currentTest.get().name match {
case Some(testname) =>
import scala.util.Using
val file = new File("target", s"${testname}.${fileType}")
Using(new BufferedOutputStream(new FileOutputStream(file))) { os =>
os.write(bytes)
}
case None => throw new IllegalStateException("Unknown test context")
}
}
This will work whether you're running tests in parallel or not, assuming you're not processing things asynchronously (i.e., in another thread).
A cleaner usage of this is to create purposed actors. e.g.,
case class TestContext(name: Option[String] = None)
object TestContext {
val currentTest: ThreadLocal[TestContext] = ThreadLocal.withInitial(() => TestContext())
class TestNamer {
def currentName: String = currentTest.get().name match {
case Some(testname) => testname
case None => throw new IllegalStateException("No test context available")
}
}
class TestContextWriter(testNamer: TestNamer = new TestNamer()) {
def cachedBytes(bytes: Array[Byte], extension: String): Array[Byte] = {
import java.io.{BufferedOutputStream, File, FileOutputStream}
import scala.util.Using
val file = new File("target", s"${testNamer.currentName}.${extension}")
Using(new BufferedOutputStream(new FileOutputStream(file))) { outstream =>
outstream.write(bytes)
}
bytes
}
}
}
And inject as needed:
trait BaseFunSpec {
val testContextWriter = new TestContextWriter()
def fetchRawResults(...): Array[Byte] = {
...
testContextWriter.cachedBytes(bytes, "pdf")
}
}