我想编写一组每个实现特定操作的类,因此它们接受某种类型的参数并返回相同类型或不同类型的参数。然后,给出这些操作的列表,折叠初始值,依次应用每个操作,并将结果提供给列表中的下一个操作。
例如,像这样:
val program = List[Operation](Add3, ToString, Repeat5)
program.foldLeft(5) ((progress, operation) => operation.apply(progress))
所以第一个操作加3,第二个把它变成一个字符串,最后一个重复5次。这将导致:
"88888"
如何在Scala中实现这类功能?
谢谢!
答案 0 :(得分:1)
在List
中使用不同签名的方法很难以类型安全的方式进行,但您可以采用不同的方式对其进行排列。
def add3(i: Int): Float = i + 3.1f
def num2string(f: Float): String = f"$f%.1f"
def repeat5(s: String): String = s * 5
val all = add3 _ andThen num2string andThen repeat5
all(6) // res0: String = 9.19.19.19.19.1
请注意,编译器不允许您以错误的顺序放置这些方法。这是一个很好的功能,你不会使用List
操作。
andThen
操作链可以在运行时动态构建,或多或少与构建List
相同。
从参数类型开始。 (在您的示例中,Int
。)
val ops0: Int => Int = identity _
现在您有一个Int => Int
功能,您可以根据当前条件添加或不添加操作。类型总是Int => ??
在哪里?是添加到链中的最后一个操作的返回类型。
答案 1 :(得分:1)
你可以做这样的事情。不鼓励瓦尔,但此时这是我提出的最好的
abstract class Operation
case class Add3() extends Operation with Function[Int, Int] {
def apply(x: Int) = x + 3
}
case class ToString() extends Operation with Function[Int, String] {
def apply(x: Int) = x.toString
}
case class Repeat5() extends Operation with Function[String, String] {
def apply(s: String) = s * 5
}
val lst = List[Operation](Add3(), ToString(), Repeat5())
var v = "5"
lst.foreach { op =>
{
v = op match {
case op: Add3 => op.apply(v.toInt).toString
case op: ToString => op.apply(v.toInt)
case op: Repeat5 => op.apply(v)
}
}
}
println(v)