2010-10-18 109 views
2

我的第一个Scala程序和我卡住了。scala覆盖无

所以基本上我试图在过去的声明中覆盖“last”潜在的None值。

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

你的意思是取出行'if(last == None)return;'?正如所写的,当初始化“过去”时,“last”永远不会是“None”。也就是说,编写该初始化程序的惯用方法是'val past = last getOrElse 01'。 – 2010-10-18 22:03:06

+0

嗯,有这个编译器错误,我想也许它不够聪明,推断该逻辑阻止它为空。 – smartnut007 2010-10-18 22:08:56

+1

如果适用,你应该总是在你的问题中包含任何错误信息(在这种情况下它透明地是) – 2010-10-19 09:27:49

回答

7

你应该尝试和提炼的问题多一点,但肯定包括你实际的错误!

但是,没有三元操作符(? :)Scala中因此,你可以使用:

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

这是因为(几乎 - 见下文凯文的评论)Scala中的一切都是表达式与返回类型。在Java中,有些事情是语句(没有类型),这是不正确的。使用scala,最好使用组合,而不是分叉(例如,在您的示例中为if (expr) return;)。在您的例子三元操作无关反正

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

注意,因为last不能没有在这一点上(你刚才回来,如果它是):所以我会重新写为。我的建议是使用明确的类型一段时间,因为你习惯了Scala。因此,上述将被:

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

(这似乎在你的评论,你可能会尝试将Long值赋给last,这将是当然的错误,因为lastOption[Long]型的,不Long

+0

谢谢。假设这也能起作用Console.println(“Hi:”+(cur - last.getOrElse(0L)) – smartnut007 2010-10-18 22:34:50

+2

我也犯了这个错误,并非所有Scala中的表达式,变量,类和方法定义都是语句,当编译器遇到一个以语句结尾的代码块时,如果你试图评估该块,它会在末尾插入表达式'()' - 因此给出*外观*这一切都是表达式 – 2010-10-19 00:30:51

+1

你错了关于转让;。它的类型是Unit'的'的表达,但问题依然存在,我会一直更清晰 – 2010-10-19 07:13:19

4

你有一对夫妇的“代码味道”,在那里,这表明,一个更好的,更亮泽的设计可能是指日可待:

  • 您正在使用可变变量var而不是val
  • timeit仅由副作用工作,它修改了函数外部的状态,并且使用相同输入的连续调用可能会有不同的结果。
  • seq作为一个变量名称略有风险,它离标准库中的(非常常见的&流行)Seq类型太接近。

因此,回到第一原则,如何在更“惯用”的风格下实现相同的结果?最初的设计开始(据我所知):

  • timeit(seq,comment)第一个电话刚指出当前时间
  • seq的println自上次通话所经过的时间相同值的后续调用

基本上,你只是想要一段代码运行需要多长时间。如果有一种方法可以将“代码块”传递给函数,那么也许,也许......也许......幸运的是,斯卡拉能做到这一点,只是用了一个用名字PARAM:

def timeit(block: => Unit) : Long = { 
    val start = System.currentTimeMillis 
    block 
    System.currentTimeMillis - start 
} 

只是检查出block参数,它看起来有点像不带参数的函数,这是由名PARAMS是怎么写的。函数System.currentTimeMillis - start的最后一个表达式用作返回值。

通过{}包装参数列表括号()而不是括号,你可以使它看起来像一个内置的控制结构,并使用它像这样:

val duration = timeit { 
    do stuff here 
    more stuff 
    do other stuff 
} 

println("setup time:" + duration + "ms") 

或者,你可以把println的行为放回使用timeit功能,但是,使生活困难,如果你以后想重新使用它定时东西,没有它打印到控制台:

def timeit(description: String)(block: => Unit) : Unit = { 
    val start = System.currentTimeMillis 
    block 
    val duration System.currentTimeMillis - start 
    println(description + " took " + duration + "ms") 
} 

这是另一招,多参数块。它允许你使用括号对于第一块,和括号为第二:你可以在这个模式中,出现不同程度的复杂性/复杂性

timeit("setup") { 
    do stuff here 
    more stuff 
    do other stuff 
} 
// will print "setup took XXXms" 

当然,还有无数其他的变种,但它应该足以让你开始...

+0

我有一个沉重的项目,想要介绍一些scala代码作为学习体验。 – smartnut007 2010-10-19 01:49:54

+0

但是,不知道如何从java调用这个。 – smartnut007 2010-10-19 01:55:48

+0

while((line = br.readLine())!= null){ \t \t \t if(line.length()<140)continue; \t \t \t \t \t addDoc(W,线); \t \t \t如果(++ N%100000 == 0) \t \t \t \t TimeUtil.timeit( “批处理”, “” + N/1000); \t \t \t \t \t \t} – smartnut007 2010-10-19 02:00:22