8

スタックオーバーフロー:

こんにちは、みんな。

varargs を持つ部分的に適用された関数を定義したいと思います。

確認するために、いくつかの関数、つまりFunctions._を用意しました。func 以外の関数には varargs 引数があります。

可変引数を使用して部分的に適用された関数を定義して呼び出す方法は? (たとえば、可変引数を指定した gunc1。)

Java バージョン "1.7.0_07" Scala コード ランナー バージョン 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): _*))
}

[レックス・カーのコメント後に編集]

以下の guncN のような部分的に適用された関数が必要です。

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

しかし、それは scalac によって禁止されています。

guncN は (2)、(2, 3)、(2, 3, 4, 5, 100) が与えられるたびに評価されるべきだと思います。以下の guncM は必要ありません。

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

3 に答える 3

6

可変引数だけが必要な場合は、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

しかし、現状では 2.10 ではなく、これを変更する明確な計画はありません: 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)

あなたが2.9を持っているなら、あなたはすることができます

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

しかし、おそらく、varargs 関数は非推奨になっているように見えるため (または、少なくともオプションとして機能しないか、いつでも削除される可能性が-Yeta-expand-keeps-starあるフラグの背後に移動したか)、varargs 関数を期待するべきではありません。-Y

于 2012-11-10T15:15:04.523 に答える
2

私が見つけた解決策は、関数を作成することです:

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
于 2012-11-10T15:06:03.060 に答える
0

おそらく、varargs 関数は廃止された (または少なくとも-Yeta-expand-keeps-starフラグの後ろに移動された)ように見えるため、varargs 関数を期待するべきではありません。

SI-6816は非推奨を確認し、2016 年 12 月の Scala 2.12.x ではPR 5558で、そのフラグは完全になくなりました (ここでの議論)。

args.sizeBEFOREHANDを知らない部分関数が欲しい

それはまだ可能ではないようです (Scala 2.12.x、2016 年 12 月)。

于 2016-12-26T07:39:18.053 に答える