【问题标题】:Is Scala a Functional Programming Language? [closed]Scala 是函数式编程语言吗? [关闭]
【发布时间】:2011-09-04 04:49:58
【问题描述】:

我从 Java 学习编程,然后尝试每年学习一种编程语言,其次是 C++,然后是 Python。它来学习下一个,我寻找新的东西,我选择了 Scala,因为它与 Java 兼容,并且可能是从 OOP 到函数式编程的某种过渡。

很酷,学习新范式、新风格和新思维方式。阅读优雅的 Scala 概念是很棒的体验,而且在 Scala 上编写代码要好得多。

阅读了很多我面对this批评Scala的文章:

Scala 不是函数式编程语言。它是一种带有闭包的静态类型的面向对象语言。

看了这篇文章后,我产生了一些疑问,我真的很喜欢 Scala,并且开始更多地写 Scala,但是 Scala 适合函数式编程的定义吗?那篇文章是说真话还是只是假装读者?我必须学习 Haskell 或其他函数式编程语言才能真正体验 FP 吗?

更新:期待合理的答案,提供好的例子,不会引起争议。

【问题讨论】:

  • 请删除所有与问题无关的个人意见。这浪费了我们宝贵的时间,这些时间应该投入到解决您的问题上。
  • 谢谢,我已经更新了问题。
  • “面向对象的语言鼓励过度使用状态和继承。” “函数式语言鼓励过度使用高阶编程。” (来自 Peter van Roy och Seif Haridi。版权所有 © 2004。0-262-22069-5。麻省理工学院出版社。计算机编程的概念、技术和模型。)。
  • 这个问题无法回答,因为没有明确定义什么是函数式语言。您当然可以在 Scala 中以函数式风格进行编程。这是否使它起作用?

标签: java python scala haskell functional-programming


【解决方案1】:

Scala 不会强迫您以函数式风格编写代码。这是完全有效的 Scala:

var i = 1
while (i < 10) {
  println("I like side effects, this is number "+i)
  i += 1
}
case class C(var i: Int, var set: Boolean = false)
def setMe(c: C) = { if (!c.set) { c.set = true; c.i += 1 }; c }
setMe(C(5))

所以从这个意义上说,可怕的是,Scala 不是函数式的!大量副作用,可变状态——你可以在 Java 中做的所有事情都可以在 Scala 中做。

尽管如此,Scala 允许您以函数式风格编写代码,并以多种方式让您的生活更轻松(比使用 Java):

  • 有一流的功能
  • 有一个不可变的集合库
  • 支持尾递归(在 JVM 可以管理的范围内)
  • 支持模式匹配
  • (等)

这看起来更实用:

for (i <- 1 to 10) println("Sometimes side effects are a necessary evil; this is number"+i)
case class C(i: Int, set: Boolean = false)
def setIt(c: C, f: Int=>Int) = C(f(c.i), true)
setIt(C(5), _+1)

值得注意的是,那篇文章的作者似乎对 Scala 的理解很差;几乎每一个在他手中看起来很丑的例子都是不必要的丑陋。例如,他写道

def x(a: Int, b: Int) = a + b
def y = Function.curried(x _)(1)

但如果你注意自己在做什么,那就没那么糟糕了:

def x(a: Int)(b: Int) = a + b
val y = x(1) _

无论如何,最重要的是 Scala 不是一种纯粹的函数式编程语言,因此,它的语法并不总是适合函数式编程,因为还有其他考虑因素在起作用。然而,它确实具备函数式编程语言所期望的几乎所有标准特性。

【讨论】:

    【解决方案2】:

    【讨论】:

      【解决方案3】:

      我个人对功能语言的试金石是教堂数字。

      方案示例:

      (define (thrice f)
          (lambda (x)
              (f (f (f x))))))
      
      ((thrice 1+) 0)
        => 3
      

      1+ 是一个将 1 添加到其参数的 Scheme 函数。thrice 接受一个函数 f 并返回一个函数,该函数将 f 与自身组合三次。因此(thrice 1+) 将其参数添加了三个。)

      ((thrice (thrice 1+)) 0)
        => 9
      

      (由于(thrice 1+) 是一个加三的函数,取其中的thrice 得到一个加九的函数。)

      还有我最喜欢的:

      (((thrice thrice) 1+) 0)
        => 27
      

      (推理留给读者作为练习。最后一个例子是最重要的。)

      如果你不能用你的语言编写这个例子,而没有可怕的扭曲,那么我说它不是一种函数式语言(例如:C/C++)。

      如果您可以用您的语言编写此示例,但看起来非常不自然,那么我说您的语言“支持函数式编程”但不是真正的函数式语言(例如:Perl)。

      如果此示例巧妙地移植到您的语言,并且实际上看起来与您日常使用的方式没有太大区别,那么它就是一种函数式语言。

      我不知道 Scala。有人想告诉我它适合哪里吗? :-)

      【讨论】:

      • def thrice[A](f: A =&gt; A) = f andThen f andThen fthrice[Int](1+)(0) // gives 3thrice(thrice[Int](1+))(0) // gives 9thrice(thrice[Int])(1+)(0) // gives 27。怎么样?
      • (FWIW,它看起来不自然,但那是因为创建数字 27 的效率非常低,并且因为应用后继操作“1+”并不是我们大多数人认为做算术的方式。 (就此而言,对函数进行三次处理也不是那么有用,因为 Iterator.iterate 可以任意深度地应用函数。)
      • @Rex:好吧,你也不会像这样在 Scheme 中添加 27,但这不是重点。这实际上是 Alonzo Church 在原始 lambda 演算中表示自然数的方式。 (当你只有lambda时,你的选择是有限的。)我称之为“三次”,他称之为“3”;就像在实际的整数 3 中一样。在我看来,编写可以应用于自身的“三次”的能力是对语言“功能性”的一个很好的测试。
      • @Hyenk:嗯,我想对于大多数 Perl 程序员来说,线路噪音看起来是“自然的”:-)
      • @Nemo:美在旁观者的眼中。我可以告诉同样的方案。 Thrice(\&amp;Thrice)-&gt;(\&amp;Inc)-&gt;(0) 对我来说似乎比 (((thrice thrice) 1+) 0) 更容易理解,它更明确地发生了什么。
      猜你喜欢
      • 2011-04-27
      • 1970-01-01
      • 2010-12-05
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      相关资源
      最近更新 更多