我可以实现 defval 在哪里 def 没有任何论点:

trait T { def foo: Int }
class C(val foo: Int) extends T

为什么不能将其扩展到实施 def 将n args带到一个瓦尔 FunctionN?我希望可以实施类似的事情:

def expensiveOperation(p: Int => Boolean) : List[Int]

具有懒惰的功能 val. 。就像是:

val expensiveOperation = {
    val l = //get expensive list
    l.filter _ //partially applied function
}

我知道该语法似乎对2.8不起作用。有我缺少的东西吗,为什么我不能 实施 一个 def 将参数作为功能 val?

有帮助吗?

解决方案

现在,邮政编辑,我想我明白您的追求。但是您无法做自己想做的事,因为类型签名不匹配。

def x: Int = 5
val x: Int = 5

在这两种情况下,您什么也没提供并恢复INT(在这种情况下为5)。伟大的!

def expensive(p: Int => Boolean): List[Int]

现在您提供一些东西。但是val只是一个地方存储的对象。你可以提供一些东西 标签指的对象, ,但这与为标签'x'提供的东西不同。

如果您希望Val覆盖它,则需要使用以下设置:

def expensive: (Int=>Boolean)=>List[Int]

现在,您有没有参数的东西,它返回可以采用int => boolean函数的东西,并为您提供列表[int]回报。这正是您使用阀门所获得的 - 在两种情况下,您都有返回具有所需功能的对象的东西的名称。

(在Scala中,实际上将Vals实现为隐藏的字段,该字段没有采用任何参数并返回隐藏字段中的任何内容。因此,它确实是一种像DEF一样的方法。)

其他提示

一个 val 不进行参数,因为它是计算并存储在字段中的。但是我可能只会您参考我在邮件列表中最后两天所做的大量帖子。

或者,从Java的角度来考虑它,因为Scala与JVM级别兼容Java,并且肯定必须遵守JVM规则。让我们从第一堂课开始:

abstract class X {
  def expensiveOperation(p: Int => Boolean) : List[Int] 
}

现在,让我们扩展它:

abstract class Y extends X {
  override val expensiveOperation: ((Int) => Boolean) => List[Int]
}

因此,来自Java,我们知道该课 X 有方法 expensiveOperation, ,收到 Function1[Int, Boolean] 并返回 List[Int].

现在我们上课 Y. 。自然,它必须定义相同的方法,但也必须定义getter expensiveOperation, ,没有任何争论和返回 Function1[Function1[Int, Boolean],List[Int]].

只要这种附加方法不存在,它可能是可行的 X 也。因此,让我们定义它:

class Z extends Y {
  override val extensiveOperation = new Function1[Function1[Int, Boolean], List[Int]] {
    def apply(p: Int => Boolean) = List range (1, 10) filter p
  }
}

如何定义?确实会复制 apply的身体作为身体 expensiveOperation (接收参数,而不是getter的一个)?它可能仍然可行。但是,让我们尝试其他事情:

class W(f: ((Int) => Boolean) => List[Int]) extends Y {
  override val extensiveOperation = f
}

现在,我们如何覆盖参数收集 extensiveOperation?我想我们可以这样写:

override def extensiveOperation(p: Int => Boolean) = extensiveOperation.apply(p)

那是可行的。但是我个人认为这有点令人费解。我的建议:写一个简短的SID,并在Scala邮件列表上获得一些协议。但是,如果没有代码来实施它,我认为它没有太多的机会被采用 - Scala必须跟踪每个功能类型的 val 确定它是否覆盖了 def 或不。

您总是可以将其转发到您的val:

trait T {
  def expensiveOperation(p: Int => Boolean) : List[Int]
}

class C extends T {
  def expensiveOperation(p: Int => Boolean): List[Int] = {
      expensiveOperationVal(p) 
  }
  val expensiveOperationVal = { p: (Int=>Boolean) =>
    // ... lazy stuff
    List(1,2,3)
  }
}

而且,尽管这没有回答您的问题,但除非您 // ... get expensive list 代码取决于谓词 p, ,那么您可以做类似的事情:

class C extends T {
  def expensiveOperation(p: Int => Boolean): List[Int] = {
      myExpensiveList filter p 
  }
  lazy val myExpensiveList = {
    val l = // ... expensive stuff
    l
  }
}

编辑:好的,我没有弄清楚您的实际意思。但是,如果您的意思是我的想法...

您可以使用缩写的语法,创建一个应用操作的Val:

val expensive = (p: (Int) => Boolean) => {
  val l = List(1,2,3,4)
  l filter p
}
scala> expensive(_<3)
res1: List[Int] = List(1,2)

但这实际上并没有缓存列表,这是我认为您想要的。原因是此短手语法将所有内容都放入=>的函数方法中。您可能希望列表像这样存储:

val expensive = new Function1[Int=>Boolean,List[Int]] {
  lazy val l = List(1,2,3,4)
  def apply(p: (Int) => Boolean) = { l filter p }
}

为此,我不知道的速记。

编辑:如果您很乐意在该块之外创建列表,则有一个速记(另请参见评论):

val expensive = List(1,2,3,4).filter _

scala> expensive(_ < 3)
res6: List[Int] = List(1, 2)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top