এখানে 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]
টাইপক্লাস ব্যবহার করে পুনরায় লিখতে পারেন - tailRecM
ফাংশনটি স্ট্যাক নিরাপদ থাকবে তার গ্যারান্টি দেওয়ার জন্য আপনাকে স্পষ্টভাবে ট্রামপোলিন সঞ্চালনের অনুমতি দেওয়ার পদ্ধতি রয়েছে । আমি ভুল হতে পারি তবে এগুলি ব্যতীত আপনি নিজেরাই F
স্ট্যাক নিরাপদে থাকার উপর নির্ভর করছেন (উদাহরণস্বরূপ যদি এটি অভ্যন্তরীণভাবে ট্রাম্পোলাইন প্রয়োগ করে) তবে আপনি কখনই জানেন না কে আপনার সংজ্ঞা দেবে F
, সুতরাং আপনার এটি করা উচিত নয়। যদি আপনার কোনও গ্যারান্টি নেই F
যা স্ট্যাক নিরাপদ, এটি একটি ধরণের শ্রেণি ব্যবহার করুন যা tailRecM
এটি সরবরাহ করে কারণ এটি আইন অনুসারে স্ট্যাক-নিরাপদ।
@tailrec
সংকলকটিকে লেজ রেক ফাংশনগুলির জন্য টীকা সহ প্রমাণ করতে দেওয়া সহজ easy অন্যান্য ক্ষেত্রে স্কাল এএফাইক-তে কোনও আনুষ্ঠানিক গ্যারান্টি নেই। এমনকি যদি ফাংশনটি নিজেই নিরাপদ থাকে তবে অন্যান্য ফাংশনগুলি যার কাছে এটি কল করছে তা নাও হতে পারে: /।