简体   繁体   English

scala coding-style:根据可选值初始化val Seq

[英]scala coding-style: initialize a val Seq depending on optional values

I'm developing a simple function that should build a sql condition based on optional parameters that might not be present. 我正在开发一个简单的函数,它应该根据可能不存在的可选参数构建一个sql条件。

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 所以,我只是开始使用Seqs,如果价值不存在我将它与Nil合并

Working with a var I get something like: 使用var我得到类似的东西:

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) 我发现它更具可读性(我想知道第二种方法是否因为var而不是线程安全的)

I wanted to know what would be a scala idiomatic and elegant way to solve such a thing 我想知道什么是scala惯用和优雅的方式来解决这样的事情

-- 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. 这样的构造非常安全,因为在块外部无法访问var You could also use a val with a mutable builder, for instance a ListBuffer . 您还可以使用带有可变构建器的val,例如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. 此模式显示在Scala API中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM