Scala流的行为违反直觉

时间:2013-07-25 20:25:46

标签: scala stream

我正在玩Scala的游戏,但我不确定是否能抓住这个想法。 我们考虑以下代码

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head, fun(s.tail))

执行此

val f = fun(Stream.from(7))
f take 14 foreach println

的结果

7 8 9 10 ... up to 20

让我说我理解这一点。

现在,稍微更改代码(添加2到头)

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head + 2, fun(s.tail))

结果

9 10 11 ... up to 22

我想我也明白了。问题从下一个例子开始(d

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head / 2, fun(s.tail))

3 4 4 5 5 6 6 7 7 8 8 9 9 10

我不明白,请解释为什么会这样结果? 类似地,减去也不像我期望的那样行为

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head - 2, fun(s.tail))

输出

5 6 7 8 9 10 ... up to 18

3 个答案:

答案 0 :(得分:1)

鉴于你的“接受”:7 8 9 10 ... up to 20

  • 当你对每个元素+ 2时会发生什么?

  • 当你/ 2对每个元素(int算术)时会发生什么?

  • 当你对每个元素- 2时会发生什么?

答案 1 :(得分:0)

如果您将其视为映射Stream

,是否更直观?
scala> val s1 = Stream.from(10)
s1: scala.collection.immutable.Stream[Int] = Stream(10, ?)

scala> val s2 = s1 map (_ * 2)
s2: scala.collection.immutable.Stream[Int] = Stream(20, ?)

scala> s2.take(5).toList
res0: List[Int] = List(20, 22, 24, 26, 28)

scala> val s3 = s1 map (_ / 2)
s3: scala.collection.immutable.Stream[Int] = Stream(5, ?)

scala> s3.take(5).toList
res1: List[Int] = List(5, 5, 6, 6, 7)

scala> val s4 = s1 map (_ - 2)
s4: scala.collection.immutable.Stream[Int] = Stream(8, ?)

scala> s4.take(5).toList
res2: List[Int] = List(8, 9, 10, 11, 12)

答案 2 :(得分:0)

好的,让我们试着把它分解......

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head, fun(s.tail))

是一个函数,它接受Stream并将其headtail分开,在tail上递归应用,然后将{2}结果重新组合为{{ 1}} operator。

由于在此操作期间未触及cons,因此head将按原样逐元素重建。

Stream

val f = fun(Stream.from(7)) f相同[即]从7开始增加整数的无限序列

打印Stream.from(7)实际上表明我们有从7开始的前14个数字 [即7,8,9,...,20]

接下来会发生的是,在使用f take 14重建流时,每个元素都会以某种方式进行修改

cons

def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head + 2, fun(s.tail)) 添加2 ,然后再将其与修改后的head重新组合。后者以相同的方式进行修改,其第一个元素被添加到2,然后重新组合到它自己的tail,所以拥有。

如果我们再次假设tail包含从7开始的数字,那么会发生什么看起来像

s

这与向流fun(s) = cons(7 + 2, cons(8 + 2, cons(9 + 2, ... ad infinitum ... ))))) 的每个元素添加2相同。

代码确认通过打印“9到22”,正好是“7到20”,每个元素都添加了2个。

其他例子类似:

  • 每个元素除以2 的流(并舍入到地板 整数值,因为s的类型为Stream}
  • 每个元素递减2
  • 的流