2012-11-10 23 views
8

Stack Over Flow:Làm thế nào để xác định và gọi một hàm được áp dụng một phần với varargs?

Xin chào tất cả.

Tôi muốn xác định hàm được áp dụng một phần có các biến thể.

Để xác nhận, tôi đã chuẩn bị một số chức năng tức là Chức năng._. Các hàm ngoại trừ func có đối số varargs.

Cách xác định và gọi hàm được áp dụng một phần bằng varargs? (ví dụ gunc1 với varargs.)

java phiên bản "1.7.0_07" Scala phiên bản mã Á hậu 2.9.1.final

object Functions { 
    def func(x: Int, y: Int) = x + y 
    def gunc(x: Int*) = x.sum 
    def hunc(x: Int, y: Int*) = x + y.sum 
    def iunc(x: Int)(y: Int*) = x + y.sum // curried 
    def junk(x: String, y: Int*) = x + y.sum 
} 

object PartiallyApplied extends App { 
    import Functions._ 

    val func0 = func(1, _: Int) // I can. 
    println("result: " + func0(2)) 

    val gunc0 = gunc(1, _: Int) // I can invoke if I specify the varargs.size. But gunc0 no longer has varargs... 
    println("result: " + gunc0(2)) 

// val gunc1 = gunc(1, _: Int*) => compile error: ')' expected but identifier found. 
// val gunc1 = gunc(1, _: Seq[Int]) => compile error: type mismatch | found: Seq[Int] | required: Int 
    val gunc1 = gunc(1, _: Int) // I can invoke if I specify the varargs.size. But gunc1 no longer has varargs... 
    println("result: " + gunc1(2)) 

// val hunc0 = hunc(1)_ => compile error: _ must follow method; cannot follow Int 
// val hunc0 = hunc(1, _: Int*) => compile error: ')' expected but identifier found. 
// val hunc0 = hunc(1, _: Seq[Int]) => compile error: type mismatch | found: Seq[Int] | required: Int 
    val hunc0 = hunc(1, _: Int) // I can invoke if I specify the varargs.size. But hunc0 no longer has varargs... 
    println("result: " + hunc0(2)) 
// println("result: " + hunc0(2, 3)) => compile error: too many arguments for method apply: (v1: Int)Int in trait Function1 
// println("result: " + hunc0((2, 3): _*)) => compile error: type mismatch | found: (Int, Int) | required: Seq[Int] 
// println("result: " + hunc0(Seq(2, 3))) => compile error: type mismatch | found: Seq[Int] | required: Int 
// println("result: " + hunc0(Seq(2, 3): _*)) => compile error: no `: _*' annotation allowed here (such annotations are only allowed in arguments to *-parameters) 

    val hunc1 = hunc(1, _: Int, _: Int) // I can invoke if I specify the varargs.size. But hunc1 no longer has varargs... 
    println("result: " + hunc1(2, 3)) 

    val hunc2 = hunc(1, _: Int, _: Int, _:Int) // I can invoke if I specify the varargs.size. But hunc2 no longer has varargs... 
    val hunc3 = hunc2(2, _: Int, _: Int) 
    val hunc4 = hunc3(3, _: Int) 
    println("result: " + hunc4(4)) 

    println("result: " + hunc5(2, 3)) 

// val iunc0 = iunc(1)(_: Int*) => compile error: ')' expected but identifier found. 
// val iunc0 = iunc(1)(_: Seq[Int]) => compile error: type mismatch | found: Seq[Int] | required: Int 
    val iunc0 = iunc(1)(_: Int) 
    println("result: " + iunc0(2)) 

    val iunc1 = iunc(1)(_: Int, _: Int) 
    println("result: " + iunc1(2, 3)) 
} 

object NotPartiallyApplied extends App { 
    import Functions._ 

    println("result: " + gunc(1)) 
    println("result: " + gunc(1, 2, 3)) 
    println("result: " + gunc(Seq(1, 2, 3): _*)) 

    println("result: " + hunc(1)) 
    println("result: " + hunc(1, 2, 3)) 
    println("result: " + hunc(1, Seq(2, 3): _*)) 

    println("result: " + iunc(1)(2, 3)) 
    println("result: " + iunc(1)(Seq(2, 3): _*)) 

    println("result: " + junk("x")) 
    println("result: " + junk("x", 2, 3)) 
    println("result: " + junk("x", Seq(2, 3): _*)) 
} 

[Chỉnh sửa sau khi bình luận Rex Kerr]

Tôi muốn hàm được áp dụng một phần như guncN bên dưới:

