2012-11-10 11 views
8

Stack over Flow:Come definire e richiamare una funzione parzialmente applicata con varargs?

Ciao a tutti.

Vorrei definire una funzione parzialmente applicata con vararg.

Per confermare, ho preparato diverse funzioni, ad esempio Funzioni._. Le funzioni tranne func hanno un argomento varargs.

Come definire e richiamare una funzione parzialmente applicata con varargs? (ad esempio gunc1 con varargs.)

versione java "1.7.0_07" Scala versione del codice corridore 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): _*)) 
} 

[Edit dopo il commento di Rex Kerr]

Voglio che il parzialmente funzione applicata come guncN seguito:

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 

Ma è vietato da scalac.

Penso che guncN dovrebbe essere valutato ogni volta, al momento (2), (2, 3) e (2, 3, 4, 5, 100) sono dati. Non abbiamo bisogno di guncM di seguito:

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

risposta

2

La soluzione che ho trovato è di funzioni che compongono:

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

Grazie per la risposta. Ma non posso compilare cpde ... Quale versione è Scala? 'Scala> res0 andthen res1' ' : 11: errore: tipo non corrispondente; '' trovato:? Int * => Int' 'richiesto: Seq [Int] =>' ' res0 andthen res1' –

6

Se si desidera solo varargs, è possibile in 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 

Ma non in 2.10 come ora, e non c'è alcun piano apparente per cambiare questo: 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) 

Se si dispone di 2.9, allora si può

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 

ma forse non si dovrebbe contare su funzioni varargs dal momento che sembra essere stato deprecato (o almeno si mosse dietro la bandiera -Yeta-expand-keeps-star, che come L'opzione -Y potrebbe non funzionare o essere rimossa in qualsiasi momento).

+0

[Rex Kerr] Grazie per la risposta.La funzione estate è solo somma. Il mio gunc0 non è gunc. La sua differenza è che gunc0 ha 1 (Int) come primo argomento (gunc not). La funzione temp ha due int Argomento PRIMA. Voglio una funzione parziale che non conosciamo args.size BEFOREHAND. Saluti. –

+0

Le risposte non dovrebbero andare nelle risposte - Ammetto che SO è strano nel non permettere ai nuovi utenti di commentare le risposte alle loro stesse domande. Ad ogni modo, l'ho risolto in modo da non sapere quanti argomenti hai in anticipo. Suppongo che tu voglia avere anche un numero variabile in seguito. In caso contrario, modifica la domanda per fornire esempi chiari di codice che dovresti essere in grado di scrivere e quali dovrebbero essere le risposte. –

+0

Grazie per la segnalazione ambigua. Ho modificato la domanda iniziale. –

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 conferma deprecazione, e in Scala 2.12.x, dicembre 2016, con PR 5558, quella bandiera è definitivamente andato (discussion here).

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

che ancora non sembra possibile (in Scala 2.12.x, dicembre 2016)

Problemi correlati