Simplify/DRY 在 Scala 中为 Twirl 模板添加一个 case 语句
Simplify/DRY up a case statement in Scala for Twirl Templates
所以我正在使用 play Twirl 模板(不在 play 中;独立项目)并且我有一些模板可以生成一些数据库 DDL。以下作品:
if(config.params.showDDL.isSupplied) {
print( BigSenseServer.config.options("dbms") match {
case "mysql" => txt.mysql(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
case "pgsql" => txt.pgsql(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
case "mssql" => txt.mssql$.MODULE$(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
})
System.exit(0)
}
但是我有很多重复的陈述。如果我尝试将大小写分配给变量并使用 $.MODULE$ 技巧,我会收到一条错误消息,指出我的变量不带参数:
val b = BigSenseServer.config.options("dbms") match {
case "mysql" => txt.mysql$.MODULE$
case "pgsql" => txt.pgsql$.MODULE$
case "mssql" => txt.mssql$.MODULE$
}
b("string1","string2","string3","string4","string5","string6")
和错误:
BigSense/src/main/scala/io/bigsense/server/BigSenseServer.scala:32: play.twirl.api.BaseScalaTemplate[T,F] with play.twirl.api.Template6[A,B,C,D,E,F,Result] does not take parameters
简化此 Scala 代码的最佳方法是什么?
编辑:使用以下答案组合的最终解决方案
下面的答案建议创建工厂 类,但我真的想避免这种情况,因为我已经有了 Twirl 生成的模板对象。部分应用的功能让我更好地理解了如何实现这一点。事实证明,我需要做的就是选择 apply
方法并进行 eta 扩展;如有必要,结合部分功能应用程序。以下效果很好:
if(config.params.showDDL.isSupplied) {
print((config.options("dbms") match {
case "pgsql" =>
txt.pgsql.apply _
case "mssql" =>
txt.mssql.apply _
case "mysql" =>
txt.mysql.apply(InetAddress.getLocalHost().getCanonicalHostName,
_:String, _:String, _:String,_:String, _:String)
})(
config.options("dbDatabase"),
config.options("dboUser"),
config.options("dboPass"),
config.options("dbUser"),
config.options("dbPass")
))
System.exit(0)
}
您可以尝试使用 tupled() 创建函数的元组版本。
object X {
def a(x : Int, y : Int, z : Int) = "A" + x + y + z
def b(x : Int, y : Int, z : Int) = "B" + x + y + z
def c(x : Int, y : Int, z : Int) = "C" + x + y + z
}
val selectedFunc = X.a _
selectedFunc.tupled((1, 2, 3)) //returns A123
更具体地说,您可以将参数存储在一个元组中:
val params = (BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName) //etc.
然后在你的匹配语句中:
case "mysql" => (txt.mysql _).tupled(params)
您可以尝试使用eta-expansion和部分应用函数。
给定一个带有一些方法的工厂:
class Factory {
def mysql(i: Int, s: String) = s"x: $i/$s"
def pgsql(i: Int, s: String) = s"y: $i/$s"
def mssql(i: Int, j: Int, s: String) = s"z: $i/$j/$s"
}
您可以像这样抽象方法:
val factory = new Factory()
// Arguments required by all factory methods
val i = 5
val s = "Hello"
Seq("mysql", "pgsql", "mssql").foreach {
name =>
val f = name match {
case "mysql" =>
// Eta-expand: Convert method into function
factory.mysql _
case "pgsql" =>
factory.pgsql _
case "mssql" =>
// Argument for only one factory method
val j = 10
// Eta-expand, then apply function partially
factory.mssql(_ :Int, j, _: String)
}
// Fill in common arguments into the new function
val result = f(i, s)
println(name + " -> " + result)
}
正如您在 "mssql" 案例中看到的那样,论点甚至可能不同;然而,公共参数只需要传递一次。 foreach
循环只是为了测试每个案例,正文中的代码显示了如何部分应用函数。
所以我正在使用 play Twirl 模板(不在 play 中;独立项目)并且我有一些模板可以生成一些数据库 DDL。以下作品:
if(config.params.showDDL.isSupplied) {
print( BigSenseServer.config.options("dbms") match {
case "mysql" => txt.mysql(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
case "pgsql" => txt.pgsql(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
case "mssql" => txt.mssql$.MODULE$(
BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName,
BigSenseServer.config.options("dboUser"),
BigSenseServer.config.options("dboPass"),
BigSenseServer.config.options("dbUser"),
BigSenseServer.config.options("dbPass")
)
})
System.exit(0)
}
但是我有很多重复的陈述。如果我尝试将大小写分配给变量并使用 $.MODULE$ 技巧,我会收到一条错误消息,指出我的变量不带参数:
val b = BigSenseServer.config.options("dbms") match {
case "mysql" => txt.mysql$.MODULE$
case "pgsql" => txt.pgsql$.MODULE$
case "mssql" => txt.mssql$.MODULE$
}
b("string1","string2","string3","string4","string5","string6")
和错误:
BigSense/src/main/scala/io/bigsense/server/BigSenseServer.scala:32: play.twirl.api.BaseScalaTemplate[T,F] with play.twirl.api.Template6[A,B,C,D,E,F,Result] does not take parameters
简化此 Scala 代码的最佳方法是什么?
编辑:使用以下答案组合的最终解决方案
下面的答案建议创建工厂 类,但我真的想避免这种情况,因为我已经有了 Twirl 生成的模板对象。部分应用的功能让我更好地理解了如何实现这一点。事实证明,我需要做的就是选择 apply
方法并进行 eta 扩展;如有必要,结合部分功能应用程序。以下效果很好:
if(config.params.showDDL.isSupplied) {
print((config.options("dbms") match {
case "pgsql" =>
txt.pgsql.apply _
case "mssql" =>
txt.mssql.apply _
case "mysql" =>
txt.mysql.apply(InetAddress.getLocalHost().getCanonicalHostName,
_:String, _:String, _:String,_:String, _:String)
})(
config.options("dbDatabase"),
config.options("dboUser"),
config.options("dboPass"),
config.options("dbUser"),
config.options("dbPass")
))
System.exit(0)
}
您可以尝试使用 tupled() 创建函数的元组版本。
object X {
def a(x : Int, y : Int, z : Int) = "A" + x + y + z
def b(x : Int, y : Int, z : Int) = "B" + x + y + z
def c(x : Int, y : Int, z : Int) = "C" + x + y + z
}
val selectedFunc = X.a _
selectedFunc.tupled((1, 2, 3)) //returns A123
更具体地说,您可以将参数存储在一个元组中:
val params = (BigSenseServer.config.options("dbDatabase"),
InetAddress.getLocalHost().getCanonicalHostName) //etc.
然后在你的匹配语句中:
case "mysql" => (txt.mysql _).tupled(params)
您可以尝试使用eta-expansion和部分应用函数。
给定一个带有一些方法的工厂:
class Factory {
def mysql(i: Int, s: String) = s"x: $i/$s"
def pgsql(i: Int, s: String) = s"y: $i/$s"
def mssql(i: Int, j: Int, s: String) = s"z: $i/$j/$s"
}
您可以像这样抽象方法:
val factory = new Factory()
// Arguments required by all factory methods
val i = 5
val s = "Hello"
Seq("mysql", "pgsql", "mssql").foreach {
name =>
val f = name match {
case "mysql" =>
// Eta-expand: Convert method into function
factory.mysql _
case "pgsql" =>
factory.pgsql _
case "mssql" =>
// Argument for only one factory method
val j = 10
// Eta-expand, then apply function partially
factory.mssql(_ :Int, j, _: String)
}
// Fill in common arguments into the new function
val result = f(i, s)
println(name + " -> " + result)
}
正如您在 "mssql" 案例中看到的那样,论点甚至可能不同;然而,公共参数只需要传递一次。 foreach
循环只是为了测试每个案例,正文中的代码显示了如何部分应用函数。