Vous avez un couple de « code sent » là-dedans, ce qui suggère qu'une meilleure conception est probablement plus brillante juste autour du coin:
- Vous utilisez une variable mutable, var au lieu de val
- timeit travaille exclusivement par effets secondaires, il modifie l'état en dehors de la fonction et les appels successifs avec la même entrée peuvent avoir des résultats différents.
seq
est légèrement risqué en tant que nom de variable, il est beaucoup trop proche du type (très commun & populaire) Seq
de la bibliothèque standard.
Pour revenir aux premiers principes, comment les mêmes résultats pourraient-ils être obtenus dans un style plus "idiomatique"? A partir de la conception originale (si je comprends bien):
- le premier appel à
timeit(seq,comment)
note juste l'heure actuelle
- les appels suivants avec la même valeur de
seq
println le temps écoulé depuis l'appel précédent
Fondamentalement, vous voulez juste de temps combien de temps un bloc de code prend pour fonctionner. S'il y avait un moyen de passer un "bloc de code" à une fonction, alors peut-être, juste peut-être ...Heureusement, scala peut le faire, il suffit d'utiliser un sous-PARAM name: il semble juste vérifier que le paramètre block
,
def timeit(block: => Unit) : Long = {
val start = System.currentTimeMillis
block
System.currentTimeMillis - start
}
un peu comme une fonction sans argument, voilà comment sont écrits params par nom. La dernière expression de la fonction System.currentTimeMillis - start
est utilisée comme valeur de retour.
En encapsulant la liste des paramètres dans {} Les accolades au lieu de() entre parenthèses, vous pouvez le faire ressembler à une structure de contrôle intégrée, et l'utiliser comme ceci:
val duration = timeit {
do stuff here
more stuff
do other stuff
}
println("setup time:" + duration + "ms")
Vous pouvez pousser le comportement println retour dans la fonction timeit, mais qui rend la vie plus difficile si vous voulez plus tard de le réutiliser pour chronométrer quelque chose sans l'imprimer à la console:
def timeit(description: String)(block: => Unit) : Unit = {
val start = System.currentTimeMillis
block
val duration System.currentTimeMillis - start
println(description + " took " + duration + "ms")
}
Ceci est une autre astuce, blocs de paramètres multiples. Il vous permet d'utiliser des parenthèses pour le premier bloc et accolades pour le deuxième:
timeit("setup") {
do stuff here
more stuff
do other stuff
}
// will print "setup took XXXms"
Bien sûr, il y a un million d'autres variantes que vous pouvez faire sur ce modèle, avec des degrés de sophistication/complexité, mais il faut être suffisant pour vous aider à démarrer ...
Vouliez-vous supprimer la ligne 'if (last == None) return;'? Comme écrit, 'last' ne sera jamais' None' lors de l'initialisation de 'past'. Cela dit, la façon idiomatique d'écrire cet initialiseur serait 'val past = last getOrElse 01'. –
ah bien, il y avait cette erreur de compilateur et je pensais que ce n'est peut-être pas assez intelligent pour déduire que la logique l'empêche d'être nul. – smartnut007
Vous devez toujours inclure toutes les informations d'erreur dans votre question, le cas échéant (ce qui est de manière transparente, dans ce cas) –