Chain functions in different way - scala

Scala functions has following methods for chaining:
fn1.andThen(fn2)
fn1.compose(fn2)
But how can be written this case:
I have function cleanUp() which has to be called always as last step.
And I have a bunch of other functions, like that:
class Helper {
private[this] val umsHelper = new UmsHelper()
private[this] val user = umsHelper.createUser()
def cleanUp = ... // delete user/ and other entities
def prepareModel(model: TestModel) = {
// create model on behalf of the user
}
def commitModel() = {
// commit model on behalf of the user
}
}
And some external code can use code something like this:
val help = new Helper()
help.prepareModel()
help.commitModel()
// last step should be called implicitly cleanUp
How this can be written in a functional way, that chaining will always
call cleanUp function implicitly as last step?
Note: I see it as analogue of destructor in C++. Some chaining (doesn't matter how this chain is done) fn1 andLater fn2 andLater fn3 have to call as last step cleanUp (fn1 andLater fn2 andLater fn3 andLater cleanUp). Wrong with directly writing cleanUp method is there is a big chance someone will miss this step and user will be leaked (will be stayed in database)

This is a more advanced alternative:
When you hear "context" and "steps", there's a functional pattern that directly comes to mind: Monads. Rolling up your own monad instance can simplify the user-side of putting valid steps together, while providing warranties that the context will be cleaned up after them.
Here, we are going to develop a "CleanableContext" construction that follows that pattern.
We base our construct on the most simple monad, one whose only function is to hold a value. We're going to call that Context
trait Context[A] { self =>
def flatMap[B](f:A => Context[B]): Context[B] = f(value)
def map[B](f:A => B): Context[B] = flatMap(f andThen ((b:B) => Context(b)))
def value: A
}
object Context {
def apply[T](x:T): Context[T] = new Context[T] { val value = x }
}
Then we have a CleanableContext, which is capable of "cleaning up after itself" provided some 'cleanup' function:
trait CleanableContext[A] extends Context[A] {
override def flatMap[B](f:A => Context[B]): Context[B] = {
val res = super.flatMap(f)
cleanup
res
}
def cleanup: Unit
}
And now, we have an object that's able to produce a cleanable UserContext that will take care of managing the creation and destruction of users.
object UserContext {
def apply(x:UserManager): CleanableContext[User] = new CleanableContext[User] {
val value = x.createUser
def cleanup = x.deleteUser(value)
}
}
Let's say that we have also our model and business functions already defined:
trait Model
trait TestModel extends Model
trait ValidatedModel extends Model
trait OpResult
object Ops {
def prepareModel(user: User, model: TestModel): Model = new Model {}
def validateModel(model: Model): ValidatedModel = new ValidatedModel {}
def commitModel(user: User, vmodel: ValidatedModel): OpResult = new OpResult {}
}
Usage
With that reusable machinery in place, our users can express our process in a succinct way:
import Ops._
val ctxResult = for {
user <- UserContext(new UserManager{})
validatedModel <- Context(Ops.prepareModel(user, testModel)).map(Ops.validateModel)
commitResult <- Context(commitModel(user, validatedModel))
} yield commitResult
The result of the process is still encapsulated, and can be taken "out" from the Context with the value method:
val result = ctxResult.value
Notice that we need to encapsulate the business operations into a Context to be used in this monadic composition. Note as well that we don't need to manually create nor cleanup the user used for the operations. That's taken care of for us.
Furthermore, if we needed more than one kind of managed resource, this method could be used to take care of managing additional resources by composing different contexts together.
With this, I just want to provide another angle to the problem. The plumbing is more complex, but it creates a solid ground for users to create safe processes through composition.

I think that the core of the question is "how to keep a resource within a managed context". i.e. provide users with a way to use the resource and prevent it to 'leak' outside its context.
One possible approach is to provide a functional access to the managed resource, where the API requires functions to operate over the resource in question. Let me illustrate this with an example:
First, we define the domain of our model: (I've added some subtypes of Model to make the example more clear)
trait User
trait Model
trait TestModel extends Model
trait ValidatedModel extends Model
trait OpResult
// Some external resource provider
trait Ums {
def createUser: User
def deleteUser(user: User)
}
Then we create a class to hold our specific context.
class Context {
private val ums = new Ums{
def createUser = new User{}
def deleteUser(user: User) = ???
}
def withUserDo[T](ops: User => T):T = {
val user = ums.createUser
val result = ops(user)
ums.deleteUser(user)
result
}
}
The companion object provides (some) operations on the managed resource. Users can provide their own functions as well.
object Context {
def prepareModel(model: TestModel): User => Model = ???
val validateModel: Model => ValidatedModel = ???
val commitModel: ValidatedModel => OpResult = ???
}
We can instantiate our context and declare operations on it, using a classic declaration, like:
val ctx = new Context
val testModel = new TestModel{}
val result = ctx.withUserDo{ user =>
val preparedModel = prepareModel(testModel)(user)
val validatedModel = validateModel(preparedModel)
commitModel(validatedModel)
}
Or, given the desire in the question to use functional composition, we could rewrite this as:
val result = ctx.withUserDo{
prepareModel(testModel) andThen validateModel andThen commitModel
}

Use autoClean this will automatically call cleanUp at the end.
create a HelperStuff trait which contains all the necessary functions.
Inside the Helper object create a private implementation of the HelperStuff and then have a method method called autoClean which does the work keeping the Helper instance private and safe way from the rouge users.
Helper.autoClean { helperStuff =>
//write all your code here. clean up will happen automatically
helper.foo()
helper.commitModel()
}
Here is the autoClean function for you
trait HelperStuff {
def foo(): Unit
def commitModel: Unit
def cleanUp(): Unit
}
object Helper {
private class Helper extends HelperStuff {
def foo(): Unit = println("foo")
def cleanUp(): Unit = println("cleaning done")
}
private val helper = new Helper()
def autoClean[T](code: HelperStuff => T): T = {
val result = code(helper)
helper.cleanUp()
result
}
}

Related

How can I create a DSL involving "blocks" where certain functions are in-scope?

Overview
I have a Kotlin-based project that defines a DSL, but for reasons given below I'm now investigating whether it would be better to write my project in Scala. As Scala doesn't seem to lend itself to creating DSLs with as much ease as in Kotlin, I'm not entirely sure how I'd recreate the same DSL in Scala.
Before this gets flagged as a duplicate of this question, I've looked at that but my DSL requirements are somewhat different and I haven't been able to figure out a solution from that.
Details
I'm trying to create a flow-based programming system for developing automated vehicle part test procedures, and for the past couple of weeks I've been testing out an implementation of this in Kotlin, since it seems to support a lot of features that are really nice for creating FBP systems (native coroutine support, easy creation of DSLs using type-safe builders, etc.).
As awesome as Kotlin is though, I'm starting to realise that it would help a lot if the implementation language for the FBP was more functional, since FBP's seem to share a lot in common with functional languages. In particular, being able to define and consume typeclasses would be really useful for a project like this.
In Kotlin, I've created a DSL representing the "glue" language between nodes in a flow-based system. For example, given the existence of two blackbox processes Add and Square, I can define a "composite" node that squares the sum of two numbers:
#CompositeNode
private fun CompositeOutputtingScalar<Int>.addAndSquare(x: Int, y: Int) {
val add = create<Add>()
val square = create<Square>()
connect {
input(x) to add.x
input(y) to add.y
add.output to square.input
square.output to output
}
}
The idea is that connect is a function that takes a lambda of form ConnectionContext.() -> Unit, where ConnectionContext defines various overloads of an infix function to (shadowing the built-in to function in the Kotlin stdlib) allowing me to define the connections between these processes (or nodes).
This is my attempt to do something similar in Scala:
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]) {}
}
class InputPort[+A]
object connect {
val connections = new ListBuffer[Connection[_]]()
case class Connection[A](outputPort: OutputPort[A], inputPort: InputPort[A])
class ConnectionTracker() {
def track[A](connection: Connection[A]) {}
}
// Cannot make `OutputPort.connectTo` directly return a `Connection[A]`
// without sacrificing covariance, so make an implicit wrapper class
// that does this instead
implicit class ExtendedPort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = {
outputPort connectTo inputPort
connections += Connection(outputPort, inputPort)
}
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
output |> input // Should not be valid here
connect {
output |> input // Should be valid here
}
}
Right now this won't compile because ConnectablePort isn't in scope. I can bring it into scope by doing:
import connect._
connect {
output |> input // Should be valid here
}
However, it's undesirable to have to do this within the node definition.
To summarise, how can I recreate the DSL I've made in Kotlin within Scala? For reference, this is how I've defined my Kotlin DSL:
interface Composite {
fun <U : ExecutableNode> create(id: String? = null): U
fun connect(apply: ConnectionContext.() -> Unit)
class ConnectionContext {
val constants = mutableListOf<Constant<*>>()
fun <T> input(parameter: T): OutputPort<T> = error("Should not actually be invoked after annotation processing")
fun <T> input(parameterPort: OutputPort<T>) = parameterPort
fun <T> constant(value: T) = Constant(value.toString(), value)
infix fun <U, V> U.to(input: InputPort<V>): Nothing = error("Cannot connect value to specified input")
infix fun <U> OutputPort<U>.to(input: InputPort<U>) = this join input
infix fun <T, U> T.to(other: U): Nothing = error("Invalid connection")
}
}
interface CompositeOutputtingScalar<T> : Composite {
val output: InputPort<T>
}
interface CompositeOutputtingCluster<T : Cluster> : Composite {
fun <TProperty> output(output: T.() -> TProperty): InputPort<TProperty>
}
Just turning on the |> is pretty straightforward in Scala if you use a companion object, and is something always available with the output port
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]):Unit = {}
}
class InputPort[+A]
object OutputPort{
implicit class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo inputPort
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
output |> input // Should be valid here
}
Judiciously deciding where to do imports is a core Scala concept. It is how we turn on implicit in our code, like the following, is very common, since that is the way we turn on our type classes.
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]): Unit = {}
}
class InputPort[+A]
object Converter {
implicit class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo inputPort
}
}
def someCompositeFunction() {
val output = new OutputPort[Int]
val input = new InputPort[Int]
import Converter._
output |> input // Should be valid here
}
Now, I think this is what you are looking for, but there are still some import and implicit that needs to be setup, but this would enclose the implicit behavior:
class OutputPort[-A] {
def connectTo(inputPort: InputPort[A]): Unit = {}
}
class InputPort[+A]
object Converter {
private class ConnectablePort[A](outputPort: OutputPort[A]) {
def |>(inputPort: InputPort[A]): Unit = outputPort connectTo
inputPort
}
def convert[A](f: (OutputPort[A] => ConnectablePort[A]) => Unit): Unit = {
def connectablePortWrapper(x: OutputPort[A]): ConnectablePort[A] = new ConnectablePort[A](x)
f(connectablePortWrapper _)
}
}
object MyRunner extends App {
val output = new OutputPort[Int]
val input = new InputPort[Int]
import Converter.convert
//output |> input won't work
convert[Int] { implicit wrapper =>
output |> input // Should be valid here
}
}

