2014-02-25 132 views
3

我試圖讓功能柯里正常工作。我有如下:斯卡拉功能組合

def method(x: ByteArrayInputStream) 
       (y: ByteArrayOutputStream) 
       (z: GZIPOutputStream) 
       (func: (ByteArrayInputStream, GZIPOutputStream) => Unit) = { 

    ..... 
    ..... 

    } 

現在,當我稱呼它,我把它稱爲是這樣的:

method(new ByteArrayInputStream("".getBytes("UTF-8"))) 
      (new ByteArrayOutputStream()) 
      (new GZIPOutputStream(_)) 
      (myFunc(_, _)) 

我的理解是,在第三個參數即到GZIPOutputStream,當我說_,它會從第二個參數中選取值。但它抱怨說,

Type mismatch, expected: GZIPOutputstream, actual: (OutputStream) => GZIPOutputStream 

任何提示?

+3

您已經定義了一個帶四個參數列表的方法,每個參數列表都有一個參數。你還沒有創建一個咖喱'功能'。在調用這個方法時使用下劃線的地方,你實際上使用了部分應用程序('GZIPOutputStream'構造函數和'myFunc',不管是什麼)。我不確定你習慣了什麼,但是Scala並不是Haskell和curried函數,它們可以被創建,但並不常用。至少不會在經常使用ScalaZ的FP純化社區之外。 –

+0

@RandallSchulz我不認爲在這個例子中_是一個部分應用函數...它擴展爲實際:(OutputStream)=> GZIPOutputStream ...其中沒有任何參數部分適用 –

+0

@AndrewCassidy:我不能想到'myFunc'的定義,這些下劃線對於部分應用來說不會是*的。你能建議嗎? –

回答

0

我設法皮膚了一下,這裏是我到過:

val bytePayload = method(new ByteArrayInputStream(s.getBytes("UTF-8")))(new ByteArrayOutputStream())(writeBytes(_,_)) 

    def method(bin: ByteArrayInputStream) 
      (bos: ByteArrayOutputStream) 
      (func: (ByteArrayInputStream, GZIPOutputStream) => Unit): Either[String, Array[Byte]] = { 
    val gzip = new GZIPOutputStream(bos) 

    try { 
     func(bin, gzip) 
     gzip.finish 
    } catch { 
     case e: Exception => Left(e.getMessage) 
    } finally { 
     bin.close() 
     bos.close() 
     gzip.close() 
    } 
    Right(bos.toByteArray) 
    } 

雖然我還是處理異常,我對一些有充分的信心我不會把它們扔掉。

0

我不完全知道如何做到這一點...但這裏是一個解決方案,它模仿你在找什麼

def add(j: Int)(i: Option[Int] = None): Int = j + i.getOrElse(j) 
add(5)() 

添加(5)()返回10,並使用第j值

+0

也@ @ user3102968這myFunc(_,_)絕對不會工作。當您的方法需要一個函數時,應用該函數將返回單位 –

0

的問題是在

(new GZIPOutputStream(_)) 

由於您的錯誤說,你的方法要AA GZIPOutputstream,但你傳遞一個函數從OutputStreamGZIPOutputStream

開頭的下劃線有點令人困惑,但它是告訴scala你有意不傳遞參數到GZIPOutputStream的方式,以便它不會抱怨丟失的參數。換句話說,你傳遞的是函數本身,而不是函數的結果。

如何解決這個問題取決於你實際嘗試做什麼。如果您確實想要通過GZIPOutputStream,則需要用OutputStream替換_

如果你的目的是使method創建給出一個工廠函數像你路過,你想改變的聲明類型爲z的一個GZIPOutputStream。例如,

(z: (OutputStream) => GZIPOutputStream) 

,然後在方法體中,你可以這樣說:z(y)獲得GZIPOutputStream。 (或者其他一些輸出流代替y。)