2013-04-03 83 views
2

我有一個複雜的返回類型的方法,我想有一個函數,該方法的結果作爲參數。是否有可能爲該方法的返回類型創建一個別名?類似於C++的typeof推斷類型的別名

例如,

object Obj { 
    def method(x:Int) = 1 to x 
    type ReturnType = ??? 

    //possible solution if i know a parameter for which the method won't fail 
    val x = method(1) 
    type ReturnType = x.type 

    //another possible solution, I don't need a parameter that won't fail 
    //the method but i still think there is a better way 
    lazy val x = method(1) 
    type ReturnType = x.type 

    //I would then like to have a function which takes ReturnType as a parameter 
    def doit(t:ReturnType) = Unit 
} 

事情是編譯器知道類型,但我不知道如何從他那裏得到它。

+0

據我所知,它被稱爲* dependent types *。 – 2013-04-03 19:31:27

+0

如果您使用的是IntelliJ Scala插件,您可以使用'Alt' +'='檢查任何表達式或方法的類型。在Scala REPL中,您可以使用':type'命令獲取任何表達式的類型。 – ghik 2013-04-03 19:45:05

+1

@ghik是的,我知道我可以在IDE或REPL中找到該類型,但在我的情況下,完整類型超過80個字符長,並且在源代碼中使用它將無助於可讀性。也有可能返回類型將在未來發生變化。 – 2013-04-03 20:18:26

回答

2

我能想到的唯一的辦法是這樣的:

class Return[T](f:() => T) { 
    type Type = T 
} 

def getDifficultReturnType() = 1 to 10 

val Return = new Return(getDifficultReturnType) 

def doIt(t:Return.Type) = { 

} 

我不知道如果這是你在找什麼。

+0

這的確比我的解決方案更容易理解。謝謝。我很好奇的是爲什麼FunctionN特徵沒有那種類型的別名? (我知道我可以創建一個隱式轉換,但是返回類型不應該關注我的原因有什麼特別的原因嗎?) – 2013-04-03 22:35:14

+0

在大多數情況下,這不是你想要的。我會用'trait'或'structural type'鍵入'doIt'方法,其中包含我將在該方法中使用的功能。如果我想保留原始類型,我會添加一個像這樣的類型參數:'def doIt [T <:TraitOrStructuralType](t:T)'。一個應用程序包含很多功能,如果在所有應用程序中添加一個類型別名,那麼這個功能就有點兒麻煩了。 – EECOLOR 2013-04-03 22:40:08

+0

我認爲結構類型,但期望的行爲也不是很簡單(在我的情況ReturnType是一個光滑的查詢結果的類型做一個多表連接)在任何情況下,謝謝你,這確實是一個更好的做我想做的事。儘管我會嘗試去思考它是否真的有必要。 – 2013-04-03 23:36:38

0

據我所知,這是不可能的。也許在未來的Scala版本中有type macros

在任何情況下,如果它是非平凡的話,離開類型不是一個好的設計在我看來。我知道你不想輸入80個字符,但是如果保留這種類型至關重要(如聽起來那樣),它應該在的某些點解釋。

您可以使用類型別名

object Obj { 
    type ReturnType = My with Very[LongAndComplicated] with Name 
    // explicit type ensures you really get what you want: 
    def method(x: Int): ReturnType = 1 to x 

    def doit(t: ReturnType) {} 
} 
+0

好吧,它是可能的(通過方法參數的惰性val和空值)。它只是不好。編寫整個類型的東西是,我認爲它不會幫助任何人看到它寫出來(方法的主體是一個相當複雜的光滑查詢,導致我不明白的類型 - 我是考慮使用結構類型來定義我需要的結果類型,但似乎很多工作沒有特別的好處)。無論如何感謝輸入,如果確實是不可能的,我會寫出類型。 – 2013-04-03 22:25:27

+0

@MartinKolinek我認爲你錯了。你正在做的是使用從屬類型'x.type'作爲從method_生成的_some值。這不是該方法的一般返回類型。只要嘗試用從'method'獲得的另一個值調用'doit',就會發現這是不可能的。 – 2013-04-04 16:07:42

+0

最初,我也這麼想,但給了方法'def方法(x:Int):List [Int] =拋出新的Exception()'惰性val方法起作用。換句話說,懶惰的val不會被'x.type'代碼評估。 – 2013-04-04 23:36:06