我正在向一位 friend (他大部分时间使用 Java)做广告,他问我一个挑战:在 Scala 中编写数组 {1, 2, 4, 8, 16} 的方法是什么。

我不太了解函数式编程,但我真的很喜欢 Scala。然而,这是一个由(n*(n-1))形成的迭代数组。 ,但是如何跟踪上一步呢?有没有一种方法可以在 Scala 中轻松完成,或者我是否必须编写多行代码才能实现这一目标?

请您参考如下方法:

Array.iterate(1, 5)(2 * _) 

或者
Array.iterate(1, 5)(n => 2 * n) 

按照评论中的要求详细说明这一点。不知道你想让我详细说明什么,希望你能找到你需要的。

这是 上的函数 iterate(start,len)(f)对象 数组 ( scaladoc )。那将是 静态 在 java 。

重点是填充一个数组 len元素,从第一个值 start并且总是通过将前一个元素传递给函数 f 来计算下一个元素。

一个基本的实现是
import scala.reflect.ClassTag 
 
def iterate[A: ClassTag](start: A, len: Int)(f: A => A): Array[A] = { 
  val result = new Array[A](len) 
  if (len > 0) { 
    var current = start 
    result(0) = current 
    for (i <- 1 until len) { 
      current = f(current) 
      result(i) = current 
    } 
  } 
  result 
} 

(实际实现中,可以找到 here 差别不大。主要是因为相同的代码用于不同的数据结构,例如 List.iterate )

除此之外,实现非常简单。语法可能需要一些解释:
def iterate[A](...) : Array[A]使其成为通用方法,可用于任何类型 A。那将是 public <A> A[] iterate(...)在 java 。
ClassTag只是一个技术问题,在 Scala 和 Java 中,您通常无法创建泛型类型的数组(java new E[]),而 : ClassTag要求编译器添加一些魔法,这与在方法声明中添加并在调用站点传递 class<A> clazz 非常相似。 java中的参数,然后可用于通过反射创建数组。如果您执行例如 List.iterate 而不是 Array.iterate,则不需要。

也许更令人惊讶的是,两个参数列表,一个带有 start 和 len,然后在一个单独的括号中,一个带有 f。 Scala 允许一个方法有多个参数列表。这里的原因是 scala 进行类型推断的特殊方式:查看第一个参数列表,它将根据 start 的类型确定什么是 A。只有在之后,它才会查看第二个列表,然后才知道 A 是什么类型。否则,它需要被告知,所以如果只有一个参数列表, def iterate[A: ClassTag](start: A, len: Int, f: A => A),
那么电话应该是
  • Array.iterate(1, 5, n : Int => 2 * n)
  • Array.iterate[Int](1, 5, n => 2 * n)
  • Array.iterate(1, 5, 2 * (_: int))
  • Array.iterate[Int](1, 5, 2 * _)

  • 制作 Int明确的一种或另一种方式。所以在scala 中将函数参数放在一个单独的参数列表中是很常见的。该类型可能比'Int'要长得多。
    A => A只是类型 Function1[A,A 的语法糖]。显然,函数式语言具有作为(第一类)值的函数,类型化函数式语言具有函数类型。

    通话中, iterate(1, 5)(n => 2 * n) , n => 2 * n是函数的值。更完整的声明是 {n: Int => 2 * n} ,但由于上述原因,可以免除 Int。 Scala 语法相当灵活,您也可以省去圆括号或方括号。所以它可能是 iterate(1, 5){n => 2 * n} . curl 允许包含多个指令的完整块,此处不需要。

    至于不变性,Array 基本上是可变的,除了在某个时刻更改数组之外,没有办法将值放入数组中。我的实现(以及库中的实现)也使用了一个可变的 var ( current ) 和副作用 for ,这不是绝对必要的,(尾)递归实现的编写时间只会稍微长一点,并且同样有效。但是一个可变的本地并没有太大的伤害,无论如何我们已经在处理一个可变数组。


    评论关闭
    IT干货网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!