Injecting playFramework dependancies to scala object using MacWire traits fail

Lets say I have bunch of car objects in my project, for example:
object Porsche extends Car {
override def start() {...}
override def canStart(fuelInLitr: Int) = fuelInLitr > 5
override val fuelInLitr = 45
override val carId = 1234567
}
im extending Car which is just a trait to set a car structure:
trait Car {
def start(): Unit
val canStart(fuel: Double): Boolean
val fuelInLitr: Int
val carId: Int
}
Now, in the start() method I want to use some api service that will give me a car key based on its id so I cant start the car.
So I have this CarApiService:
class CarApiService (wsClient: WSClient, configuration: Configuration) {
implicit val formats: Formats = DefaultFormats
def getCarkey(carId: String): Future[Option[CarKey]] = {
val carInfoServiceApi = s"${configuration.get[String]("carsdb.carsInfo")}?carId=$carId"
wsClient.url(carInfoServiceApi).withHttpHeaders(("Content-Type", "application/json")).get.map { response =>
response.status match {
case Status.OK => Some(parse(response.body).extract[CarKey])
case Status.NO_CONTENT => None
case _ => throw new Exception(s"carsdb failed to perform operation with status: ${response.status}, and body: ${response.body}")
}
}
}
}
I want to have the ability to use getCarkey() in my car objects, so I created a CarsApiServicesModule which will give my access to the carApiService and I can use its methods:
trait CarsApiServicesModule {
/// this supply the carApiService its confuguration dependancy
lazy val configuration: Config = ConfigFactory.load()
lazy val conf: Configuration = wire[Configuration]
/// this supply the carApiService its WSClient dependancy
lazy val wsc: WSClient = wire[WSClient]
lazy val carApiService: CarApiService = wire[CarApiService]
}
and now I want to add mix this trait in my car object this way:
object Porsche extends Car with CarsApiServicesModule {
// here I want to use myApiService
// for example: carApiService.getCarkey(carId)...
}
but when compiling this I get this error:
does anyone know what is the issue?
also, is that design make sense?
You need to keep in mind that wire is just a helper macro which tries to generate new instance creation code: it's quite dumb, in fact. Here, it would try to create a new instance of WSClient.
However, not all objects can be instantiated using a simple new call - sometimes you need to invoke "factory" method.
In this case, if you take a look at the readme on GitHub, you'll see that to instantiate the WSClient, you need to create it through the StandaloneAhcWSClient() object.
So in this case, wire won't help you - you'll need to simply write the initialisation code by hand. Luckily it's not too large.

