【问题标题】:Is my understanding of below scala code correct?我对以下 scala 代码的理解是否正确?
【发布时间】:2012-10-14 16:49:16
【问题描述】:

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


这里声明了一个新类型别名 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

带有 cmets 的完整代码:

  /**
   * 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

【问题讨论】:

  • 你在询问 coursera Scala 课程作业 2 的答案。
  • 我相信他只是要求解释。事实上,我现在正在学习这门课程,函数式编程对我来说是全新的。我也有这个assingment的问题......我不想要解决方案 - 只是解释。下面的 Paola 给出了我所需要的。
  • 我也直觉地知道如何写这个(最终),但受益于 Paolo 的回答。不是每个来这里的人都想作弊。感谢 Moby 为这个问题的提出方式辩护。 +1

标签: scala


【解决方案1】:

让我们按逻辑顺序倒着读。

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

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

对于我上面示例中的集合,您可以将这个函数简单地编写为:

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

或认识到集合中的整数是斐波那契数列的第一个整数,并以稍微复杂的方式定义 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 =&gt; Boolean,如果我们将其定义为类型别名,我们可以使其更具可读性。

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

除了可读性之外,将Set 定义为Int =&gt; Boolean 的别名可以明确表明,在某种程度上,集合它的特征功能。我们可以使用Set 类型别名以更简洁(但在其他方面等效)的方式重新定义 mySet:

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

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

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

对于仅包含 4 个的单例集,它将是:

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

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

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

附录:

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

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

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

这就像直接调用mySet(3)

【讨论】:

  • 我同意您的附录:这基本上是 Lambda 演算中集合的 Church 编码(令人惊讶的是,这也是面向对象的编码 - 请参阅 William R. CookOn Understanding Data Abstraction, Revisited 以了解原因)。巧妙的技巧正是集合同时是对象和特征函数,而这种contains 方法不必要地掩盖了美丽的设计。
  • @PaoloFalabella “val Singleton4 : Set = set => set == 4”的详细方式是什么我无法理解“set”参数的来源
  • @Pangea set =&gt; set == 4 是一个闭包,它接受一个名为set 的输入并返回一个布尔输出(是set == 4?)。您可以使用x 或任何其他名称代替set。在这里,我们将整个闭包分配给一个名为 Singleton4 的 val。希望现在更清楚了
  • 方法 singletonSet 返回一个集合,其中闭包返回一个布尔值。我很困惑。
  • @user1434770 很难在评论中以不混淆的方式回复,但基本上是的...存储在堆上的内部状态,
【解决方案2】:

看了《Currying》的讲座视频后,我相信Paolo的解决方案用更冗长的方式表达是:

    def singletonSet(elem: Int): Set = {
    def innerFunction (givenElement: Int) = 
      if (elem == givenElement) true
      else false
      innerFunction
  }

如果我错了,请纠正我!

【讨论】:

  • 使用匿名函数会短很多:def singletonSet(elem: Int): Set = (x: Int) =&gt; elem == x
  • 方法 singletonSet 返回一个集合,其中闭包返回一个布尔值。我很困惑。
【解决方案3】:

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

这是在您进行实际函数调用时执行的。考虑以下函数调用。

包含(singletonSet(1), 1)

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

包含((x => x == 1),1)

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

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

【讨论】:

  • Ramya,这在以下场景中如何工作? def contains(s: Set, elem: Int): Boolean = s(elem) ;验证集:集 = 集(1,2,3,4);包含(集,5);在这种情况下,我创建了一组超过 1 个值。这工作得很好。它是否一一迭代所有值?
【解决方案4】:

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

def singletonSet(elem: Int): Set = (x : Int) =&gt; x == elem

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

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

为了更好的理解,我们可以把参数名改成如下:

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

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

【讨论】:

    猜你喜欢
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多