scala – 用于理解和功能创建的次数
最近我接受了
Scala开发者职位的采访.我被问到这样的问题
// matrix 100x100 (content unimportant) val matrix = Seq.tabulate(100,100) { case (x,y) => x + y } // A for { row <- matrix elem <- row } print(elem) // B val func = print _ for { row <- matrix elem <- row } func(elem) 问题是:哪个实施A或B更有效? 我们都知道,为了理解可以翻译 // A matrix.foreach(row => row.foreach(elem => print(elem))) // B matrix.foreach(row => row.foreach(func)) B可以写为matrix.foreach(row => row.foreach(print _)) 假设正确的答案是B,因为A会创建功能打印100倍以上. 我已经检查了语言规范,但仍然无法理解答案.有人可以向我解释一下吗 解决方法
简而言之:
示例A在理论上更快,实际上您不应该能够测量任何差异. 长答案: 正如你已经发现的 for {xs <- xxs; x <- xs} f(x) 被翻译成 xxs.foreach(xs => xs.foreach(x => f(x))) 这在§6.19SLS中解释:
现在当一个人写一个函数文字时,每次都需要调用一个新的实例(§6.23SLS).这意味着 xs.foreach(x => f(x)) 相当于 xs.foreach(new scala.Function1 { def apply(x: T) = f(x)}) 介绍本地功能类型时 val g = f _; xxs.foreach(xs => xs.foreach(x => g(x))) 您不会引入优化,因为您仍然将函数文字传递给foreach.实际上代码较慢,因为内部的foreach被翻译成了 xs.foreach(new scala.Function1 { def apply(x: T) = g.apply(x) }) 其中g的应用方法的附加调用发生.虽然,你可以优化你写的时候 val g = f _; xxs.foreach(xs => xs.foreach(g)) 因为内在的foreach现在被翻译成 xs.foreach(g()) 这意味着函数g本身被传递给foreach. 这意味着B在理论上更快,因为每次执行理解的主体都不需要创建匿名函数.然而,上面提到的优化(函数直接传递给foreach)并不适用于理解,因为由于规范说转换包括函数文字的创建,因此总是创建不必要的函数对象(这里我必须说编译器也可以优化,但不是因为优化的理解是困难的,并且在2.11中仍然没有发生.总而言之,这意味着A更有效率,但如果没有理解(但没有为最内层函数创建函数文字),则B将更有效. 然而,所有这些规则只能在理论上应用,因为在实践中,存在scalac的后端和JVM本身都可以进行优化 – 更不用说由CPU完成的优化.此外,您的示例包含一个在每次迭代执行的系统调用 – 它可能是这里最昂贵的操作,胜过其他一切. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |