我可以使用def
实现val
,其中def
不带参数:
trait T { def foo: Int }
class C(val foo: Int) extends T
为什么这不能扩展到实现def
将N args带到FunctionN
的val?我希望有可能实现类似的东西:
def expensiveOperation(p: Int => Boolean) : List[Int]
使用惰性函数val
。类似的东西:
val expensiveOperation = {
val l = //get expensive list
l.filter _ //partially applied function
}
我知道这种语法似乎不适用于2.8。有什么我不知道的,为什么我不能实现 def
将参数作为功能val
?
答案 0 :(得分:2)
现在,编辑后,我想我明白你在追求什么。但是你不能做你想要的,因为类型签名不匹配。
def x: Int = 5
val x: Int = 5
在这两种情况下,您都不提供任何东西并返回Int(在本例中为5)。太好了!
def expensive(p: Int => Boolean): List[Int]
现在你提供一些东西。但是val只是某个存储对象。您可以向标签引用的对象提供 ,但这与向标签“x”提供内容不同。
如果你想要val覆盖它,那么你需要使用def:
def expensive: (Int=>Boolean)=>List[Int]
现在你有一些你没有参数调用的东西,它返回的东西可以采用Int =>布尔函数并给你一个List [Int]作为回报。这正是你用val得到的 - 在这两种情况下,你都有一些返回具有你想要的功能的对象的名称。
(在Scala中,vals实际上是作为隐藏字段实现的,getter方法不带任何参数并返回隐藏字段中的任何内容。所以它实际上就像def一样。)
答案 1 :(得分:2)
val
不接受参数,因为它是计算并存储在字段中的。但我可能只是推荐你过去两天在邮件列表上发表的大量帖子。
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
}
}
如何定义? Scala是否将apply
的主体复制为expensiveOperation
的主体(接收参数的主体,而不是获取参数的主体)?它可能仍然可行。不过,让我们试试别的东西:
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
。
答案 2 :(得分:1)
你总是可以把它转发给你的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
}
}
答案 3 :(得分:0)
编辑:好吧,我没弄明白你的意思。但如果你的意思是我的意思......
您可以使用缩写语法创建应用操作的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)
但这实际上并没有缓存列表,这就是我认为你想要的。原因是这个简短的语法将所有内容放在=&gt;之后。进入Function1的apply方法。您可能希望列表存储如下:
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)