উত্তর:
তাদের মধ্যে পার্থক্যটি হ'ল val
এটি যখন নির্ধারিত lazy val
হয় তখন এটি কার্যকর করা হয় এবং যখন প্রথমবার অ্যাক্সেস করা হয় তখন একটি কার্যকর করা হয়।
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13
একটি পদ্ধতির বিপরীতে (সংজ্ঞায়িত def
) এ lazy val
একবার কার্যকর করা হয় এবং তারপরে আর কখনও হয় না। এটি কার্যকর হতে পারে যখন কোনও অপারেশন সম্পূর্ণ হতে দীর্ঘ সময় নেয় এবং যখন এটি পরে ব্যবহৃত হয় তা নিশ্চিত না হয়।
scala> class X { val x = { Thread.sleep(2000); 15 } }
defined class X
scala> class Y { lazy val y = { Thread.sleep(2000); 13 } }
defined class Y
scala> new X
res5: X = X@262505b7 // we have to wait two seconds to the result
scala> new Y
res6: Y = Y@1555bd22 // this appears immediately
এখানে, যখন মানগুলি x
এবং y
কখনই ব্যবহৃত হয় না, কেবল x
অকারণে সম্পদ নষ্ট করে। যদি আমরা মনে করি y
এর কোনও পার্শ্ব প্রতিক্রিয়া নেই এবং এটি যে কতবার অ্যাক্সেস করা হয় তা আমরা জানি না (কখনই, একবারও হাজার বার নয়) এটি হিসাবে ঘোষণা করা অযথাdef
যেহেতু আমরা বেশ কয়েকবার এটি কার্যকর করতে চাই না তা ।
আপনি কীভাবে lazy vals
বাস্তবায়ন হয় তা জানতে চাইলে এই প্রশ্নটি দেখুন ।
Lazy<T>
নেট মধ্যে তুলনা করুন
এই বৈশিষ্ট্যটি কেবল ব্যয়বহুল গণনাগুলিতে বিলম্ব করতে সহায়তা করে না, তবে পারস্পরিক নির্ভরশীল বা চক্রীয় কাঠামোগত গঠনেও কার্যকর। যেমন এটি স্ট্যাকের ওভারফ্লোতে বাড়ে:
trait Foo { val foo: Foo }
case class Fee extends Foo { val foo = Faa() }
case class Faa extends Foo { val foo = Fee() }
println(Fee().foo)
//StackOverflowException
তবে অলস ভ্যালস দিয়ে এটি ভাল কাজ করে
trait Foo { val foo: Foo }
case class Fee extends Foo { lazy val foo = Faa() }
case class Faa extends Foo { lazy val foo = Fee() }
println(Fee().foo)
//Faa()
আমি বুঝতে পারি যে উত্তরটি দেওয়া হয়েছে তবে আমি আমার মতো নতুনদের পক্ষে এটি সহজ করে বোঝার জন্য একটি সহজ উদাহরণ লিখেছিলাম:
var x = { println("x"); 15 }
lazy val y = { println("y"); x+1 }
println("-----")
x = 17
println("y is: " + y)
উপরের কোডের আউটপুট হল:
x
-----
y
y is: 18
যেমনটি দেখা যায়, এটি প্রারম্ভিক হওয়ার সময় এক্স মুদ্রিত হয়, তবে একইভাবে আরম্ভ করা হলে y প্রিন্ট করা হয় না (আমি x ইচ্ছাকৃতভাবে বর্ণ হিসাবে এখানে নিয়েছি - y কখন আরম্ভ হয় তা ব্যাখ্যা করার জন্য)। এরপরে যখন y বলা হবে, এটি আরম্ভের পাশাপাশি শেষ 'x' এর মান বিবেচনা করা হবে তবে পুরানোটি নয়।
আশাকরি এটা সাহায্য করবে.
একটি অলস ভ্যালটি " মেমোইজড (নো- আরগ ) ডিএফ " হিসাবে সহজেই বোঝা যায় ।
একটি ডিএফের মতো, অলস ভালটি চালিত না হওয়া পর্যন্ত মূল্যায়ন করা হয় না। তবে ফলাফলটি সংরক্ষণ করা হয় যাতে পরবর্তী অনুরোধগুলি সংরক্ষিত মানটি ফেরত দেয়। স্মৃতিযুক্ত ফলাফলটি আপনার ডেটা কাঠামোতে একটি ভালকের মতো স্থান গ্রহণ করে।
অন্যরা যেমন বলেছে, অলস ভ্যালের ব্যবহারের ক্ষেত্রে ব্যয়বহুল গণনাগুলি প্রয়োজন হয় না হওয়া পর্যন্ত তাদের ফলাফলগুলি সংরক্ষণ করা এবং মানগুলির মধ্যে নির্দিষ্ট বিজ্ঞপ্তি নির্ভরতা সমাধান করা expensive
অলস ভ্যালস প্রকৃতপক্ষে কমবেশি স্মৃতিবদ্ধ ডিফল্ট হিসাবে প্রয়োগ করা হয়। আপনি তাদের প্রয়োগের বিশদ সম্পর্কে এখানে পড়তে পারেন:
http://docs.scala-lang.org/sips/pending/improved-lazy-val-initialization.html
এছাড়াও lazy
নিম্নলিখিত কোড হিসাবে, আবর্তনশীল নির্ভরতা ছাড়া দরকারী হল:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { val x = "Hello" }
Y
অ্যাক্সেস Y
এখন নাল পয়েন্টার ব্যতিক্রম নিক্ষেপ করবে, কারণ x
এটি এখনও আরম্ভ করা হয়নি। নিম্নলিখিতটি ঠিকঠাকভাবে কাজ করে:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { lazy val x = "Hello" }
Y
সম্পাদনা: নিম্নলিখিতগুলিও কাজ করবে:
object Y extends { val x = "Hello" } with X
একে বলা হয় "প্রাথমিক শুরুর দিকে"। দেখুন এই তাই প্রশ্ন আরো বিস্তারিত জানার জন্য।
lazy
উপরের সংজ্ঞায়িত হিসাবে - এর একটি প্রদর্শন - অ্যাক্সেসের সময় বনাম কার্যকরকরণ নির্ধারিত হলে কার্যকর করা: (2.12.7 স্কেল শেল ব্যবহার করে)
// compiler says this is ok when it is lazy
scala> lazy val t: Int = t
t: Int = <lazy>
//however when executed, t recursively calls itself, and causes a StackOverflowError
scala> t
java.lang.StackOverflowError
...
// when the t is initialized to itself un-lazily, the compiler warns you of the recursive call
scala> val t: Int = t
<console>:12: warning: value t does nothing other than call itself recursively
val t: Int = t
scala> lazy val lazyEight = {
| println("I am lazy !")
| 8
| }
lazyEight: Int = <lazy>
scala> lazyEight
I am lazy !
res1: Int = 8