I've been reading about the OO 'fluent interface' approach in Java, JavaScript and Scala and I like the look of it, but have been struggling to see how to reconcile it with a more type-based/functional approach in Scala.
To give a very specific example of what I mean: I've written an API client which can be invoked like this:
val response = MyTargetApi.get("orders", 24)
The return value from get() is a Tuple3 type called RestfulResponse, as defined in my package object:
// 1. Return code
// 2. Response headers
// 2. Response body (Option)
type RestfulResponse = (Int, List[String], Option[String])
This works fine - and I don't really want to sacrifice the functional simplicity of a tuple return value - but I would like to extend the library with various 'fluent' method calls, perhaps something like this:
val response = MyTargetApi.get("customers", 55).throwIfError()
// Or perhaps:
MyTargetApi.get("orders", 24).debugPrint(verbose=true)
How can I combine the functional simplicity of get() returning a typed tuple (or similar) with the ability to add more 'fluent' capabilities to my API?
It seems you are dealing with a client side API of a rest style communication. Your get method seems to be what triggers the actual request/response cycle. It looks like you'd have to deal with this:
properties of the transport (like credentials, debug level, error handling)
providing data for the input (your id and type of record (order or customer)
doing something with the results
I think for the properties of the transport, you can put some of it into the constructor of the MyTargetApi object, but you can also create a query object that will store those for a single query and can be set in a fluent way using a query() method:
MyTargetApi.query().debugPrint(verbose=true).throwIfError()
This would return some stateful Query object that stores the value for log level, error handling. For providing the data for the input, you can also use the query object to set those values but instead of returning your response return a QueryResult:
class Query {
def debugPrint(verbose: Boolean): this.type = { _verbose = verbose; this }
def throwIfError(): this.type = { ... }
def get(tpe: String, id: Int): QueryResult[RestfulResponse] =
new QueryResult[RestfulResponse] {
def run(): RestfulResponse = // code to make rest call goes here
}
}
trait QueryResult[A] { self =>
def map[B](f: (A) => B): QueryResult[B] = new QueryResult[B] {
def run(): B = f(self.run())
}
def flatMap[B](f: (A) => QueryResult[B]) = new QueryResult[B] {
def run(): B = f(self.run()).run()
}
def run(): A
}
Then to eventually get the results you call run. So at the end of the day you can call it like this:
MyTargetApi.query()
.debugPrint(verbose=true)
.throwIfError()
.get("customers", 22)
.map(resp => resp._3.map(_.length)) // body
.run()
Which should be a verbose request that will error out on issue, retrieve the customers with id 22, keep the body and get its length as an Option[Int].
The idea is that you can use map to define computations on a result you do not yet have. If we add flatMap to it, then you could also combine two computations from two different queries.
To be honest, I think it sounds like you need to feel your way around a little more because the example is not obviously functional, nor particularly fluent. It seems you might be mixing up fluency with not-idempotent in the sense that your debugPrint method is presumably performing I/O and the throwIfError is throwing exceptions. Is that what you mean?
If you are referring to whether a stateful builder is functional, the answer is "not in the purest sense". However, note that a builder does not have to be stateful.
case class Person(name: String, age: Int)
Firstly; this can be created using named parameters:
Person(name="Oxbow", age=36)
Or, a stateless builder:
object Person {
def withName(name: String)
= new { def andAge(age: Int) = new Person(name, age) }
}
Hey presto:
scala> Person withName "Oxbow" andAge 36
As to your use of untyped strings to define the query you are making; this is poor form in a statically-typed language. What is more, there is no need:
sealed trait Query
case object orders extends Query
def get(query: Query): Result
Hey presto:
api get orders
Although, I think this is a bad idea - you shouldn't have a single method which can give you back notionally completely different types of results
To conclude: I personally think there is no reason whatsoever that fluency and functional cannot mix, since functional just indicates the lack of mutable state and the strong preference for idempotent functions to perform your logic in.
Here's one for you:
args.map(_.toInt)
args map toInt
I would argue that the second is more fluent. It's possible if you define:
val toInt = (_ : String).toInt
That is; if you define a function. I find functions and fluency mix very well in Scala.
You could try having get() return a wrapper object that might look something like this
type RestfulResponse = (Int, List[String], Option[String])
class ResponseWrapper(private rr: RestfulResponse /* and maybe some flags as additional arguments, or something? */) {
def get : RestfulResponse = rr
def throwIfError : RestfulResponse = {
// Throw your exception if you detect an error
rr // And return the response if you didn't detect an error
}
def debugPrint(verbose: Boolean, /* whatever other parameters you had in mind */) {
// All of your debugging printing logic
}
// Any and all other methods that you want this API response to be able to execute
}
Basically, this allows you to put your response into a contain that has all of these nice methods that you want, and, if you simply want to get the wrapped response, you can just call the wrapper's get() method.
Of course, the downside of this is that you will need to change your API a bit, if that's worrisome to you at all. Well... you could probably avoid needing to change your API, actually, if you, instead, created an implicit conversion from RestfulResponse to ResponseWrapper and vice versa. That's something worth considering.
Related
I have a following question. Our project has a lot of code, that runs tests in Scala. And there is a lot of code, that fills the fields like this:
production.setProduct(new Product)
production.getProduct.setUuid("b1253a77-0585-291f-57a4-53319e897866")
production.setSubProduct(new SubProduct)
production.getSubProduct.setUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c")
Eventually, I grew tired from this code, since all those fields are actually subclasses of the basic class that has the uuid field, so, after thinking a while, I wrote the auxiliary function like this:
def createUuid[T <: GenericEntity](uuid: String)(implicit m : Manifest[T]) : T = {
val constructor = m.runtimeClass.getConstructors()(0)
val instance = constructor.newInstance().asInstanceOf[T]
instance.setUuid(uuid)
instance
}
Now, my code got two times shorter, since now I can write something like this:
production.setProduct(createUuid[Product]("b1253a77-0585-291f-57a4-53319e897866"))
production.setSubProduct(createUuid[SubProduct]("89a877fa-ddb3-3009-bb24-735ba9f7281c"))
That's good, but I am wondering, if I could somehow implement the function createUuid so the last bit would like this:
// Is that really possible?
production.setProduct(createUuid("b1253a77-0585-291f-57a4-53319e897866"))
production.setSubProduct(createUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c"))
Can scala compiler guess, that setProduct expects not just a generic entity, but actually something like Product (or it's subclass)? Or there is no way in Scala to implement this even shorter?
Scala compiler won't infer/propagate the type outside-in. You could however create implicit conversions like:
implicit def stringToSubProduct(uuid: String): SubProduct = {
val n = new SubProduct
n.setUuid(uuid)
n
}
and then just call
production.setSubProduct("89a877fa-ddb3-3009-bb24-735ba9f7281c")
and the compiler will automatically use the stringToSubProduct because it has applicable types on the input and output.
Update: To have the code better organized I suggest wrapping the implicit defs to a companion object, like:
case class EntityUUID(uuid: String) {
uuid.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") // possible uuid format check
}
case object EntityUUID {
implicit def toProduct(e: EntityUUID): Product = {
val p = new Product
p.setUuid(e.uuid)
p
}
implicit def toSubProduct(e: EntityUUID): SubProduct = {
val p = new SubProduct
p.setUuid(e.uuid)
p
}
}
and then you'd do
production.setProduct(EntityUUID("b1253a77-0585-291f-57a4-53319e897866"))
so anyone reading this could have an intuition where to find the conversion implementation.
Regarding your comment about some generic approach (having 30 types), I won't say it's not possible, but I just do not see how to do it. The reflection you used bypasses the type system. If all the 30 cases are the same piece of code, maybe you should reconsider your object design. Now you can still implement the 30 implicit defs by calling some method that uses reflection similar what you have provided. But you will have the option to change it in the future on just this one (30) place(s).
I'm attempting to write a method which accepts multiple generic types and takes as an argument a unit of work to execute.
The idea is that the unit of work is a common function that itself is generic. For the sake of example, let's say it's something like the following:
def loadModelRdd[T: TypeTag](sc: SparkContext): RDD[T] = {
...
}
loadModelRdd() will construct an RDD of the given type after some internal processing like loading the Model information, etc.
A prototype method I've been hacking on looks something like the following (non-working):
def forkAll[A : Manifest, B : Manifest](work: => RDD[_]): (RDD[A], RDD[B]) = {
def aFuture = Future { work } // How can I notify that this work call returns type A?
def bFuture = Future { work } // How can I notify that this work call returns type B?
val res = for {
a <- aFuture
b <- bFuture
} yield (a.asInstanceOf[A], b.asInstanceOf[B])
Await.result(res, 10.seconds)
}
This is a shortened version of the code I'm working on as I'm actually looking at accepting as many as 10 different types.
As you can see, the overall goal of the forkAll method is to wrap the unit of work in a Future, fork-join the execution of the unit of work for each type, then return the results as a Tuple'd result. An example consumer statement would be:
val (a, b) = forkAll[ClassA, ClassB](loadModelRdd)
i.e I want to fork-join at this point and wait for the results, but I want the executions to be executed in parallel and then collected back to the Driver (Spark Driver to be specific).
The problem is I'm not sure how to coerce the type returned by the unit of work within forkAll when constructing the Future {} blocks. Without the forkAll, the implementation looked like the following:
val resA = loadModelRdd[ClassA](sc)
val resB = loadModelRdd[ClassB](sc)
...
I am looking at doing this for two reasons:
To abstract the details of fork-join for any unit of work which matches this model.
A version of this code, which explicitly states what the unit of work is, is working in Production and was responsible for cutting execution of a long-running block by close to half. I have a couple of execution steps where this pattern could be applied
Is this something that is possible in Scala's type system? Or should I look at this problem from a different perspective? I've tried a couple of implementations (including one described here) but I haven't quite found one that fits my current view of the problem
Please let me know if there is any additional information needed.
Thanks!
Short answer: Scala does not allow functions with type parameters, so what you want is not exactly possible.
You are attempting to pass a method with a type parameter. Although methods are allowed to have type parameters, functions are not. When you try to pass a method, it acts like an anonymous function, so you must specify a type.
However, since methods do allow type parameters, you can take advantage of this by creating an abstract class that will do your fork/join
abstract class ForkJoin {
protected def work[T]: RDD[T]
def apply[A, B]: (RDD[A], RDD[B]) = {
// Write implementation of fork/join here
(work[A], work[B])
}
}
then overriding the type generic work method so that it does what you want, such as calling some other pre-defined method.
val forkJoin = new ForkJoin {
override protected def work[T]: RDD[T] =
loadModelRdd[T](sc)
}
val (intRdd, stringRdd) = forkJoin[Int, String]
Check out this for a prototype implementation that compiles and runs without issues.
Often I find myself wanting to chain a side-effecting function to the end of another method call in a more functional-looking way, but I don't want to transform the original type to Unit. Suppose I have a read method that searches a database for a record, returning Option[Record].
def read(id: Long): Option[Record] = ...
If read returns Some(record), then I might want to cache that value and move on. I could do something like this:
read(id).map { record =>
// Cache the record
record
}
But, I would like to avoid the above code and end up with something more like this to make it more clear as to what's happening:
read(id).withSideEffect { record =>
// Cache the record
}
Where withSideEffect returns the same value as read(id). After searching high and low, I can't find any method on any type that does something like this. The closest solution I can come up with is using implicit magic:
implicit class ExtendedOption[A](underlying: Option[A]) {
def withSideEffect(op: A => Unit): Option[A] = {
underlying.foreach(op)
underlying
}
}
Are there any Scala types I may have overlooked with methods like this one? And are there are any potential design flaws from using such a method?
Future.andThen (scaladoc) takes a side-effect and returns a future of the current value to facilitate fluent chaining.
The return type is not this.type.
See also duplicate questions about tap.
You can use scalaz for "explicit annotation" of side-effectful functions. In scalaz 7.0.6 it's IO monad: http://eed3si9n.com/learning-scalaz/IO+Monad.html
It's deprecated in scalaz 7.1. I would do something like that with Task
val readAndCache = Task.delay(read(id)).map(record => cacheRecord(record); record)
readAndCache.run // Run task for it's side effects
I'm writing a message parser. Suppose I have a superclass Message with two auxiliary constructors, one that accepts String raw messages and one that accepts a Map with datafields mapped out in key-value pairs.
class Message {
def this(s: String)
def this(m: Map[String, String])
def toRaw = { ... } # call third party lib to return the generated msg
def map # call third party lib to return the parsed message
def something1 # something common for all messages which would be overriden in child classes
def something2 # something common for all messages which would be overriden in child classes
...
}
There's good reason to do this as the library that does parsing/generating is kind of awkward and removing the complexity of interfacing with it into a separate class makes sense, the child class would look something like this:
class SomeMessage extends Message {
def something1 # ...
def something2 # ...
}
and the idea is to use the overloaded constructors in the child class, for example:
val msg = new SomeMessage(rawMessage) # or
val msg = new SomeMessage("fld1" -> ".....", "fld2" -> "....")
# and then be able to call
msg.something1
msg.something2 # ...
However, the way auxiliary constructors and inheritance seem to behave in Scala this pattern has proven to be pretty challenging, and the simplest solution I found so far is to create a method called constructMe, which does the work of the constructors in the above case:
val msg = new SomeMessage
msg.constructMe(rawMessage) # or
msg.constructMe("fld1" -> ".....", "fld2" -> "....")
which seems crazy to need a method called constructMe.
So, the question:
is there a way to structure the code so to simply use the overloaded constructors from the superclass? For example:
val msg = new SomeMessage(rawMessage) # or
val msg = new SomeMessage("fld1" -> ".....", "fld2" -> "....")
or am I simply approaching the problem the wrong way?
Unless I'm missing something, you are calling the constructor like this:
val msg = new SomeMessage(rawMessage)
But the Message class doesn't not take a parameter, your class should be defined so:
class Message(val message: String) {
def this(m: Map[String, String]) = this("some value from mapping")
}
Also note that the constructor in scala must call the primary constructor as first action, see this question for more info.
And then the class extending the Message class should be like this:
class SomeMessage(val someString: String) extends Message(someString) {
def this(m: Map[String, String]) = this("this is a SomeMessage")
}
Note that the constructor needs a code block otherwise your code won't compile, you can't have a definition like def this(someString: String) without providing the implementation.
Edit:
To be honest I don't quite get why you want to use Maps in your architecture, your class main point it to contain a String, having to do with complex types in constructors can lead to problems. Let's say you have some class which can take a Map[String, String] as a constructor parameter, what will you do with it? As I said a constructor must call himself as first instruction, what you could is something like this:
class A(someString: String) = {
def this(map: Map[String, String]) = this(map.toString)
}
And that's it, the restrictions in scala don't allow you to do anything more, you would want to do some validation, for example let's say you want to take always the second element in the map, this could throw exceptions since the user is not forced to provide a map with more than one value, he's not even forced to provide a filled map unless you start filling your class with requires.
In your case I probably would leave String as class parameter or maybe a List[String] where you can call mkString or toString.
Anyway if you are satisfied calling map.toString you have to give both constructor implementation to parent and child class, this is one of scala constructor restrictions (in Java you could approach the problem in a different way), I hope somebody will prove me wrong, but as far as I know there's no other way to do it.
As a side note, I personally find this kind of restriction to be correct (most of the time) since the force you to structure your code to be more rigorous and have a better architecture, think about the fact that allowing people to do whatever they want in a constructor (like in java) obfuscate their true purpose, that is return a new instance of a class.
I'm writing a Scala application that accesses a database. Most of the time, there will be a connection available, but sometimes there won't be. What I'd like to do is something like the following:
object User {
def authenticate(username: String, password: String)
(implicit conn: Connection): Option[User] = {
// use conn to grab user from db and check that password matches
// return Some(user) if so, None if not
}
def authenticate(username: String, password: String): Option[User] = {
implicit val conn = DB.getConnection()
authenticate(username, password)
}
}
What I hoped would happen is that, if there's an implicit value of type Connection available, the compiler would use the first method. If not, it would use the second. Unfortunately, I've discovered that the compiler isn't quite that smart or, if it is, I'm not telling it what to do in the right way.
So, my basic question is, is there a way to write a method that expects an implicit argument and then provide an overloaded version of the same method that creates an acceptable value of the implicit parameter's type if there isn't one available.
You might say, "Why would you want to do such a thing? If you can create an acceptable value of the appropriate type, why not just always do it?" And that's mostly true, except that if I have an open database connection, I'd prefer to go ahead and use it rather than creating a new one. However, if I don't have an open database connection, I know where to get one.
I mean, the simple answer is to just give the two methods different names, but I shouldn't have to, gosh-darn-it. But maybe I do...
Thanks!
Todd
You don't need overloaded methods. Just give your implicit parameter a default value, i.e.
object User {
def authenticate(username:String, password:String)(implicit conn:Connection = null): Option[User] = {
val real_conn = Option(conn).getOrElse(DB.getConnection())
// do the rest with the real_conn
}
}
The cleaner solution which I can think of is using nested methods and as someone suggested, default values for implicits.
class Testclass {
def myMethod(a:Int)(implicit b:Option[Int]=None):Int = {
def myMethodInternal(a:Int, b:Int):Int = {
// do something
a+b
}
val toUse = b.getOrElse(30)
myMethodInternal(a,toUse)
}
}
Inside your method you define an myMethodInternal, which takes no implicits but only explicits parameters. This method will be visible only inside myMethod, and you will prepare your second parameter like the following:
val toUse = b.getOrElse(30)
And finally call your method with explicits parameters:
myMethodInternal(a,toUse)