我正在开设Coursera的Scala课程作业并提出问题。出于好奇,我已经从一个匿名函数切换到一个已定义的函数:
object sets {
def main(args:Array[String]) {
type Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = {println("in contains elem ="+elem);s(elem)}
def singletonSet(elem: Int): Set = { //println("in singleton elem ="+elem); (x: Int) => x == elem}
def singletonSetF(x: Int): Boolean = {
println ("in singleton elem ="+elem+", x="+x)
elem == x
}
singletonSetF
}
println(contains(singletonSet(69), 6))
}
}
这是输出:
in contains elem = 6
in singleton elem = 69,x = 6
假
我相信代码是正确的并且正常运行。我的问题是如何以及为什么“elem = 6”参数从contains方法传递,在singletonSetF方法中被赋值为“x = 6”? contains函数调用“s(elem)”是否调用singletonSetF而不是singletonSet?
答案 0 :(得分:1)
我认为主要的问题是,从Set
获取singletonSet
时,您认为s(elem)
是一种固定数据结构。但是,它只是一个可以调用的函数。 singletonSetF
调用它并最终执行singletonSet(69)
中的代码。
以下是发生的事情: singletonSet
调用singletonSetF
函数。此函数返回singletonSetF
函数的函数值。函数值充当局部函数或方法的包装类型。你没有看到包装器,但它是隐式添加的,因为contains
不能直接返回(它是一个无法传递的本地函数)。
Int => Boolean
会收到此函数值,该值已正确输入为6
,并使用值singletonF
调用该函数。然后,函数值/包装器使用值6
调用实数put test
put test/tag_doc/_mapping
{
"properties" : {
"tags" : {
"type" : "nested" ,
"properties": {
"t" : {"type" : "string"},
"weight" : {"type" : "double"}
}
}
}
}
put test/tag_doc/_bulk
{ "index" : { "_index" : "test", "_type" : "tag_doc", "_id":1} }
{"name": "Cornflakes","tags": [{"t": "Cereals", "weight":100},{"t": "Sugar", "weight": 100}]}
{ "index" : { "_index" : "test", "_type" : "tag_doc","_id":2} }
{ "name": "Basmati","tags": [{"t": "Cereals", "weight": 1},{"t": "Rice", "weight": 1000}]}
{ "index" : { "_index" : "test", "_type" : "tag_doc","_id":3} }
{ "name": "Rice Krispies", "tags": [{"t": "Cereals", "weight": 10},{"t": "Rice", "weight": 1}]}
post test/_search
{
"query": {
"dis_max": {
"queries": [
{
"match": {
"name": {
"query": "cereals",
"boost": 100
}
}
},
{
"nested": {
"path": "tags",
"query": {
"function_score": {
"functions": [
{
"field_value_factor": {
"field": "tags.weight"
}
}
],
"query": {
"match": {
"tags.t": "cereals"
}
},
"boost_mode": "replace",
"score_mode": "max"
}
},
"score_mode": "max"
}
}
]
}
}
}
。
答案 1 :(得分:1)
使用值singletonSetF
调用singletonSet
方法时,69
调用会产生一个Set
实例,在这种情况下是一个实例功能从Int
到Boolean
(Int => Boolean
)。此时创建了该函数(虽然它对69
的{{1}}值“关闭”,未评估,因此此处未设置elem
。
然后,当x
被调用时,它会运行contains
行s(elem)
此处elem
关闭的elem
不一样!)参数值singletonSetF
。
行6
是对先前创建的函数的调用(s(elem)
这里是相同的s
- 因此相同的Set
实例 - 由调用创建Int => Boolean
),将参数singletonSet
的值(传递给elem
作为值contains
)传递给该函数。
此时执行函数,6
= x
,生成您观察到的打印语句。
答案 2 :(得分:1)
contains
函数有两个参数:Set
和Int
。我们正在尝试测试Set
是否包含Int
。
Set实际上是Int => Boolean
类型的函数,由Set
的类型别名定义。
我们通过调用singletonSet
创建第一个参数,它返回一个函数(singletonSetF
)。但是,singletonSetF
是一个闭包 - 它会捕获传递到elem
的{{1}}的值,在这种情况下为69。
最后我们致电singletonSet
。 s(elem)
是包含值69的闭包。s
是值6,然后绑定到参数' x'在elem
。
重要:代码有点混乱,因为您使用singletonSetF
表示两个不同位置的两个不同的东西 - 在elem
中,它是我们正在测试的值成为集合的成员;在contains
中,它是该集的唯一成员。重命名其中一个可能会有很大帮助!