2010-10-18 4 views
2

Mon premier programme Scala et je suis bloqué.scala overriding Aucun

Donc, fondamentalement, j'essaye de remplacer la valeur potentielle None de "last" à 0l dans la déclaration de passé.

import java.util.Date; 

object TimeUtil { 
    var timerM = Map("" -> new Date().getTime()); 

    def timeit(seq:String, comment:String) { 
     val last = timerM.get(seq) 
     val cur = new Date().getTime() 
     timerM += seq -> cur; 
     println(timerM) 
     if(last == None) return; 

     val past = (last == None) ? 0l : last ; 
     Console.println("Time:" + seq + comment + ":" + (cur - past)/1000 ) 
    } 

    def main(args : Array[String]) { 
     timeit("setup ", "mmm") 
     timeit("setup ", "done") 
    } 
} 
+1

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'. –

+0

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

+1

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) –

Répondre

7

Vous devriez probablement essayer de distiller le problème un peu plus, mais certainement inclure votre erreur réelle!

Cependant, il n'y a aucun opérateur ternaire (? :) à Scala donc au lieu que vous pouvez utiliser:

if (pred) a else b //instead of pred ? a : b 

En effet, (presque - voir les commentaires de Kevin ci-dessous) tout scala est un l'expression avec un type de retour. Ce n'est pas vrai en Java où certaines choses sont des instructions (sans type). Avec scala, il est toujours préférable d'utiliser la composition, plutôt que de forcer (c'est-à-dire le if (expr) return; dans votre exemple). Donc, je ré-écrire ce que:

val last = timerM.get(seq) 
val cur = System.currentTimeMillis 
timerM += (seq -> cur) 
println(timerM) 
last.foreach{l => println("Time: " + seq + comment + ":" + (l - past)/1000) } 

Notez que l'opération ternaire dans votre exemple est étranger de toute façon, parce que last ne peut être aucun à ce moment-là (vous venez de rentrer si elle était). Mon conseil est d'utiliser des types explicites pour un court moment, à mesure que vous vous habituez à Scala. Donc ce qui précède serait alors:

val last: Option[Long] = timerM.get(seq) 
val cur: Long = System.currentTimeMillis 
timerM += (seq -> cur) 
println(timerM) 
last.foreach{l : Long => println("Time: " + seq + comment + ":" + (l - past)/1000) } 

(Il semble dans votre commentaire que vous pourriez essayer d'attribuer une valeur Long à last, ce qui serait une erreur bien sûr, parce que last est de type Option[Long], non Long)

+0

merci. supposons que cela fonctionne aussi Console.println ("Hi:" + (cur - last.getOrElse (0L)) – smartnut007

+2

J'ai aussi fait cette erreur: tout dans Scala n'est pas une expression, une variable, une classe et une définition de méthode sont des instructions, comme Lorsque le compilateur rencontre un bloc de code qui se termine par une instruction, il insère l'expression '()' à la fin si vous essayez d'évaluer ce bloc - donnant ainsi l'apparence * –

+1

Vous avez tort à propos de l'assignation, c'est une expression de type 'Unit' mais le point est toujours en jeu. J'aurais dû être plus clair –

4

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 ...

+0

J'ai un projet lourd et je voulais introduire du code scala comme une expérience d'apprentissage – smartnut007

+0

Mais, je ne sais pas comment appeler cela depuis Java – smartnut007

+0

while ((line = br.readLine())! = Null) { \t \t \t si (ligne.longueur() <140) continue; \t \t \t \t \t addDoc (w, ligne); \t \t \t if (++ N% 100000 == 0) \t \t \t \t TimeUtil.timeit ("batch", "" + N/1000); \t \t \t \t \t \t} – smartnut007