I'm developing a simple function that should build a sql condition based on optional parameters that might not be present.
I'm trying to accomplish it using immutables values, and in and elegant and idiomatic way.
So far now I came with something like this:
val cond: Seq[String] = Nil ++
(if (entity != "*") Seq("entity = {entity}") else Nil) ++
(if (name != "*") Seq("name = {name}") else Nil) ++
val condition =
if (cond.size == 0) ""
else " where " + cond.mkString(" and ") + " "
So, I'm just mergins Seqs, if the value is not present I'm merging it with Nil
Working with a var I get something like:
var cond: Seq[String] = Seq();
if (entity != "*") cond = cond :+ "entity = {entity}"
if (name != "*") cond = cond :+ "name = {name}"
Which I find it to be more readable (I wonder if this second approach is not threadsafe because of the var)
I wanted to know what would be a scala idiomatic and elegant way to solve such a thing
-- edit
in the end, I settled down with this implementation:
val condition: String = {
var cond: Seq[String] = Seq();
if (entity != "")
cond = cond :+ "entity = {entity}"
if (filter != "")
cond = cond :+ """(name like {filter} or prev like {filter} or post like {filter})"""
if (cond.size == 0) ""
else " where " + cond.mkString(" and ") + " "
}
Don't repeat yourself:
def seqIf(r: String, s: String) = if (r != "*") Seq("%s = {%s}".format(s,s)) else Nil
val cond = seqIf(entity, "entity") ++ seqIf(name, "name")
Not only strings:
def seqIf[A](p: Boolean, a: A) = if (p) Seq(a) else Nil
val cond = seqIf(entity != "*", "entity = {entity}") ++
seqIf(name != "*", "name = {name}")
Another approach is to keep the mutable construction, but hidden in a block to avoid side effects:
val cond = {
var cs = Seq[String]()
if (entity != "*") cs = cs :+ "entity = {entity}"
if (name != "*") cs = cs :+ "name = {name}"
cs
}
Such construct is perfectly safe because the var
is not accessible outside the block. You could also use a val with a mutable builder, for instance a ListBuffer
. In that case. Just be sure you don't leak a mutable object out of the block:
import scala.collection.mutable.ListBuffer
val cond = {
val cs = ListBuffer[String]()
if (entity != "*") cs += "entity = {entity}"
if (name != "*") cs += "name = {name}"
cs.result() //Converts the ListBuffer into an immutable List
}
This is perfectly acceptable because the block itself is still "pure". This pattern appears in the Scala API.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.