val guncN = gunc(1, _: Int*) 
println("result: " + guncN(2)) // => 3 
println("result: " + guncN(2, 3)) // => 6 
println("result: " + guncN(2, 3, 4, 5, 100)) // => 115 

Nhưng bị cấm bởi scalac.

Tôi nghĩ rằng guncN nên được đánh giá mỗi lần, tại thời điểm (2), (2, 3) và (2, 3, 4, 5, 100) được đưa ra. Chúng ta không cần guncM dưới đây:

val guncM = guncN(2, _: Int*) 
println("result: " + guncM(3, 4)) // => 10 

Trả lời

2

Các giải pháp tôi tìm thấy là do chức năng sáng tác:

Welcome to Scala version 2.10.0-RC1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_37). 
... 
scala> 1 :: (_:Int) :: Nil : Seq[Int] 
res42: Int => Seq[Int] = <function1> 

scala> gunc _ 
res43: Seq[Int] => Int = <function1> 

scala> res42 andThen res43 
res54: Int => Int = <function1> 

scala> res54(5) 
res56: Int = 6 
+0

Cảm ơn bạn đã trả lời. Nhưng tôi không thể biên dịch bạn cpde ... Phiên bản nào là Scala? 'Scala> res0 andThen res1' ' : 11: lỗi: loại không phù hợp; ' 'tìm thấy: Int * => Int' ' yêu cầu: Seq [Int] =>' 'res0 andThen res1' –

6

Nếu bạn chỉ muốn varargs, bạn có thể trong 2,9:

Welcome to Scala version 2.9.1.final 
(Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31). 
... 
scala>  def sum(xs: Int*) = xs.sum 
sum: (xs: Int*)Int 

scala>  val summer = sum _ 
summer: Int* => Int = <function1> 

scala> summer(1,2,3) 
res0: Int = 6 

Nhưng không phải trong 2,10 như hiện tại và không có kế hoạch rõ ràng để thay đổi điều này: https://issues.scala-lang.org/browse/SI-4176

Welcome to Scala version 2.10.0-RC2 
(Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31). 
... 

scala> def sum(xs: Int*) = xs.sum 
sum: (xs: Int*)Int 

scala> val summer = sum _ 
summer: Seq[Int] => Int = <function1> 

scala> summer(1,2,3) 
<console>:10: error: too many arguments for method apply: 
(v1: Seq[Int])Int in trait Function1 
       summer(1,2,3) 

Nếu bạn có 2.9, sau đó bạn có thể

scala> def temp(early: Int*)(rest: Int*) = sum((early ++ rest): _*) 
temp: (i: Int, j: Int)(rest: Int*)Int 

scala> val presummed = temp(1,2) _ 
presummed: Int* => Int = <function1> 

scala> presummed(4,5) 
res1: Int = 12 

nhưng có lẽ bạn không nên tin tưởng vào việc có varargs chức năng vì đó dường như đã được phản đối (hoặc ít nhất là di chuyển phía sau -Yeta-expand-keeps-star cờ, mà là một -Y tùy chọn có thể không hoạt động hoặc bị xóa bất kỳ lúc nào).

+0

[Rex Kerr] Cảm ơn bạn đã trả lời.Mùa hè chức năng chỉ là tổng hợp. Gunc0 của tôi không phải là gunc. Sự khác biệt của nó là gunc0 có 1 (Int) làm đối số đầu tiên (gunc not). Hàm temp có hai Int args BEFOREHAND. Tôi muốn một chức năng một phần mà chúng ta không biết args.size TRƯỚC KHI. Trân trọng. –

+0

Trả lời không được trả lời - Tôi thừa nhận rằng SO là lạ khi không cho phép người dùng mới nhận xét về câu trả lời cho câu hỏi của riêng họ. Dù sao, tôi đã cố định nó để bạn không biết có bao nhiêu args bạn có trước. Tôi giả định rằng bạn muốn có một số biến sau đó cũng có. Nếu không, vui lòng chỉnh sửa câu hỏi của bạn để đưa ra các ví dụ rõ ràng về mã bạn có thể viết và câu trả lời sẽ là gì. –

+0

Cảm ơn bạn đã chỉ ra không rõ ràng. Tôi đã chỉnh sửa câu hỏi ban đầu. –

0

perhaps you shouldn't count on having varargs functions since that seems to have been deprecated (or at least moved behind the -Yeta-expand-keeps-star flag)

SI-6816 khẳng định việc không dùng, và trong Scala 2.12.x, tháng 12 năm 2016, với PR 5558, cờ đó là dứt khoát đi (discussion here).

I want a partial function which we don't know args.size BEFOREHAND

Đó vẫn dường như không thể (trong Scala 2.12.x, tháng 12 năm 2016)

Các vấn đề liên quan