我正在玩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
答案 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
并将其head
和tail
分开,在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个。
其他例子类似:
s
的类型为Stream
}