এখানে 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 অন্যান্য ক্ষেত্রে স্কাল এএফাইক-তে কোনও আনুষ্ঠানিক গ্যারান্টি নেই। এমনকি যদি ফাংশনটি নিজেই নিরাপদ থাকে তবে অন্যান্য ফাংশনগুলি যার কাছে এটি কল করছে তা নাও হতে পারে: /।