আমি মনে করি যে @tailrec
সংকলকটি একটি লেজ পুনরাবৃত্তির ক্রিয়াকে অনুকূল করবে ensure আপনি কি কেবল ঘোষণার সামনে রেখেছেন? স্কেল স্ক্রিপ্টিং মোডে ব্যবহার করা হয় (উদাহরণস্বরূপ, :load <file>
আরপিএল এর অধীনে) যদি এটিও কাজ করে ?
উত্তর:
" টেইল কল, @ টেলরেক এবং ট্রাম্পোলাইন " ব্লগ পোস্ট থেকে:
- স্কেলা ২.৮-এ আপনি
@tailrec
কোন পদ্ধতিগুলি অনুকূলিত হয়েছে সে সম্পর্কে তথ্য পেতে নতুন টিকাটি ব্যবহার করতে সক্ষম হবেন ।
এই টীকা আপনাকে নির্দিষ্ট পদ্ধতি চিহ্নিত করতে দেয় যা আপনি আশা করেন যে সংকলকটি অনুকূলিত করবে।
সংকলক দ্বারা সেগুলি অপ্টিমাইজ করা না হলে আপনি তার পরে একটি সতর্কতা পাবেন।- স্কেল ২.7 বা তার আগে, কোনও পদ্ধতি অপ্টিমাইজড হয়েছে কিনা তা বের করার জন্য আপনাকে ম্যানুয়াল টেস্টিং বা বাইটকোডের পরিদর্শনের উপর নির্ভর করতে হবে।
উদাহরণ:
আপনি একটি
@tailrec
টীকা যোগ করতে পারেন যাতে আপনি নিশ্চিত হন যে আপনার পরিবর্তনগুলি কাজ করেছে।
import scala.annotation.tailrec
class Factorial2 {
def factorial(n: Int): Int = {
@tailrec def factorialAcc(acc: Int, n: Int): Int = {
if (n <= 1) acc
else factorialAcc(n * acc, n - 1)
}
factorialAcc(1, n)
}
}
এবং এটি আরপিএল থেকে কাজ করে (উদাহরণস্বরূপ স্কালার আরপিএল টিপস এবং কৌশলগুলি ):
C:\Prog\Scala\tests>scala
Welcome to Scala version 2.8.0.RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.annotation.tailrec
import scala.annotation.tailrec
scala> class Tails {
| @tailrec def boom(x: Int): Int = {
| if (x == 0) throw new Exception("boom!")
| else boom(x-1)+ 1
| }
| @tailrec def bang(x: Int): Int = {
| if (x == 0) throw new Exception("bang!")
| else bang(x-1)
| }
| }
<console>:9: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
@tailrec def boom(x: Int): Int = {
^
<console>:13: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
@tailrec def bang(x: Int): Int = {
^
স্কালা সংকলক স্বয়ংক্রিয়ভাবে কোনও সত্যিকারের লেজ-পুনরাবৃত্ত পদ্ধতিটি অনুকূল করে তুলবে। আপনি যদি এমন কোনও পদ্ধতির টীকা দেন যা আপনি মনে করেন যে @tailrec
টীকাটি টীকা অনুসারে টীকা অনুসারে পুনরাবৃত্তিযোগ্য , তবে পদ্ধতিটি যদি পুচ্ছ-পুনরাবৃত্তি না করে তবে সংকলক আপনাকে সতর্ক করবে। এটি @tailrec
কোনও পদ্ধতি বর্তমানে অনুকূলিত হওয়ার যোগ্য এবং এটি সংশোধিত হওয়ার সাথে সাথে এটি অপ্টিমাইজযোগ্য থেকে যায় তা উভয়ই নিশ্চিত করে তা টীকাটিকে একটি ভাল ধারণা করে তোলে ।
নোট করুন যে স্ক্যালাল কোনও পদ্ধতিকে পুচ্ছ-পুনরাবৃত্ত হিসাবে বিবেচনা করে না যদি এটি ওভাররাইড করা যায়। সুতরাং পদ্ধতিটি অবশ্যই ব্যক্তিগত, চূড়ান্ত, কোনও বস্তুর (শ্রেণি বা বৈশিষ্ট্যের বিপরীতে) হতে হবে, বা অন্য পদ্ধতির অভ্যন্তরে অনুকূলিত হতে হবে।
টীকাটি হ'ল scala.annotation.tailrec
। পদ্ধতিটি টেল কলটি অনুকূলিত করা যায় না, যদি এটি একটি সংকলক ত্রুটি ট্রিগার করে, যা ঘটে যদি:
এটি def
একটি পদ্ধতির সংজ্ঞায়নের ঠিক আগে স্থাপন করা হয়েছিল । এটি আরপিএলে কাজ করে।
এখানে আমরা টীকাটি আমদানি করি এবং কোনও পদ্ধতি হিসাবে চিহ্নিত করার চেষ্টা করি @tailrec
।
scala> import annotation.tailrec
import annotation.tailrec
scala> @tailrec def length(as: List[_]): Int = as match {
| case Nil => 0
| case head :: tail => 1 + length(tail)
| }
<console>:7: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
@tailrec def length(as: List[_]): Int = as match {
^
উফফফফ! শেষ প্রার্থনা হয় 1.+()
, না length()
! আসুন পদ্ধতিটি সংস্কার করুন:
scala> def length(as: List[_]): Int = {
| @tailrec def length0(as: List[_], tally: Int = 0): Int = as match {
| case Nil => tally
| case head :: tail => length0(tail, tally + 1)
| }
| length0(as)
| }
length: (as: List[_])Int
নোটটি length0
স্বয়ংক্রিয়ভাবে ব্যক্তিগত কারণ এটি অন্য পদ্ধতির স্কোপে সংজ্ঞায়িত করা হয়েছে।
override
জাভাতে টীকাগুলির মতো - কোডটি এটি ছাড়াই কাজ করে, তবে আপনি যদি এটি সেখানে রাখেন তবে এটি আপনাকে বলে যে আপনি কোনও ভুল করেছেন কিনা।