İşte fs2 belgelerinden bir parça kod . İşlev go
özyinelemeli. Soru, yığının güvenli olup olmadığını nasıl bilebiliriz ve herhangi bir fonksiyonun yığın güvenli olup olmadığını nasıl anlayabiliriz?
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
Başka bir yöntemden çağırırsak da yığın güvenli olur mu?
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
Örneğin Monad[F]
typeclass'ı kullanmak için yeniden yazabilirsiniz - tailRecM
işlevin istif güvenli olacağından emin olmak için trambolini açıkça gerçekleştirmenizi sağlayan bir yöntem vardır . Yanılıyor olabilirim ama onsuz F
kendi başına güvenli bir şekilde istiflenmeye güveniyorsunuz (örneğin, trambolini dahili olarak uygularsa), ancak kiminizi tanımlayacağını asla bilemezsiniz F
, bu yüzden bunu yapmamalısınız. F
Yığın güvenliği için bir garantiniz yoksa, tailRecM
yasalar tarafından yığın açısından güvenli olduğu için bir tür sınıfı kullanın .
@tailrec
kuyruk kayıt işlevleri için ek açıklama ile kanıtlamasına izin vermek kolaydır . Diğer durumlar için Scala AFAIK'te resmi bir garanti yoktur. Fonksiyonun kendisi güvenli olsa bile, çağırdığı diğer fonksiyonlar olmayabilir: /.