我是一名初学者Scala开发人员,他在编写练习时遇到了问题(5.12),这本书采用了#34; Scala中的函数编程"保罗丘萨诺。
我在这里有一个名为展开的函数,它接受一个初始状态和一个生成具有下一个状态的流的函数:
def unfold[A,S](z: S)(f: S => Option[(A,S)]): Stream[A] = f(z) match {
case Some((h,t)) => h #:: unfold(t)(f)
case _ => Stream.empty
}
例如,使用此功能可以创建无限的对象流,例如
def constant[A](a: A): Stream[A] = unfold(a)(_ => Some(a,a))
现在,我想创建Fibonacci序列,然后输入:
def fibs: Stream[Int] = unfold((0,1))((a,b) => Some(a,(b,a+b)))
我收到这些错误:
缺少参数类型b
Some [((Int,Int),(Nothing,String))]类型的表达式不符合预期类型Option [(A _,(Int,Int))]
如果我在传递给展开的匿名函数中使用 case 关键字,例如:
{ case (a,b) => Some(a,(b,a+b))}
所以我的问题是:两个实现之间的区别是什么?是不是我不理解的类型推断?
答案 0 :(得分:2)
MAX()
是一个带有两个参数的函数 - { (a,b) => Some(a, (b, a+b)) }
和a
,并返回一个选项(元组的)。这不是你需要的。您想要定义一个带有单个(元组)参数的函数。一种方法是这样的:
b
您可以扩展为以下内容:
{ tuple => Some(tuple._1, (tuple._2, tuple._1 + tuple._2)) }
这看起来很长,但是scala有一个特殊的语法结构,它允许你使用类似于模式匹配的语法(动态地“解析 { tuple =>
val a = tuple._1
val b = tuple._2
// Can also do it shorter, with automatic unapply here:
// val (a,b) = tuple
// this is already pretty similar to what you have with `case`, right?
Some(a, (b, a+b))
}
,在运行时将复杂参数解构为匿名函数,同样如模式匹配那样):
unapply
这与上面完全相同。
答案 1 :(得分:0)
您似乎已经达成了有关编译器如何解释代码的规则之一:
A normal function of one arg:
scala> val g = (x: Int) => x + 1
g: Int => Int = <function1>
The data type for a tuple of ints is Tuple2(Int, Int):
scala> (3,4)
res3: (Int, Int) = (3,4)
scala> val a: Tuple2[Int, Int] = (3,4)
a: (Int, Int) = (3,4)
But this does not work:
scala> val f = ((a,b): (Int, Int)) => a+b
<console>:1: error: not a legal formal parameter.
Note: Tuples cannot be directly destructured in method or function parameters.
Either create a single parameter accepting the Tuple1,
or consider a pattern matching anonymous function: `{ case (param1, param1) => ... }
val f = ((a,b): (Int, Int)) => a+b
^
This works:
scala> val f = (x: Tuple2[Int, Int]) => x._1 + x._2
f: ((Int, Int)) => Int = <function1>
这是你认为你可以做的:
val f = ((a, b): (Int, Int)) => Some(a, (b, a + b))
然后(在unfold
的上下文中)(0,1)被理解为类型(Int, Int)
,所以当你调用unfold
时你可以省略类型声明并且只写((a, b)) => Some(a, (b, a + b))
。但它不起作用,因为“元组不能在方法或函数参数中直接解构”。
上面的函数f
甚至不能在unfold
之外编译。相反,这编译:
val g = (x: Tuple2[Int, Int]) => Some(x._1, (x._2, x._1 + x._2))