2010-01-18 9 views
3

En dépit du prochain framework fork/join de java 7, je construis une méthode d'aide qui est légère dans la syntaxe pour que le client exécute du code en parallèle. Voici une méthode principale exécutable pour illustrer l'idée.Une syntaxe de jointure de fourche Scala légère

import actors.Futures 

object ForkTest2 { 



    def main(args: Array[String]) { 
    test1 
    test2 
    } 



    def test1 { 
    val (a, b, c) =fork({ 
     Thread.sleep(500) 
     println("inside fx1 ",+System.currentTimeMillis) 
     true 
    }, { 
     Thread.sleep(1000) 
     println("inside fx2 ",+System.currentTimeMillis) 
     "stringResult" 
    }, { 
     Thread.sleep(1500) 
     println("inside fx3 ",+System.currentTimeMillis) 
     1 
    }) 

    println(b, a, c) 
    true 
    } 

    def test2 { 
    val results = forkAll({ 
    () => 
       Thread.sleep(500) 
       println("inside fx1 ",+System.currentTimeMillis) 
       true 
    }, { 
    () => 
       Thread.sleep(1000) 
       println("inside fx2 ",+System.currentTimeMillis) 
       "stringResult" 
    }, { 
    () => 
       Thread.sleep(1500) 
       println("inside fx3 ",+System.currentTimeMillis) 
       1 
    }, { 
    () => 
       Thread.sleep(2000) 
       println("inside fx4 ",+System.currentTimeMillis) 
       1.023 
    }) 

    println(results) 
    true 
    } 

    val tenMinutes = 1000 * 60 * 10 

    def fork[A, B, C](
      fx1: => A, 
      fx2: => B, 
      fx3: => C 
     ) = { 
    val re1 = Futures.future(fx1) 
    val re2 = Futures.future(fx2) 
    val re3 = Futures.future(fx3) 
    //default wait 10 minutes 
    val result = Futures.awaitAll(tenMinutes, re1, re2, re3) 
    (
      result(0).asInstanceOf[Option[A]], 
      result(1).asInstanceOf[Option[B]], 
      result(2).asInstanceOf[Option[C]] 

      ) 
    } 

    type fxAny =() => Any 

    def forkAll(
      fx1: fxAny* 
     ): List[Any] = { 
    val results = fx1.toList.map {fx: fxAny => Futures.future(fx())} 
    Futures.awaitAll(tenMinutes, results: _*) 
    } 
} 

un échantillon eteint est

(inside fx1 ,1263804802301) 
(inside fx2 ,1263804802801) 
(inside fx3 ,1263804803301) 
(Some(stringResult),Some(true),Some(1)) 
(inside fx1 ,1263804803818) 
(inside fx2 ,1263804804318) 
(inside fx3 ,1263804804818) 
(inside fx4 ,1263804805318) 
List(Some(true), Some(stringResult), Some(1), Some(1.023)) 

test 1 illustrent un type sûr type de retour

test 2 illustrent un argument d'entrée arbitraire

j'espère combiner la méthode à deux test Ainsi, le code client peut exécuter une fonction arbitraire en parallèle avec le type de retour sécurisé.

Un autre point sur les arguments de la fonction arbitraire est:

Je pense que la ligne

type fxAny =() => Any 

devrait vraiment être code comme

type fxAny = => Any 

, mais le compilateur scala ne me permettent pas de fais-le.

Toute aide est appréciée.

Répondre

4

Eric Torreborre a écrit dans le lien fourni par @retronym:

trait LazyParameters { 
    /** transform a value to a zero-arg function returning that value */ 
    implicit def toLazyParameter[T](value: =>T) = new LazyParameter(() => value) 
    /** class holding a value to be evaluated lazily */ 
    class LazyParameter[T](value:()=>T) { 
    lazy val v = value() 
    def apply() = v 
    } 
} 

Voici sa version LazyParameter de votre test:

object ForkTest2 extends LazyParameters { 

...

def forkAll(fx1: LazyParameter[Any]*): List[Any] = { 
    val results = fx1.toList.map { 
    fx: LazyParameter[Any] => Futures.future(fx.apply())} 
    Futures.awaitAll(tenMinutes, results: _*) 
} 

Modifier: Comme vous l'avez remarqué, implicite Evalue le paramètre par nom et elle ne porte pas avant le délai d'évaluation. Pourquoi ne pas simplement utiliser le mot future? Personnellement, je pense que cela rend le code plus lisible.

import actors.Futures 
import actors.Futures.future 
import actors.Future 

...

def test2 { 
    val results = forkAll(
    future { 
     Thread.sleep(500) 
     println("inside fx1 ",+System.currentTimeMillis) 
     true 
    }, 
    future { 
     Thread.sleep(1000) 
     println("inside fx2 ",+System.currentTimeMillis) 
     "stringResult" 
    }, 
    future { 
     Thread.sleep(1500) 
     println("inside fx3 ",+System.currentTimeMillis) 
     1 
    }, 
    future { 
     Thread.sleep(2000) 
     println("inside fx4 ",+System.currentTimeMillis) 
     1.023 
    }) 

    println(results) 
    true 
} 

...

def forkAll(futures: Future[Any]*): List[Any] = { 
    println("forkAll") 
    Futures.awaitAll(tenMinutes, futures: _*) 
} 
+0

Vous pouvez définir ce encore plus court: implicite def anyToFun0 [T] (t: => T): (() => T) =() => t (http://stackoverflow.com/questions/1826145/how-to-write-a-lazy-variable-argument-version-of-orelse/1826794#1826794). Le problème est que vous ne serez pas en sécurité. Vous devez définir une fonction ou une valeur paresseuse. Un bloc sera évalué. –

+0

la fonction implicite ferait que le fx soit évalué et invoqué. Le client doit explicitement appeler la conversion de type pour éviter une évaluation précoce – laiBilly

0

Un exemple d'implémentation pour toute personne intéressée,

Pour le cas d'utilisation qui avec quelques arguments de la fonction, peut être simplement définir la liste de la fonction fourche avec nombre différent d'arguments (suivant l'idée dans la définition de tuple) et profiter de type sÛR type de retour

object ForkTest4 extends LazyParameters { 
    def main(args: Array[String]) { 
    test4 
    } 

    def test4 { 
    println("Begin test 4") 
    //Without the explicit call to type conversion would cause early evaluation 
    // val result4 = forkAll({ 
    val result4 = forkAll(l { 
     Thread.sleep(500) 
     println("inside fx4 ", +System.currentTimeMillis) 
     true 
    }) 
    println(result4) 
    true 
    } 

    val tenMinutes = 1000 * 60 * 10 

    def forkAll(fx1: (() => Any)*): List[Any] = { 

    val results = fx1.toList.map { 

     fx: (() => Any) => { 

     val result = Futures.future(fx.apply()) 

     result 
     } 
    } 
    Futures.awaitAll(tenMinutes, results: _*) 
    } 

    def l[T](t: => T): (() => T) =() => t 

    implicit def implicitLazy[T](t: => T): (() => T) =() => t 
} 
Questions connexes