我对下面的scala代码的理解是否正确?

时间:2012-10-24 15:45:33

标签: scala

我只是想了解下面的代码:


这里声明了一个新类型别名Set,它是一个接受Int的函数 参数并返回一个布尔值

type Set = Int => Boolean

这里声明了一个新方法'contains',它接受Set和Int类型的两个参数 返回一个布尔值。布尔值设置为前面声明的函数 ('type Set = Int => Boolean') 但是执行什么逻辑来确定Int'elem'是否是Set's'

的成员
def contains(set: Set, elem: Int): Boolean = set(elem)

这里定义了一个方法,它返回一个返回函数的集合?

def singletonSet(elem: Int): Set = set => set == elem

包含评论的完整代码:

  /**
   * We represent a set by its characteristic function, i.e.
   * its `contains` predicate.
   */
  type Set = Int => Boolean

      /**
       * Indicates whether a set contains a given element.
       */
def contains(set: Set, elem: Int): Boolean = set(elem)

      /**
       * Returns the set of the one given element.
       */
      def singletonSet(elem: Int): Set = set => set == elem

4 个答案:

答案 0 :(得分:88)

让我们按逻辑顺序向后阅读。

假设你有一组有限的整数:例如0, 1, 2, 3, 5, 8

描述这组整数的一种方法是通过一个函数(characteristic or indicator function),对于每个整数,如果整数在集合中,则返回true,否则返回false。 正如我们所描述的,这个函数的签名必须始终是Int => Bool(“给我一个整数,我会告诉你它是否在集合中”),而它的实现将根据具体的集合而变化。 / p>

对于上面示例中的设置,您可以将此函数简单地写为:

val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x

或者认识到集合中的int是Fibonacci序列的第一个,并以稍微复杂的方式定义f(我不会在这里做...)。 请注意,我使用的“包含”是为所有scala集合定义的。 在任何情况下,现在你都有一个函数可以告诉你集合中的内容和不集合的内容。 我们在REPL中尝试一下。

scala> val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>

scala> mySet(3)
res0: Boolean = true

scala> mySet(9)
res1: Boolean = false

现在,mySet的类型为Int => Boolean,如果我们将其定义为类型别名,我们可以使其更具可读性。

scala> type Set = Int => Boolean
defined type alias Set

除了可读性之外,将Set定义为Int => Boolean的别名是明确表示Set 的特征函数。我们可以使用Set类型别名以更简洁(但在其他方面等效)的方式重新定义mySet:

scala> val mySet: Set = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>

现在是这个长答案的最后一部分。让我们定义一个特征函数来描述这个Singleton集:3。 易:

val Singleton3 : Set = set => set == 3

对于仅包含4的Singleton集合,它将是:

val Singleton4 : Set = set => set == 4

因此,让我们概括一下这些函数的创建,并编写一个返回Singleton函数的方法,对于任何整数,该函数描述仅包含该整数的集合:

def singletonSet(elem: Int): Set = set => set == elem

<强>附录

我跳过了这一部分,因为它并不是真的需要:def contains(set: Set, elem: Int): Boolean = set(elem)

我认为这有点毫无意义,并且(没有更多上下文)它看起来就像一个人为的例子来演示如何将函数作为参数传递,就像scala中的任何其他类型一样。需要Int => Bool函数和Int才能将函数应用于Int,以便您可以执行

scala> contains(mySet, 3)
res2: Boolean = true

就像直接调用mySet(3)一样。

答案 1 :(得分:4)

在观看关于“Currying”的讲座视频后,我相信Paolo的解决方案表达方式更为简洁:

    def singletonSet(elem: Int): Set = {
    def innerFunction (givenElement: Int) = 
      if (elem == givenElement) true
      else false
      innerFunction
  }
如果我错了,Plesae纠正我!

答案 2 :(得分:1)

回答你的问题 - 但是执行了什么逻辑来确定Int'elem'是否是Set's'的成员

执行实际函数调用时会执行此操作。请考虑以下函数调用。

  

包含(singletonSet(1),1)

现在,singletonSet被定义为 def singletonSet(elem:Int):Set = x =&gt; x == elem (为了清楚起见,我选择使用标识符x)。 singletonSet的返回类型是Set类型的函数,它接受Int参数并返回Boolean。所以上面的调用函数的第一个参数singletonSet(1)等于函数 x =&gt; x == 1 因为这里的元素是1.所以我们得到

  

包含((x =&gt; x == 1),1)

现在考虑包含函数的定义 def contains(f:Set,elem:Int):Boolean = f(elem)。上面调用中的第一个参数是函数x =&gt; x == 1代替形式参数f,第二个参数1代替形式参数elem。 contains的返回值是函数f(elem),它等于f(1)。由于f(x)定义为(x == 1),f(1)等于(1 == 1),返回true。

按照相同的逻辑,像contains(singletonSet(1),2)这样的函数调用最终会等同于(1 == 2),它将返回false。

答案 3 :(得分:1)

我现在正在上课,也很困惑,但我想我现在明白了。

def singletonSet(elem: Int): Set = (x : Int) => x == elem

这里singletonSet是一个函数,它返回一个类型为Set 的函数,定义为type Set = Int => Boolean

所以当你调用def contains(s:Set, elem:Int): Boolean = s(elem)时,例如:contains(singletonSet(1), 2),singletonSet(1)返回一个函数,其中elem(在singletonSet的定义中)设置为1,而2(也定义为elem,但是在contains的参数中定义)作为x在singletonSet定义中传入,我们需要摆脱java set的想法,我们不需要singletonSet来保持我们设置的值。

为了更好地理解,我们可以更改参数名称,如下所示:

def singletonSet(elemToStore: Int): Set = (x : Int) => x == elemToStore

def contains(s: Set, elemToCheck: Int): Boolean = s(elemToCheck)