Scala组成包对象

时间:2016-09-09 15:17:52

标签: scala

我正在研究一些工具,这些工具将被加载到标准repl或ammonite中。有没有办法组合包对象/导入,以便我不必在我的客户端导入scala.concurent.duration包?这是我重用隐式持续时间转换的唯一方法吗?

(是的,我知道包装我的工具的菊石脚本可以加载REPL的所有内容,但是菊石可能不是我使用包裹的唯一方式)

这不是一种可扩展的方法:(

package object tool package {
  // redeclaring the implicit value class conversions found in package object scala.concurrent.duration
  implicit final class DurationInt(private val n: Int) extends AnyVal with DurationConversions {
    override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n.toLong, unit)
  }

  implicit final class DurationLong(private val n: Long) extends AnyVal with DurationConversions {
    override protected def durationIn(unit: TimeUnit): FiniteDuration = Duration(n, unit)
  }
}

1 个答案:

答案 0 :(得分:1)

是。人们要求"包装进口"以这种方式,但它不会那样工作。

另一个常见用例是导入语言含义:您必须重新定义包中的值。

以下在REPL中不起作用,但将其作为未来的提醒:

scala> :pa -raw
// Entering paste mode (ctrl-D to finish)

// attempt to add an import into the block
package object w {
  def wrap[A](a: A): A = macro www[A]
  import reflect.macros.blackbox.Context
  def www[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = {
    import c.universe._
    val Block(ss, res) = a.tree
    Block(q"import scala.concurrent.duration._" +: ss, res)
  }
}

// Exiting paste mode, now interpreting.


scala> $intp.setExecutionWrapper("w.wrap")

它不起作用,因为包装器包装了错误的代码......

scala> 5.seconds
<console>:12: error: value seconds is not a member of Int
       5.seconds
         ^

scala> :se -Xprint:typer

scala> 42
[[syntax trees at end of                     typer]] // <console>
package $line7 {
  object $read extends scala.AnyRef {
    def <init>(): $line7.$read.type = {
      $read.super.<init>();
      ()
    };
    object $iw extends scala.AnyRef {
      def <init>(): type = {
        $iw.super.<init>();
        ()
      };
      object $iw extends scala.AnyRef {
        def <init>(): type = {
          $iw.super.<init>();
          ()
        };
        private[this] val res4: Int = 42;
        <stable> <accessor> def res4: Int = $iw.this.res4
      }
    }
  }
}

[[syntax trees at end of                     typer]] // <console>
package $line7 {
  object $eval extends scala.AnyRef {
    def <init>(): $line7.$eval.type = {
      $eval.super.<init>();
      ()
    };
    lazy private[this] var $result: Int = _;
    <stable> <accessor> lazy def $result: Int = {
      $eval.this.$result = $line7.$read.$iw.$iw.res4;
      $eval.this.$result
    };
    lazy private[this] var $print: String = _;
    <stable> <accessor> lazy def $print: String = {
      $eval.this.$print = ({
        import scala.concurrent.duration._;
        $line7.$read.$iw.$iw;
        "res4: Int = ".+(scala.runtime.ScalaRunTime.replStringOf($line7.$read.$iw.$iw.res4, 1000))
      }: String);
      $eval.this.$print
    }
  }
}

res4: Int = 42

...无论如何,代码必须在扩展之前和之后编译。

模板不允许添加尾随括号:

scala> $intp.setExecutionWrapper("{ import scala.concurrent.duration._ ")

它必须看起来像

scala> $intp.setExecutionWrapper("{ import scala.concurrent.duration._ %s }")

正如您所指出的那样,scala -i my-imports.sc用于一般初始化,但接缝较少的东西将是整洁的。