用n个参数作为类型函数的Val实施DEF
-
23-09-2019 - |
题
我可以实现 def
与 val
在哪里 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)