【问题标题】:Scala composing package objectsScala 组合包对象
【发布时间】:2017-01-17 19:07:16
【问题描述】:

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

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

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

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)
  }
}

【问题讨论】:

    标签: scala


    【解决方案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 用于一般初始化,但接缝较少的东西会很整洁。

    【讨论】:

      猜你喜欢
      • 2017-01-10
      • 2019-07-23
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 2012-05-18
      • 1970-01-01
      相关资源
      最近更新 更多