scala中高阶函数古怪的参数

时间:2015-12-09 20:59:01

标签: scala

我正在开设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?

3 个答案:

答案 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实例,在这种情况下是一个实例功能从IntBooleanInt => Boolean)。此时创建了该函数(虽然它对69的{​​{1}}值“关闭”,未评估,因此此处未设置elem

然后,当x被调用时,它会运行containss(elem)此处elem关闭的elem不一样!)参数值singletonSetF

6是对先前创建的函数的调用(s(elem)这里是相同的s - 因此相同的Set实例 - 由调用创建Int => Boolean),将参数singletonSet的值(传递给elem作为值contains)传递给该函数。

此时执行函数,6 = x,生成您观察到的打印语句。

答案 2 :(得分:1)

contains函数有两个参数:SetInt。我们正在尝试测试Set是否包含Int

Set实际上是Int => Boolean类型的函数,由Set的类型别名定义。

我们通过调用singletonSet创建第一个参数,它返回一个函数(singletonSetF)。但是,singletonSetF是一个闭包 - 它会捕获传递到elem的{​​{1}}的值,在这种情况下为69。

最后我们致电singletonSets(elem)是包含值69的闭包。s是值6,然后绑定到参数' x'在elem

重要:代码有点混乱,因为您使用singletonSetF表示两个不同位置的两个不同的东西 - 在elem中,它是我们正在测试的值成为集合的成员;在contains中,它是该集的唯一成员。重命名其中一个可能会有很大帮助!