นี่คือชิ้นส่วนของรหัสจากเอกสารสำหรับFS2 ฟังก์ชั่นgoซ้ำ คำถามคือเราจะรู้ได้อย่างไรว่าปลอดภัยสำหรับสแต็กและวิธีการใช้ฟังก์ชันใดที่ปลอดภัยสแต็ก
import fs2._
// import fs2._
def tk[F[_],O](n: Long): Pipe[F,O,O] = {
def go(s: Stream[F,O], n: Long): Pull[F,O,Unit] = {
s.pull.uncons.flatMap {
case Some((hd,tl)) =>
hd.size match {
case m if m <= n => Pull.output(hd) >> go(tl, n - m)
case m => Pull.output(hd.take(n.toInt)) >> Pull.done
}
case None => Pull.done
}
}
in => go(in,n).stream
}
// tk: [F[_], O](n: Long)fs2.Pipe[F,O,O]
Stream(1,2,3,4).through(tk(2)).toList
// res33: List[Int] = List(1, 2)
มันจะปลอดภัยหรือไม่หากเราเรียกgoใช้วิธีอื่น
def tk[F[_],O](n: Long): Pipe[F,O,O] = {
def go(s: Stream[F,O], n: Long): Pull[F,O,Unit] = {
s.pull.uncons.flatMap {
case Some((hd,tl)) =>
hd.size match {
case m if m <= n => otherMethod(...)
case m => Pull.output(hd.take(n.toInt)) >> Pull.done
}
case None => Pull.done
}
}
def otherMethod(...) = {
Pull.output(hd) >> go(tl, n - m)
}
in => go(in,n).stream
}
goเพื่อใช้เช่นMonad[F]typeclass - มีtailRecMวิธีการที่อนุญาตให้คุณใช้แทรมโพลีนอย่างชัดเจนเพื่อรับประกันว่าฟังก์ชั่นนั้นจะปลอดภัย ฉันอาจจะผิด แต่ถ้าไม่มีคุณพึ่งพาFความปลอดภัยด้วยตัวเอง (เช่นถ้าใช้แทรมโพลีนภายใน) แต่คุณไม่มีทางรู้เลยว่าใครจะเป็นผู้กำหนดคุณFดังนั้นคุณไม่ควรทำเช่นนี้ หากคุณไม่มีการรับประกันว่าFปลอดภัยสแต็กให้ใช้คลาสประเภทที่ให้ไว้tailRecMเพราะมันปลอดภัยสแต็คตามกฎหมาย
@tailrecคำอธิบายประกอบสำหรับฟังก์ชั่น tail rec สำหรับกรณีอื่น ๆ ไม่มีการรับประกันอย่างเป็นทางการใน Scala AFAIK แม้ว่าฟังก์ชั่นของตัวเองจะปลอดภัย แต่ฟังก์ชั่นอื่น ๆ ที่ใช้อยู่อาจจะไม่: /