【问题标题】:Hiding and scoping implicit variable creation in a DSL在 DSL 中隐藏和限定隐式变量创建
【发布时间】:2014-04-21 04:42:39
【问题描述】:

在开发 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
}

【问题讨论】:

    标签: scala scope implicit pass-by-name


    【解决方案1】:

    你可以制作一个宏来转换

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

    进入

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

    我认为没有宏的情况下不可能比上一个示例做得更好。

    【讨论】:

      猜你喜欢
      • 2012-11-09
      • 2012-11-05
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      相关资源
      最近更新 更多