Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 从匿名函数引用实例成员_Scala_Scoping_Lexical Scope - Fatal编程技术网

Scala 从匿名函数引用实例成员

Scala 从匿名函数引用实例成员,scala,scoping,lexical-scope,Scala,Scoping,Lexical Scope,我试图定义一个类,它的实例有一个字符串和一个函数。在函数中使用字符串参数 class Tenant(val name: String, exclusion: Map[String, Int] => Boolean) val rule1 = new Tenant(name = "Baker3", (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != topFloor) val rule1 = new Tena

我试图定义一个类,它的实例有一个
字符串和一个函数。在函数中使用
字符串
参数

class Tenant(val name: String, exclusion: Map[String, Int] => Boolean)

val rule1 = new Tenant(name = "Baker3",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != topFloor)

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)
最后一次使用name时出现错误:
未找到:value name


我怎样才能做到这一点?

您需要进行函数或类声明:

class Tenant(name: String)(exclusion: Map[String, Int] => Boolean = _(name) != topFloor)
现在举一个例子:

scala> new Tenant("hello")()
res8: Tenant = Tenant@13c3c24f

问题:

您试图在词法上下文中引用名称
名称
,但该名称不可用:

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)
-在此上下文中,
名称
不是指在
承租人
中定义的
名称
,而是指
规则1
定义范围内的名称
,当然,该定义不存在。使用此代码,错误将消失,但这当然不是您想要的:

val name = ??? // this is the `name` that gets referenced by the lambda

val rule1 = new Tenant(name = "Cooper2",
  (suggestedFloor: Map[String, Int]) => suggestedFloor(name) != groundFloor)
解决方案:

要解决此问题,请使用方法重写,而不是在实例化时传入函数:

abstract class Tenant(val name: String) {
  def exclusion(suggestedFloor: Map[String, Int]): Boolean
}

val rule1 = new Tenant(name = "Baker3") {
  def exclusion(suggestedFloor: Map[String, Int]) =
    suggestedFloor(name) != topFloor
}
这将创建一个匿名的
Tenant
子类,其中包含
排除的“自定义”定义
;我想说,这在Scala中也被认为是惯用的风格

或者,您可以使用稍微不同的语义,而不是覆盖方法,而是覆盖包含函数的属性;当使用
\uu
结合更紧凑的lambda定义形式时,这将产生更短的语法:

abstract class Tenant(val name: String) {
  val exclusion: Map[String, Int] => Boolean
}

val rule1 = new Tenant(name = "Baker3") {
  val exclusion = (_: Map[String, Int])(name) != topFloor
}

不幸的是,类型推断器并没有消除
映射[String,Int]
重新声明的需要,原因只有比我聪明的人才能详细说明。

感谢快速响应,但每个实例都有另一个谓词。这是关于实际的函数文字。@Epicurist我不确定我是否理解您需要什么。您可以在声明或实例化站点传递任何函数。如果您想在谓词中使用name参数,那么需要对类进行curry处理declaration@Epicurist我明白了,但不行,不能那样引用参数字段。但您可以通过第一个参数列表中的上限,并在第二个列表中的默认函数中使用它。更正:使用
名称
将产生
未找到:值名称
,而不仅仅是最后一个。