2014-06-15 20 views
5

Aşağıdaki makro, ShapelessillTyped'un bir dize olarak sağladığınız bazı kodları tekrar yazmayı deneyen basitleştirilmiş bir sürümüdür. Başarısız olursa None döndürür ve başarısız olursaistisnası.Bu kod neden Scala 2.11'de yazıyor ve bu konuda ne yapabilirim?

import scala.language.experimental.macros 
import scala.reflect.macros.TypecheckException 
import scala.reflect.macros.whitebox.Context 

def typecheck_impl(c: Context)(code: c.Expr[String]): c.Expr[Option[String]] = { 
    import c.universe._ 

    val Expr(Literal(Constant(codeStr: String))) = code 

    try { 
    c.typecheck(c.parse(codeStr)) 
    c.Expr(q"None: Option[String]") 
    } catch { 
    case e: TypecheckException => 
     c.Expr(q"Some(${ e.toString }): Option[String]") 
    } 
} 

def typecheck(code: String): Option[String] = macro typecheck_impl 

Şimdi varsayalım Foo vaka sınıfına sahibim. Bir vaka sınıfı olduğundan, Foo bunun için otomatik olarak oluşturulan bir aspiratör var ama en de aynı şeyi yapar kendi çıkarıcı Bar tanımlayalım olacaktır:

scala> import Test._ 
import Test._ 

scala> val Foo(x, y) = Foo(1, 'a') 
x: Int = 1 
y: Char = a 

scala> val Bar(x, y) = Foo(1, 'a') 
x: Int = 1 
y: Char = a 

scala> val Foo(x, y, z) = Foo(1, 'a') 
<console>:15: error: wrong number of arguments for pattern Test.Foo(i: Int,c: Char) 
     val Foo(x, y, z) = Foo(1, 'a') 
      ^

scala> val Bar(x, y, z) = Foo(1, 'a') 
<console>:15: error: too many patterns for object Bar offering (Int, Char): expected 2, found 3 
     val Bar(x, y, z) = Foo(1, 'a') 
     ^

scala> typecheck("val Foo(x, y) = Foo(1, 'a')") 
res0: Option[String] = None 

scala> typecheck("val Bar(x, y) = Foo(1, 'a')") 
res1: Option[String] = None 

scala> typecheck("val Foo(x, y, z) = Foo(1, 'a')") 
res2: Option[String] = Some(scala.reflect.macros.TypecheckException: wrong number of arguments for pattern Test.Foo(i: Int,c: Char)) 
:

object Test { 
    case class Foo(i: Int, c: Char) 

    object Bar { 
    def unapply(foo: Foo): Option[(Int, Char)] = Some((foo.i, foo.c)) 
    } 
} 

Şimdi aşağıdaki yazabilirsiniz

Bunların hiçbiri şaşırtıcı değil - derlemeleri derleyeceğiniz şeyler, yapamayacağınız şeyler ve makromuz kabul eder. Ancak, bunu deneyin:

Ve makro sadece boğuluyor. Herhangi bir eski atılabilirliği işlemek için catch bloğunu değiştirmek aynı sonucu verir. Eşdeğer kod 2.10'da beklendiği gibi çalıştı.

Makromumun 2.11'de beklendiği gibi çalışabilmesi için bu hatayı nasıl alabilirim?

+0

İyi soru. ScalaDays'tan sonra düşünmem gerek. Bu senin işine yarar mıydı? –

+0

Elbette, Eugene - acele etmeyin, teşekkürler! Buna bir dalda Shapeless'ın “Sized” çıkarıcısı için bazı değişiklikler yaptım, ama bu hiç de acil değil (şube zaten aylık). –

+0

https://issues.scala-lang.org/browse/SI-8719 –

cevap