2016-09-09 59 views
0

我正在研究一些工具,這些工具將被加載到標準repl或菊石中。有沒有辦法編寫包對象/導入,以便我不必在客戶端導入scala.concurent.duration包?這是我重複使用隱式持續時間轉換的唯一方法嗎?構成包對象的Scala

(是的,我知道的菊腳本包我的工具能爲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

是鄉親們問這種方式來「包裝的產品進口」,但它不工作的方式

另一種常見的用例是進口的語言implicits:你必須在你的包重新定義值

下在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是一般的init,但是東西用更少的接縫將是整潔。