2014-02-25 134 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。)