scala - 在 DSL 中隐藏和限定隐式变量的创建

标签 scala scope 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
}

以下接近,但没有所有所需的属性......
// 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
}

最佳答案

你可以制作一个转换的宏

useValue("Hi") {
    // Implicit string "Hi" is only defined in this block
    External.funNeedingValue // Prints "Hi"
}

进入
{
  implicit val iString: String = "Hi"
  External.funNeedingValue
}

我认为没有宏就不可能比上一个例子做得更好。

关于scala - 在 DSL 中隐藏和限定隐式变量的创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23190917/

相关文章:

python - 以下 Python 语句的等效 Scala 是什么?

javascript - 除非全局声明,否则无法从事件处理程序内的函数更新变量

javascript - 我的脚本中的全局变量和局部变量

Scala 隐式 TypeTag 未正确传播(隐式类型为 Nothing)

Scala 隐式参数投影冲突, "Ambigious Implicit Values"错误

使用 Slick Table 的 Scala 类型推断

scala - 你能用 Scala 进行逻辑编程吗?

scala - 如何更改 PlayFramework 2.3.1 中已编译资源的目标文件夹?

mysql - 编写此日期范围范围的更好方法是什么?

scala - 省略一些隐式参数