Scala 隐式参数";“链接”;用于DSL
我有一个想法(模糊的),以这种方式传递(或链接)一些隐式值,而不是将参数引入blockScala 隐式参数";“链接”;用于DSL,scala,dsl,Scala,Dsl,我有一个想法(模糊的),以这种方式传递(或链接)一些隐式值,而不是将参数引入blockf: def block(x: Int)(f: => Unit)(implicit v: Int) = { implicit val nv = v + x f } def fun(implicit v: Int) = println(v) 如果我使用了类似的东西: implicit val ii: Int = 0 block(1) { block(2) { fun } } 它
f
:
def block(x: Int)(f: => Unit)(implicit v: Int) = {
implicit val nv = v + x
f
}
def fun(implicit v: Int) = println(v)
如果我使用了类似的东西:
implicit val ii: Int = 0
block(1) {
block(2) {
fun
}
}
它将打印3
如果我可以说def block(x:Int)(f:implicit Int=>Unit)
换句话说,我正在寻找一些设计模式,它允许我实现这个DSL:访问嵌套块中的一些累积值,但不显式地将其作为参数传递。可能吗?(implicit
s不是必需的,只是一个强调我不想显式传递累加器的提示)。当然,上面的代码将打印0
编辑:可能的用法之一:以以下方式组合http路由
prefix("path") {
prefix("subpath") {
post("action1") { (req, res) => do action }
get("action2") { (req, res) => do action }
}
}
这里
post
和get
将访问(如何?)累积的前缀,比如List(“path”、“subpath”)
或“/path/subpath/”
通过implicit
传递状态是脏的,将导致意外的、难以追踪的错误。您要做的是构建一个函数,该函数的组合方式可以使嵌套调用在某个操作上累积,而其他任何操作都使用该值来执行该函数
case class StateAccum[S](init: S){
val op: S => S
def flatMap[A <: S](f: S => StateAccum[A]) ={
val StateAccum(out) = f(s)
StateAccum(op(init, out))
}
def apply(f: S => A) = f(init)
}
考虑为此使用。它使用起来非常简单,而且线程安全:
val acc: DynamicVariable[Int] = new DynamicVariable(0)
def block(x: Int)(f: => Unit) = {
acc.withValue(acc.value + x)(f)
}
def fun = println(acc.value)
嗯,这在其他情况下可能有一些实际用途,但在我的情况下,我想要一个DSL,它允许嵌套
f
,并在那里使用一些值,比如block(1){使用累积值的某物;block(2){使用累积值的某物;}
<用于的代码>不适用于此。请解释如何使用映射器
?还是进不去it@dmitry没关系,我的for comp版本不会满足你的要求。但是,对它的编辑将被删除。它确实涉及“魔法”。@dmitry我正在将其纳入类型级别的“魔法”。它通过隐式优先级工作。您将“apply”更改为具有隐式值,并基于函数的返回类型,它将按照您想要的方式“工作”。即使在这种情况下,我也不希望每个块f
都需要处理累加器。我只是希望它能以某种方式被访问。比如它是隐式的或者某个属性,f
可以访问,但只有在需要时才可以访问。不是显式参数。这正是我需要的,谢谢!从未听说过:)
val acc: DynamicVariable[Int] = new DynamicVariable(0)
def block(x: Int)(f: => Unit) = {
acc.withValue(acc.value + x)(f)
}
def fun = println(acc.value)