Mat*_*att 5 scope scala implicit pass-by-name
在开发DSL时,限制隐式变量范围的最简洁方法是什么,同时隐藏这样一个隐式变量定义的事实?
举个例子,这是理想的行为......
object External
{
def funNeedingValue(implicit a : String)
{
println(a)
}
}
object Main extends App
{
useValue("Hi") {
// Implicit string "Hi" is only defined in this block
External.funNeedingValue // Prints "Hi"
}
External.funNeedingValue // Compilation error: No implicit String defined
}
Run Code Online (Sandbox Code Playgroud)
以下是关闭,但没有所有所需的属性......
// The following works, but does not hide the fact that there is an implicit
// variable defined.
object Main extends App
{
{
implicit val implicitValue = "Hi"
External.funNeedingValue // Prints "Hi"
}
External.funNeedingValue // Compilation error: No implicit String defined
}
// The following hides that there is an implicit variable defined, but breaks
// the scoping requirement and destroys thread safety.
abstract class Parent
{
implicit var implicitValue = ""
def useValue(valueToMakeImplicit : String)(f : => Unit)
{
implicitValue = valueToMakeImplicit
f()
}
}
class Child extends Parent
{
def go()
{
useValue("Hi") {
External.funNeedingValue // Prints "Hi"
}
External.funNeedingValue // Scoping issue: also prints "Hi"
}
}
object Main extends App
{
new Child().go()
}
// The following works, but is harder to read and still doesn't really
// hide the implicit value
object Main extends App
{
def useValue(valueToMakeImplicit : String)(f : String => Unit)
{
f(valueToMakeImplicit)
}
useValue("Hi") {
implicit value : String => {
External.funNeedingValue // Prints "Hi"
}
}
External.funNeedingValue // Compilation error: No implicit String defined
}
Run Code Online (Sandbox Code Playgroud)
你可以制作一个宏来转换
useValue("Hi") {
// Implicit string "Hi" is only defined in this block
External.funNeedingValue // Prints "Hi"
}
Run Code Online (Sandbox Code Playgroud)
进入
{
implicit val iString: String = "Hi"
External.funNeedingValue
}
Run Code Online (Sandbox Code Playgroud)
我认为在没有宏的情况下不可能比你的上一个例子做得更好。
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |