了解scala中的任何函数定义如何计算特征

时间:2016-09-10 09:27:56

标签: scala function traits

我目前正在研究几个scala代码库(每个代码库由不同地理位置的不同人员维护),我觉得Scala提供了不同的方法来做同样的事情。我的第一手理解是Scala有一层相当厚的语法糖代码,所以我现在的目标是渗透到那层,看看什么是基本的构建块。

正如我在阅读一些文档后所理解的那样,scala中的每个函数定义基本上都是一个带有填充“apply”方法的特征。(类似于java中匿名body / class的接口)。将此设置为基础(如果我的基础理解本身是错误的,请纠正我),我正在使用Scala中的函数定义。

考虑一下:

  def func (s:String):Int = {
    100
  }

评估为

  new Function1[String, Int] {
    def apply(s:String):Int = {
      100
    }
  }

但是,以下评估特征定义的内容是什么(以及如何)?

 def func (body: => Boolean):Int = {
    body;
    100;
 }

在这种情况下,“新功能......”代码是什么样的?

3 个答案:

答案 0 :(得分:3)

如果出现混淆,请查看package.json输出。 Scala的REPL提供了方便的检查方法:

"scripts": {
    "build": "npm run lint && npm run release",
    "lint": "./node_modules/.bin/eslint ./src/**/*.js",
    "dev": "node server.js",
    "release": "NODE_ENV=production webpack --config ./webpack.dist.js --progress",
    "test": "./test/*.test.js --compilers js:babel-core/register --recursive --reporter spec"
  },

所以在这里你可以看到javap在字节码中表示为scala> def func (body: => Boolean):Int = { | body; | 100; | } func: (body: => Boolean)Int scala> :javap -c func Compiled from "<console>" public class { public static final MODULE$; public static {}; Code: 0: new #2 // class 3: invokespecial #12 // Method "<init>":()V 6: return public int func(scala.Function0<java.lang.Object>); Code: 0: aload_1 1: invokeinterface #20, 1 // InterfaceMethod scala/Function0.apply$mcZ$sp:()Z 6: pop 7: bipush 100 9: ireturn public (); Code: 0: aload_0 1: invokespecial #24 // Method java/lang/Object."<init>":()V 4: aload_0 5: putstatic #26 // Field MODULE$:L; 8: return }

我在这里使用body: => Boolean版本。 scala.Function0<java.lang.Object>将尝试尽可能多地重用java8的功能,如默认方法(在接口中)或SAM(您可以尝试scala 2.11.8标志,为Scala 2.12启用introp。这将导致另一个字节码(与java&lt; 8不兼容)和更好的性能。您可以详细了解-Xexperimental更改here

答案 1 :(得分:1)

首先

def func (s:String):Int = {
  100
}

不是一种功能,它是一种方法,它没有任何价值,并且不会自己评估任何东西。当放置在功能上下文中时,它会扩展为一个函数,但是扩展为另一个函数(Scala创建一个包装器):

new Function1[String, Int] {
  def apply(s:String):Int = {
    func(s)
  }
}

所以,如果你想进行eta-expand(Scala将术语转换为函数的术语)

def func (body: => Boolean):Int = {
  body;
  100;
}

应该是这样的:

new Function1[=> Boolean, Int] {
  def apply(body: => Boolean):Int = {
    func(body)
  }
}

和Scala将类型显示为:

(=> Boolean) => Int

但问题在于,名称类型不能用作类型参数,因此看起来没有合法的方法来使用Function1特征定义此函数。

<强>更新

看起来有一种使用lambda语法的解决方法(我不能明确地声明body的类型,但不允许使用by-name):

var expandedFunc: (=> Boolean) => Int = body => func(body)

答案 2 :(得分:0)

在Dviem的评论的帮助下,代码看起来应该是这样的:

.attr("d",function(d) {return lineFunction(d.borders);})