When documenting parameters of methods with Scaladoc, we can write:
/** Is number even
* #param i number
* #return true if i is even, false otherwise
*/
def isEvenDef(i: Int) = i % 2 == 0
Which after generating the docs (e.g. via doc from sbt) yields nice documentation of the parameters (pointless in this example, but useful in general):
However, writing an analogous function via val and using the same documentation:
/** Is number even
* #param i number
* #return true if i is even, false otherwise
*/
val isEvenVal = (i: Int) => i % 2 == 0
The param does not seem to show in the generated documentation:
Is there a way do document the parameters for functions defined via val such that they show similarly to the parameters of methods defined via def?
Related
I have a function like so
def runOnce(request: Request): Future[Result] = {
}
When I call this runOnce function, if it has not been run, I want it to run some method and return that result. If it has been run, I just want it to return the original result (the request coming in will be the same).
I can do it if I have no param like so
lazy val hydratedModel = hydrateImpl(request)
future for efficient filtering
def fetchHydratedModel(): Future[HydratedModelRequest] = {
hydratedModel
}
How to do in first case?
There's a general solution to this problem, which is function memoization; for a pure function (one that has no side-effects - it will not work for non-pure functions), the result of a function call should always be the same for the same set of argument values. Therefore, an optimization is to cache the value on the first call and to return it for subsequent calls.
You can achieve this with something like the following (a memoization class for pure functions with a single argument, updated—see comment below—to make it thread-safe):
/** Memoize a pure function `f(A): R`
*
* #constructor Create a new memoized function.
* #tparam A Type of argument passed to function.
* #tparam R Type of result received from function.
* #param f Pure function to be memoized.
*/
final class Memoize1[A, R](f: A => R) extends (A => R) {
// Cached function call results.
private val result = scala.collection.mutable.Map.empty[A, R]
/** Call memoized function.
*
* If the function has not been called with the specified argument value, then the
* function is called and the result cached; otherwise the previously cached
* result is returned.
*
* #param a Argument value to be passed to `f`.
* #return Result of `f(a)`.
*/
def apply(a: A) = synchronized(result.getOrElseUpdate(a, f(a)))
}
/** Memoization companion */
object Memoize1 {
/** Memoize a specific function.
*
* #tparam A Type of argument passed to function.
* #tparam R Type of result received from function.
* #param f Pure function to be memoized.
*/
def apply[A, R](f: A => R) = new Memoize1(f)
}
Assuming that the function you're memoizing is hydrateImpl, you can then define and use runOnce as follows (note that it becomes a val not a def):
val runOnce = Memoize1(hydrateImpl)
runOnce(someRequest) // Executed on first call with new someRequest value, cached result subsequently.
UPDATE: Regarding thread-safety.
In reply to the comment from user1913596, the answer is "no"; scala.collection.mutable.Map.getOrElseUpdate is not thread-safe. However, it's fairly trivial to synchronize access, and I have updated the original code accordingly (embedding the call within sychronized(...)).
The performance hit of locking access should be negated by the improved execution time (assuming that f is nontrivial).
There are likely better ways to do this depending on your setup, but a simple solution is to do the following
private var model: Option[Future[HydratedModelRequest]] = None
def runOnce(request: Request): Future[Request] = {
if (model.isEmpty) {
model = hydrateImpl(request)
}
model.get
}
If the request is indeed the same for each call, another option would be to require the request implicitly and hydrate lazily.
implicit val request: Request
lazy val hydratedRequest: Future[HydratedModelRequest] = hydrateImpl(request)
I have a string which I would like to cross check if it is purely made of letters and space.
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet
if (str.forall(purestring(_))) println("PURE") else "NOTPURE"
The above CONCISE code does the job. However, if I run it this way:
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha(_)) // CONCISE code
I get an error (found: Char ... required: Boolean) and it can only work using the contains method this way:
str.forall(purealpha.contains(_))
My question is how can I use the CONCISE form without converting the string to a Set. Any suggestions on having my own String class with the right combination of methods to enable the nice code; or maybe some pure function(s) working on strings.
It's just a fun exercise I'm doing, so I can understand the intricate details of various methods on collections (including apply method) and how to write nice concise code and classes.
A slightly different approach is to use a regex pattern.
val str = "my long string to test"
val purealpha = "[ a-z]+"
str matches purealpha // res0: Boolean = true
If we look at the source code we can see that both these implementations are doing different things, although giving the same result.
When you are converting it to a Set and using the forAll, you are ultimately calling the apply method for the set. Here is how the apply is called explicitly in your code, also using named parameters in the anonymous functions:
if (str.forall(s => purestring.apply(s))) println("PURE") else "NOTPURE" // first example
str.forall(s => purealpha.apply(s)) // second example
Anyway, let's take a look at the source code for apply for Set (gotten from GenSetLike.scala):
/** Tests if some element is contained in this set.
*
* This method is equivalent to `contains`. It allows sets to be interpreted as predicates.
* #param elem the element to test for membership.
* #return `true` if `elem` is contained in this set, `false` otherwise.
*/
def apply(elem: A): Boolean = this contains elem
When you leave the String literal, you have to specifically call the .contains (this is the source code for that gotten from SeqLike.scala):
/** Tests whether this $coll contains a given value as an element.
* $mayNotTerminateInf
*
* #param elem the element to test.
* #return `true` if this $coll has an element that is equal (as
* determined by `==`) to `elem`, `false` otherwise.
*/
def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem)
As you can imagine, doing an apply for the String literal will not give the same result as doing an apply for a Set.
A suggestion on having more conciseness is to omit the (_) entirely in the second example (compiler type inference will pick that up):
val str = "my long string to test"
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet
str.forall(purealpha.contains)
Hi I am trying to learn org.apache.spark.ml design. I noticed in that param values are often retrieved by using $ symbol.
For example, in NGram.scala
val n: IntParam = new IntParam(this, "n", "number elements per n-gram (>=1)",
ParamValidators.gtEq(1))
/** #group setParam */
def setN(value: Int): this.type = set(n, value)
/** #group getParam */
def getN: Int = $(n)
Is $ a Scala operator with general features?
I can see in eclipse (when I hoverover $(n)) that it is defined as
final protected def $[T](param: Param[T]): T
but I could not find the class where it was defined the above way.
Can you please tell me where this is defined ?
A dollar sign is a perfectly legal method name in Scala. You can see the definition of this method here.
In this case, it is simply an alias for getOrDefault.
We're using the repository pattern for our data access in Scala and so far we have something like this in our Repository[A] trait:
trait Repository[A] {
/**
* Create a new record in the database.
*
* #param model
* #param connection
* #return
*/
def create(model: A)(implicit connection: Connection): A
/**
* Retrieve a record from the database with the corresponding id.
*
* #param id
* #param connection
* #return
*/
def getById(id: UUID)(implicit connection: Connection): Option[A]
/**
* Update the corresponding record in the database.
*
* #param model
* #param connection
* #return The updated model, or None if it was not found
*/
def update(model: A)(implicit connection: Connection): Option[A]
/**
* Delete a record from the database with the corresponding id.
*
* #param id
* #param connection
* #return The deleted model, or None if it was not found
*/
def deleteById(id: UUID)(implicit connection: Connection): Option[A]
}
And that's fine. This issue is with the "query" methods. For example, imagine I have a method for getting all blog posts where:
the user id is X, or
the user is a guest
I also want to include the blog object. Under our current system, we would have a method like this:
def getWithBlogByUserIdOrUserGuest(userId: UUID, guest: Boolean): List[Post]
This is pretty ugly, and if you want to return a bunch of relations with an entity (that have long names) it can get out of hand quickly. It's also hard to use an trait to add some sort of consistency.
Some examples I've seen only are to use a query object:
def query(criteria: Criteria): List[A]
However, this requires coming up with some sort of DSL for defining criteria, and it also requires writing code that converts the criteria to SQL which is error prone and a lot of work, and will probably suck.
So, my question is, how do most people deal with having some sort of generalized way to write query methods in repositories?
As you've already figured it out you can implement the "Query Object".
As to not "writing code that converts the criteria to SQL which is error prone and a lot of work" you can use a framework like Slick, which will do all the SQL generation for you and allows you to treat tables as collections and do things like:
posts.filter(post => post.userId == "USER-ID-1" || post.guest)
Slick's abstract class Query has a HOF called filter, so you can pass in your custom function to it to determine whether a record should be filtered out or not.
I've the following code:
trait AcceptExtractors {
/**
* Common extractors to check if a request accepts JSON, Html, etc.
* Example of use:
* {{{
* request match {
* case Accepts.Json() => Ok(toJson(value))
* case _ => Ok(views.html.show(value))
* }
* }}}
*/
object Accepts {
import play.api.http.MimeTypes
val Json = Accepting(MimeTypes.JSON)
val Html = Accepting(MimeTypes.HTML)
val Xml = Accepting(MimeTypes.XML)
val JavaScript = Accepting(MimeTypes.JAVASCRIPT)
}
}
Is there any way to extend the Accepts object?
Thank you!
Nope.
Objects are single values. If they could be extended, they would not be singletons (*). The class generated to represent them is final, so even if you knew its name (not hard to find out), you could not extend it.
(*) Objects are only truly singletons when defined at global scope or nested strictly within other objects leading back to a global one.
No, but you could make Accepts a trait which you can extend.