2012-12-02 21 views
38

Bu yüzden bu makro var makrolar:Statik dönüş tipi

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

class Foo 
class Bar extends Foo { def launchMissiles = "launching" } 

object FooExample { 
    def foo: Foo = macro foo_impl 
    def foo_impl(c: Context): c.Expr[Foo] = 
    c.Expr[Foo](c.universe.reify(new Bar).tree) 
} 

Söylediklerimin ben foo bir Foo dönmek istiyorum, ama sanki 2.10'da (aşağıdakileri yapabilirsiniz üç kez. 0-RC3): Ben de c.Expr üzerinde tür parametreleri kaldırırsanız

scala> FooExample.foo 
res0: Bar = [email protected] 

scala> res0.launchMissiles 
res1: String = launching 

aynı şey olur. Gerçekten foo numaralı telefonu arayarak Bar aldıklarını göremediğimde, ağacın kendisine bir yazı tipi eklemem gerekiyor.

Bu aslında oldukça harika - örneğin bir makroyu bir şemaya yönlendirebileceğim ve bazı sözcükleri Vocabulary sınıfının anonim bir alt sınıfını oluşturabildiğim anlamına gelir. döndürülen nesne.

Tam olarak ne yaptığımı anlamak istiyorum, bu yüzden birkaç sorum var. İlk olarak, aslında foo yönteminde dönüş türü nedir? Sadece (isteğe bağlı) belgeler için kullanılabilir mi? Açıkça (örneğin, ben bu durumda Int bunu değiştiremezsiniz) dönüş türü kısıtlar ve ben tamamen kaldırmak eğer böyle bir hata alıyorum:

scala> FooExample.foo 
<console>:8: error: type mismatch; 
found : Bar 
required: Nothing 
       FooExample.foo 
         ^

Ama olarak değiştirebilirsiniz numaralı telefonu aradığımda numaralı numaralı yazımda statik olarak yazılmıştır.

İkincisi, bu davranış bir yerlerde belirtiliyor mu? Bu oldukça basit konular dizisi gibi görünüyor, ancak net bir açıklama ya da tartışma aramadım.

+2

@ som-snytt: Ama yine de son kelimeyi almak için foo kelimesinin dönüş türünü beklemeliydim (yine de sevmediğim halde). –

+2

'FooExample.foo'daki dönüş türü notu burada çok tuhaf. Aksi halde makroların nasıl davranacağını umuyorum. – drstevens

+0

@drstevens: Anlaşmalı. –

cevap

19

Bu davranış, belirsiz ancak amaçlanmış olsa da kafa karıştırıcı görünebilir. Makro imzalarda dönüş türünün rolü üzerinde durmayı planlıyoruz, ancak şu anda esnekliğin iyi bir şey olduğunu düşünüyorum. Ayrıca, zaman zaman davranış tutarsızdır, örn. Makro, tür çıkarımının ortasında yakalandığında, asıl genişletmenin türü değil, statik imzası (örneğin, örneğinizde Foo) kullanılır. Bunun nedeni, makro çıkarımının tür çıkarımı yapılıncaya kadar kasıtlı olarak ertelenmesidir (bu nedenle makro uygulamaları, tür vars değil, türetilmiş türleri görmeye başlar). Bu bir takas ve mutlaka en iyisi değil, bu yüzden yakında yeniden ziyaret etmeyi planlıyoruz: https://issues.scala-lang.org/browse/SI-6755. Bu bölümdeki başka bir sorun, örtülü makrolarla ilgilidir. Bir örtülü makronun dönüş tipi genel ise ve istenen bir örtülü değer türünden çıkarılması gerektiğinde, kötü şeyler olur. Bu, şu anda tür etiketleri oluşturmak için makro kullanmak imkansız hale getirir: https://issues.scala-lang.org/browse/SI-5923.

+0

Bu, gerçek genişletmenin türünü örtülü aramada kullanmanın mümkün olmadığı anlamına mı geliyor? Bu arama, makronun kendisi tarafından açıkça yapılmadıkça? –

+1

Şu anda mümkün değil ve muhtemelen daha sonra mümkün olmayacaktır. Aksi halde örtülü arama, kapsamdaki tüm örtük makroları hevesle genişletmek zorunda kalacaktır. Aklında belirli bir kullanım durumunuz var mı? –

+0

Hayır, sadece işlerin nasıl yürüdüğüne dair zihinsel bir resim oluşturmaya çalışıyorum; c.inferImplicitValue çoğu durumda hile yapacak, bence. –