How do I share a single object with multiple Scalatest suites?

I have a number of test files, each with their own tests. Until now, each one has a trait in which I create a configuration object.
Building that object now takes the better part of two minutes, as it has to do a lot of work calling a number of databases (don't ask - really, it has to be done).
Is there a way to share this object (tldConfigMap, below) between multiple test suites in multiple files without having to build it over and over?
Here's how I was doing it - as you can see, when brought in as a trait, load() will be called every time:
trait TLDMapAcceptanceIsLoadedSpec extends org.scalatest.fixture.FlatSpecLike with TLDConfigMap {
val tldConfigMap: Map[String, TLDConfig] = load(withAttributes = true).right.get
type FixtureParam = Map[String, TLDConfig]
def withFixture(test: OneArgTest) = {
withFixture(test.toNoArgTest(tldConfigMap)) // "loan" the fixture to the test
}
}
You could just put it into an object (assuming it's really config and isn't changed by tests):
object TldConfigMap {
val tldConfigMap: Map[String, TLDConfig] = load(withAttributes = true).right.get
}
trait TLDMapAcceptanceIsLoadedSpec extends org.scalatest.fixture.FlatSpecLike with TLDConfigMap {
def tldConfigMap: Map[String, TLDConfig] = TldConfigMap.tldConfigMap // or just use it directly
type FixtureParam = Map[String, TLDConfig]
def withFixture(test: OneArgTest) = {
withFixture(test.toNoArgTest(tldConfigMap)) // "loan" the fixture to the test
}
}

Is it possible to mock a function that is defined within another function?

I have some functions that access a database, which I need to mock for testing purposes.
For ease of use, I would like to define these functions within another function, where I can leverage scope to reduce the number of arguments I have to pass.
I need to test the parent function, while mocking the nested functions.
Are there any tricks to mock functions that are nested?
As a secondary question, are there ways to mock functions when nested at arbitrary depth?
And a side note: my project is light enough I'm not even using classical mocking, just stackable traits like this blog post suggests; but for this question, any kind of mocking is fine.
Here is some very simple example code:
class Storage {
def storeData(specId: Long, data: String): Unit = {
val rawPath = "/path/to/file"
def storeFsEntry: Unit = {
// do stuff
}
def storeDbEntry: Unit = {
// do stuff we need mocked
}
if ( specId == 1 )
{
storeDbEntry
storeFsEntry
}
}
}
It's not possible, but you can define a trait and implement it inside your function (if you really want this logic been implemented inside):
class Storage {
trait Storing {
def path: String //you have to define all free members
def storeDbEntry: Unit
def storeFsEntry: Unit
}
def storeData(specId: Long, data: String, storingDefault: Option[Storing] = None): Unit = {
val myStoring = new Storing {
...implement it here
}
val storing = storingDefault getOrElse myStoring
import storing._
if ( specId == 1 ) {
storeDbEntry
storeFsEntry
}
}
}
Your mock will be something like that:
trait StorageMock extends Storage {
override def storeData(specId: Long, data: String, storingDefault: Option[Storing] = None): Unit = {
val storingOverride = new Storing { ... } //mocking functionality
super.storeData(specId, data, storingDefault orElse Some(storingOverride))
}
}
new Storage with StorageMock
You may also turn storingDefault into a member instead of function parameter.
The reason why it's not possible to do same for inner functions is that they are private and also typecheck can't be performed on them (in comparison with inner traits).

How store methods vals without recreating them every method call

I have Scala class which methods use a lot of regex. Each class method use some regex patterns.
Looking from the perspective of code modularity I should store those patterns in method:
class Bar {
def foo() {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
/*...*/
}
}
But this approach is quite inefficient. Patterns are recompiled on each method call.
I could move them directly to class:
class Bar {
val fooPatt1 = "[ab]+".r
val fooPatt2 = "[cd]+".r
/*...*/
}
but in case when I have 30 methods it looks ugly.
I ended up with some hybrid solution using val and anonymous function:
val z = {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
() => { /* ... */ }
}
but I am not sure if using val to store function have some drawbacks compared to def. Maybe there is other clean solution to store methods constants without polluting the class?
Using a val is perfectly fine. There might be a (very) small performance hit, but in most (99.9%) of the applications that's not a problem.
You could also create a class for the method
// The extends is not needed, although you might want to hide the Foo type
class Foo extends (() => ...) {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
def apply() = {
...
}
}
Then in the class:
class Bar {
val foo = new Foo
}
Another solution is using traits
trait Foo {
private lazy val patt1 = "[ab]+".r
private lazy val patt2 = "[cd]+".r
def foo() = ...
}
class Bar extends Foo with ...
Note that if you have different methods like that in a single class, it can be sign that the single responsibility principle is violated. Moving them to their own class (or trait) can be a solution for that problem as well.
I would put every method with the necessary regex in it's own Trait:
class Bar extends AMethod with BMethod
trait AMethod {
private val aPattern = """\d+""".r
def aMethod(s: String) = aPattern.findFirstIn(s)
}
trait BMethod {
private val bPattern = """\w+""".r
def bMethod(s: String) = bPattern.findFirstIn(s)
}
clean
separated
easy to test (object AMethodSpec extends Properties("AMethod") with AMethod ...)
I took into account Chris comment. Putting patterns to companion object is probably the most efficient approach but very unclean when we have more methods.
EECOLOR solution is less efficient but cleaner. Traits prevents recreating patterns on each method call. Unfortunately, scala do not use same compiled pattern accross multiple class instances:
(new X).patt1==(new X).patt1 // would be false.
I've combined those two approaches and instead traits I used objects.
object X {
object method1 {
val patt1 = "a".r
}
object method2 {
val patt1 = "a".r
}
}
class X {
def method1 = {
import X.method1._
patt1
}
def method2 = {
import X.method2._
patt1
}
}
(new X).method1 == (new X).method1 // true
(new X).method2 == (new X).method2 // true
Although this approach works, I think scala should provide some solution for that problem out of box. Patterns are the simplest example. We could have other immutable objects which initialization is much more expensive.
Extracting method internals somewhere outside is still unclear. It would be nice to do it like with lazy vals. Adding one modificator should ensure that value is instance only once across all instances and methods calls. It would be something like that:
def method1 {
static val x = new VeryExpensiveObject
}