পার্থক্য কি:
def even: Int => Boolean = _ % 2 == 0
এবং
val even: Int => Boolean = _ % 2 == 0
উভয়কেই বলা যেতে পারে even(10)
।
পার্থক্য কি:
def even: Int => Boolean = _ % 2 == 0
এবং
val even: Int => Boolean = _ % 2 == 0
উভয়কেই বলা যেতে পারে even(10)
।
উত্তর:
পদ্ধতি def even
কলটিতে মূল্যায়ন করে এবং প্রতিবার নতুন ফাংশন তৈরি করে (এর নতুন উদাহরণ Function1
)।
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
সঙ্গে def
আপনি প্রতি কলের নতুন ফাংশন পেতে পারেন:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val
সংজ্ঞায়িত হলে মূল্যায়ন, def
- যখন ডাকা হয়:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
মনে রাখবেন যে তৃতীয় বিকল্প যে: lazy val
।
এটি যখন প্রথমবার বলা হয় তা মূল্যায়ন করে:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
তবে FunctionN
প্রতিবার একই ফলাফল (একই ক্ষেত্রে একই ক্ষেত্রে ) ফেরত দেয় :
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
কর্মক্ষমতা
val
সংজ্ঞায়িত হলে মূল্যায়ন।
def
প্রতিটি কলের মূল্যায়ন করে, তাই val
একাধিক কল করার চেয়ে কার্য সম্পাদন আরও খারাপ হতে পারে । আপনি একক কল দিয়ে একই কর্মক্ষমতা পাবেন। এবং কোনও কল ছাড়াই আপনি কোনও ওভারহেড পাবেন না def
, তাই আপনি এটি কয়েকটি সংখ্যক শাখায় ব্যবহার না করলেও আপনি এটি সংজ্ঞায়িত করতে পারেন।
একটি দিয়ে lazy val
আপনি একটি অলস মূল্যায়ন পাবেন: আপনি এটি কয়েকটি শাখায় ব্যবহার না করলেও আপনি এটি সংজ্ঞায়িত করতে পারেন এবং এটি একবার বা কখনই মূল্যায়ন করে না, তবে আপনার প্রতিটি অ্যাক্সেসে ডাবল চেক লকিং থেকে আপনি একটি সামান্য ওভারহেড পাবেন lazy val
।
@ সার্জবর্চ উল্লেখ করেছেন যে আপনি পদ্ধতিটি সংজ্ঞায়িত করতে পারেন এবং এটি দ্রুততম বিকল্প:
def even(i: Int): Boolean = i % 2 == 0
তবে আপনার যদি ফাংশন রচনাটির জন্য বা উচ্চতর অর্ডার ফাংশনগুলির (যেমন filter(even)
) সংকলকটির জন্য কোনও ফাংশন (পদ্ধতি নয়) প্রয়োজন হয় তবে আপনি যখনই এটি ফাংশন হিসাবে ব্যবহার করছেন তখন আপনার পদ্ধতি থেকে কোনও ফাংশন তৈরি করবে, সুতরাং পারফরম্যান্সের তুলনায় কিছুটা খারাপ হতে পারে val
।
even
ডাকা হয় ফাংশন মূল্যায়ন করা কি গুরুত্বপূর্ণ নয় ?
def
কোনও পদ্ধতি নির্ধারণ করতে ব্যবহার করা যেতে পারে এবং এটি দ্রুততম বিকল্প। @ এ কারিমি
even eq even
,।
@inline
বৈশিষ্ট্য রয়েছে । তবে এটি ফাংশনগুলিকে ইনলাইন করতে পারে না কারণ ফাংশন কল apply
কোনও ফাংশন অবজেক্টের ভার্চুয়াল পদ্ধতিতে কল । জেভিএম কিছু পরিস্থিতিতে এই জাতীয় কলগুলিকে অনুগ্রহ ও ইনলাইন করতে পারে, তবে সাধারণভাবে নয়।
এই বিবেচনা:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
আপনি পার্থক্য দেখতে পান কি? সংক্ষেপে:
Def : প্রতিটি কল করার জন্য even
, এটি even
আবার পদ্ধতির বডিটিকে কল করে । কিন্তু even2
অর্থাত Val , ফাংশন শুধুমাত্র একবার যখন ঘোষণা (এবং অত: পর এটা ছাপে সক্রিয়া করা হয় val
লাইন 4 এবং কখনও) এবং একই আউটপুট প্রতিবার এটি অ্যাক্সেস ব্যবহার করা হয়। উদাহরণস্বরূপ এটি করার চেষ্টা করুন:
scala> import scala.util.Random
import scala.util.Random
scala> val x = { Random.nextInt }
x: Int = -1307706866
scala> x
res0: Int = -1307706866
scala> x
res1: Int = -1307706866
যখন x
আরম্ভ করা হয়, তখন ফিরে আসা মানটির Random.nextInt
চূড়ান্ত মান হিসাবে সেট করা হয় x
। পরবর্তী সময় x
আবার ব্যবহার করা হয়, এটি সর্বদা একই মান প্রদান করবে।
আপনি অলসভাবে আরম্ভ করতে পারেন x
। অর্থাত্ প্রথমবার এটি ব্যবহৃত হয় এটি আরম্ভ করা হয় এবং ঘোষণার সময় নয়। উদাহরণ স্বরূপ:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
even2
একবার 1
এবং একবার সাথে দু'বার কল করার চেষ্টা করুন 2
। প্রতিটি কলে আপনি বিভিন্ন উত্তর পাবেন। সুতরাং, println
পরবর্তী কলগুলিতে মৃত্যুদন্ড কার্যকর না করা অবস্থায় আপনি বিভিন্ন কল থেকে একই ফলাফল পাবেন না even2
। কেন println
পুনরায় মৃত্যুদণ্ড কার্যকর করা হবে না, এটি একটি আলাদা প্রশ্ন।
এটা দেখ:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
আশ্চর্যজনকভাবে, এটি 9 টি নয় 4 টি মুদ্রণ করবে! ভাল (এমনকি ভ্যার) অবিলম্বে মূল্যায়ন করে নির্ধারিত হয়।
এখন ডিএফ এ ভাল পরিবর্তন করুন .. এটি 9 মুদ্রণ করবে! Def একটি ফাংশন কল .. এটি যতবার ডাকে ততবার এটি মূল্যায়ন করবে।
ভাল অর্থাত্ "বর্গ" স্কালার সংজ্ঞা দ্বারা স্থির হয়। এটি ঘোষণার ঠিক সময়ে মূল্যায়ন করা হয়, আপনি পরে পরিবর্তন করতে পারবেন না। অন্যান্য উদাহরণগুলিতে, যেখানে এমনকি 2 টিও ভাল, তবে এটি ফাংশন স্বাক্ষর হিসাবে ঘোষিত হয়েছে "(Int => বুলিয়ান)", সুতরাং এটি কোনও প্রকারের নয়। এটি একটি ফাংশন এবং এর মানটি নিম্নোক্ত অভিব্যক্তি দ্বারা সেট করা হয়
{
println("val");
(x => x % 2 == 0)
}
স্কালা ভাল সম্পত্তি হিসাবে, আপনি বর্গ হিসাবে একই নিয়ম এমনকি 2, অন্য ফাংশন বরাদ্দ করতে পারবেন না।
কেন eval2 ভাল ফাংশন কল করে বার বার "ভাল" মুদ্রণ করা হচ্ছে না?
মূল কোড:
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
আমরা জানি, স্কালায় উপরের ধরণের প্রকাশের শেষ বিবৃতিটি (ভিতরে {..}}) আসলে বাম দিকে ফিরে আসে। সুতরাং আপনি এমনকি "x => x% 2 == 0" ফাংশনে সেট করে শেষ করেন যা আপনি 2 ধরণের জন্য যেমন ঘোষিত টাইপের সাথে মেলে (অর্থাত্>> বুলিয়ান), তাই সংকলক খুশি। এখন এমনকি 2 কেবল "(x => x% 2 == 0)" ফাংশনটির দিকে নির্দেশ করে (প্রিন্টলান ("ভাল") এর আগে অন্য কোনও বিবৃতি নয়) ইত্যাদি। বিভিন্ন পরামিতির সাথে ইভেন্ট 2 চালানো আসলে "(x => x% 2) কে আহ্বান করবে == 0) "কোড, কেবলমাত্র ইভেন্ট 2 দিয়ে সেভ করা আছে।
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
এই আরও স্পষ্ট করতে, নিম্নলিখিত কোডের বিভিন্ন সংস্করণ নিম্নলিখিত।
scala> val even2: (Int => Boolean) = {
| println("val");
| (x => {
| println("inside final fn")
| x % 2 == 0
| })
| }
কি হবে ? আপনি যখন এমনকি 2 () কল করেন তখন এখানে আমরা বারবার প্রিন্টেড "ফাইনাল এফএন" দেখতে পাই।
scala> even2(3)
inside final fn
res9: Boolean = false
scala> even2(2)
inside final fn
res10: Boolean = true
scala>
যেমন একটি সংজ্ঞা কার্যকর করা def x = e
এক্সপ্রেশন মূল্যায়ন করবে না। স্থির ই এর মূল্যায়ন যখনই এক্স করা হয়।
বিকল্পভাবে, স্কালা একটি মান সংজ্ঞা সরবরাহ করে val x = e
, যা সংজ্ঞাটির
মূল্যায়নের অংশ হিসাবে ডান-হাতের মূল্যায়ন করে। যদি পরবর্তীকালে x ব্যবহার করা হয়, তবে এটি তাত্ক্ষণিক ই এর প্রাক-গণিত মান দ্বারা প্রতিস্থাপিত হবে, যাতে এক্সপ্রেশনটি আবার মূল্যায়নের প্রয়োজন হয় না।
এছাড়াও, ভ্যালু মূল্য মূল্যায়ন। যার অর্থ ডান দিকের অভিব্যক্তি সংজ্ঞা চলাকালীন মূল্যায়ন করা হয়। যেখানে নাম মূল্যায়ন দ্বারা Def হয়। এটি ব্যবহার না করা পর্যন্ত এটি মূল্যায়ন করবে না।
উপরের সহায়ক জবাব ছাড়াও, আমার অনুসন্ধানগুলি হ'ল:
def test1: Int => Int = {
x => x
}
--test1: test1[] => Int => Int
def test2(): Int => Int = {
x => x+1
}
--test2: test2[]() => Int => Int
def test3(): Int = 4
--test3: test3[]() => Int
উপরেরটি দেখায় যে "ডিএফ" হ'ল একটি পদ্ধতি (শূন্য আর্গুমেন্ট প্যারামিটার সহ) যা অনুরোধ করা হলে "ফাংশন"> ইনট => ইনট "প্রদান করে।
কার্যসমূহে পদ্ধতির রূপান্তরটি এখানে ভালভাবে ব্যাখ্যা করা হয়েছে: https://tpolecat.github.io/2014/06/09/ স্মরণার্থী- ফাংশনস html
REPL এ,
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292@57a0aeb8
ডিএফ মানে call-by-name
, চাহিদার উপর মূল্যায়ন
ভাল মানে call-by-value
, আরম্ভের সময় মূল্যায়ন করা
Int => Boolean
মানে কি ? আমি মনে করিdef foo(bar: Baz): Bin = expr