ফাংশন (ECMAScript)
আপনার যা দরকার তা হ'ল ফাংশন সংজ্ঞা এবং ফাংশন কল। আপনার কোনও শাখা-প্রশাখা, শর্তসাপেক্ষ, অপারেটর বা বিল্টিন ফাংশন দরকার নেই। আমি ECMAScript ব্যবহার করে একটি বাস্তবায়ন প্রদর্শন করব।
প্রথমে, বলা হয় দুটি ফাংশন সংজ্ঞায়িত করি true
এবং false
। আমরা তাদের যেভাবে চাই সেগুলি সংজ্ঞায়িত করতে পারি, তারা সম্পূর্ণ স্বেচ্ছাচারী, তবে আমরা তাদের একটি বিশেষ পদ্ধতিতে সংজ্ঞায়িত করব যার কিছু সুবিধা রয়েছে যা আমরা পরে দেখব:
const tru = (thn, _ ) => thn,
fls = (_ , els) => els;
tru
দুটি পরামিতি সহ একটি ফাংশন যা কেবল এটির দ্বিতীয় যুক্তি উপেক্ষা করে এবং প্রথমটি প্রদান করে। fls
এটি দুটি পরামিতি সহ একটি ফাংশন যা কেবল তার প্রথম যুক্তি উপেক্ষা করে এবং দ্বিতীয়টি প্রদান করে।
কেন আমরা এনকোড হয়নি tru
এবং fls
এই ভাবে? ভাল, এইভাবে, দুটি ফাংশন কেবল দুটি ধারণারই প্রতিনিধিত্ব করে না true
এবং false
না, একই সাথে তারা "পছন্দ" ধারণাটিও উপস্থাপন করে, অন্য কথায়, তারাও একটি if
/ then
/ else
অভিব্যক্তি! আমরা if
শর্তটি মূল্যায়ন করি এবং এটি then
ব্লক এবং else
ব্লকটিকে আর্গুমেন্ট হিসাবে পাস করি । যদি শর্তটি মূল্যায়ন করে তবে এটি ব্লকটি tru
ফিরিয়ে দেবে then
, যদি এটি মূল্যায়ন করে তবে এটি ব্লকটি fls
ফিরিয়ে দেবে else
। এখানে একটি উদাহরণ:
tru(23, 42);
// => 23
এটি ফিরে আসে 23
এবং এটি:
fls(23, 42);
// => 42
42
আপনি প্রত্যাশা যেমন প্রত্যাবর্তন ।
একটি বলি আছে তবে:
tru(console.log("then branch"), console.log("else branch"));
// then branch
// else branch
এই ছাপে উভয় then branch
এবং else branch
! কেন?
ওয়েল, এটা ফেরৎ প্রথম আর্গুমেন্ট ফেরত মান, কিন্তু এটা মূল্যায়ন উভয় আর্গুমেন্ট, যেহেতু এর নাম ECMAScript কঠোর এবং সবসময় ফাংশন কল করার আগে ফাংশন সব আর্গুমেন্ট মূল্যায়ন করে। আইওডাব্লু: এটি প্রথম যুক্তির মূল্যায়ন করে যা কোনটি console.log("then branch")
, যা সহজেই ফিরে আসে undefined
এবং then branch
কনসোলে মুদ্রণের পার্শ্ব-প্রতিক্রিয়া রাখে এবং এটি দ্বিতীয় যুক্তির মূল্যায়ন করে, যা undefined
পার্শ্ব-প্রতিক্রিয়া হিসাবে কনসোলটিতে ফিরে আসে এবং মুদ্রণ করে। তারপরে, এটি প্রথমটি ফেরত দেয় undefined
।
Λ-ক্যালকুলাসে, যেখানে এই এনকোডিংটি আবিষ্কার হয়েছিল, এটি কোনও সমস্যা নয়: λ-ক্যালকুলাস খাঁটি , যার অর্থ এটির কোনও পার্শ্ব-প্রতিক্রিয়া নেই; সুতরাং আপনি কখনই লক্ষ্য করবেন না যে দ্বিতীয় তর্কটিও মূল্যায়ন হয় gets এছাড়াও, λ-ক্যালকুলাসটি অলস (বা কমপক্ষে, এটি প্রায়শই সাধারণ ক্রমের অধীনে মূল্যায়ন করা হয়), অর্থাত্ এটি আসলে যুক্তিগুলির মূল্যায়ন করে না যা প্রয়োজন হয় না। সুতরাং, আইওডাব্লু: λ-ক্যালকুলাসে দ্বিতীয় তর্কটি কখনই মূল্যায়ন করা হবে না এবং যদি এটি হয় তবে আমরা লক্ষ্য করব না।
ECMAScript অবশ্য কঠোর , অর্থাত্ এটি সর্বদা সমস্ত যুক্তির মূল্যায়ন করে। ভাল, আসলে, সর্বদা নয়: উদাহরণস্বরূপ, if
/ then
/ else
, শুধুমাত্র then
শর্তটি থাকলে শাখার মূল্যায়ন করে এবং শর্তটি থাকলে true
কেবল else
শাখার মূল্যায়ন করে false
। এবং আমরা আমাদের সাথে এই আচরণটি প্রতিলিপি করতে চাই iff
। ধন্যবাদ, যদিও ECMAScript অলস নয়, কোডের একটি অংশের মূল্যায়ন বিলম্ব করার একটি উপায় রয়েছে, প্রায় প্রতিটি ভাষা প্রায় একইভাবে করে: একটি ফাংশন এ এটিকে মোড়ানো, এবং আপনি যদি সেই ফাংশনটিকে কখনও কল করেন না, কোডটি হবে কখনও মৃত্যুদন্ড কার্যকর করা হবে না।
সুতরাং, আমরা একটি ফাংশন উভয় ব্লক মোড়ানো, এবং শেষে ফাংশন ফিরে যে কল:
tru(() => console.log("then branch"), () => console.log("else branch"))();
// then branch
প্রিন্ট then branch
এবং
fls(() => console.log("then branch"), () => console.log("else branch"))();
// else branch
কপি করে প্রিন্ট else branch
।
আমরা traditionalতিহ্যগত if
/ then
/ else
এইভাবে প্রয়োগ করতে পারি :
const iff = (cnd, thn, els) => cnd(thn, els);
iff(tru, 23, 42);
// => 23
iff(fls, 23, 42);
// => 42
আবার, উপরে যেমন একই কারণে iff
ফাংশন এবং অতিরিক্ত ফাংশন কল বন্ধনীগুলির সংজ্ঞায় কল করার সময় আমাদের কিছু অতিরিক্ত ফাংশন মোড়ানো প্রয়োজন iff
:
const iff = (cnd, thn, els) => cnd(thn, els)();
iff(tru, () => console.log("then branch"), () => console.log("else branch"));
// then branch
iff(fls, () => console.log("then branch"), () => console.log("else branch"));
// else branch
এখন যে আমাদের দুটি সংজ্ঞা রয়েছে, আমরা তা প্রয়োগ করতে পারি or
। প্রথমত, আমরা এর জন্য সত্যের টেবিলটি দেখি or
: যদি প্রথম অপারেন্ড সত্যবাদী হয়, তবে প্রকাশের ফলাফলটি প্রথম অপারেন্ডের মতোই। অন্যথায়, প্রকাশের ফলাফলটি দ্বিতীয় অপারেন্ডের ফলাফল। সংক্ষেপে: প্রথম অপারেন্ডটি যদি হয় তবে true
আমরা প্রথম অপারেন্ডটি ফিরিয়ে দেব, অন্যথায় আমরা দ্বিতীয় অপারেন্ডটি ফিরিয়ে দিই:
const orr = (a, b) => iff(a, () => a, () => b);
আসুন এটি পরীক্ষা করে দেখুন:
orr(tru,tru);
// => tru(thn, _) {}
orr(tru,fls);
// => tru(thn, _) {}
orr(fls,tru);
// => tru(thn, _) {}
orr(fls,fls);
// => fls(_, els) {}
গ্রেট! তবে, এই সংজ্ঞাটি দেখতে কিছুটা কুৎসিত দেখাচ্ছে। মনে রাখবেন, tru
এবং fls
ইতিমধ্যে সমস্ত নিজেরাই কন্ডিশনার মতো কাজ করুন, সুতরাং সত্যই প্রয়োজন নেই iff
এবং এইভাবে সমস্ত ফাংশন মোড়ানো:
const orr = (a, b) => a(a, b);
সেখানে আপনার এটি রয়েছে: or
(প্লাস অন্যান্য বুলিয়ান অপারেটর) কেবলমাত্র কয়েকটি মুখ্য লাইনে ফাংশন সংজ্ঞা এবং ফাংশন কল ছাড়া কিছুই সংজ্ঞায়িত:
const tru = (thn, _ ) => thn,
fls = (_ , els) => els,
orr = (a , b ) => a(a, b),
nnd = (a , b ) => a(b, a),
ntt = a => a(fls, tru),
xor = (a , b ) => a(ntt(b), b),
iff = (cnd, thn, els) => cnd(thn, els)();
দুর্ভাগ্যক্রমে, এই বাস্তবায়নটি বরং অকেজো: ECMAScript তে কোনও ফাংশন বা অপারেটর নেই যা ফিরে আসে tru
বা fls
, তারা সবাই ফিরে আসে true
বা false
, সুতরাং আমরা এগুলিকে আমাদের ফাংশন দিয়ে ব্যবহার করতে পারি না। তবে এখনও আমরা অনেক কিছু করতে পারি। উদাহরণস্বরূপ, এটি একক সংযুক্ত তালিকার একটি বাস্তবায়ন:
const cons = (hd, tl) => which => which(hd, tl),
car = l => l(tru),
cdr = l => l(fls);
অবজেক্টস (স্কেলা)
আপনি অদ্ভুত কিছু লক্ষ্য করেছেন: tru
এবং fls
একটি দ্বিগুণ ভূমিকা পালন করুন, তারা উভয়ই ডেটা মান হিসাবে true
এবং false
একই সাথে, তারা শর্তযুক্ত অভিব্যক্তি হিসাবেও কাজ করে। এগুলি হ'ল ডেটা এবং আচরণ , একের মধ্যে একত্রিত হয়ে ... উহম… "জিনিস" ... বা (আমি সাহস করে বলতে পারি) অবজেক্ট !
প্রকৃতপক্ষে, tru
এবং fls
বস্তু হয়। এবং আপনি যদি কখনও স্মলটালক, সেল্ফ, নিউজপেইক বা অন্যান্য অবজেক্ট-ভিত্তিক ভাষা ব্যবহার করেন তবে আপনি খেয়াল করবেন যে তারা বুলিয়ানগুলি ঠিক একইভাবে প্রয়োগ করে। আমি এখানে স্কালায় এ জাতীয় বাস্তবায়ন প্রদর্শন করব:
sealed abstract trait Buul {
def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): T
def &&&(other: ⇒ Buul): Buul
def |||(other: ⇒ Buul): Buul
def ntt: Buul
}
case object Tru extends Buul {
override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): U = thn
override def &&&(other: ⇒ Buul) = other
override def |||(other: ⇒ Buul): this.type = this
override def ntt = Fls
}
case object Fls extends Buul {
override def apply[T, U <: T, V <: T](thn: ⇒ U)(els: ⇒ V): V = els
override def &&&(other: ⇒ Buul): this.type = this
override def |||(other: ⇒ Buul) = other
override def ntt = Tru
}
object BuulExtension {
import scala.language.implicitConversions
implicit def boolean2Buul(b: ⇒ Boolean) = if (b) Tru else Fls
}
import BuulExtension._
(2 < 3) { println("2 is less than 3") } { println("2 is greater than 3") }
// 2 is less than 3
এই বিটিডাব্লু হ'ল পলিমারফিজমের সাথে শর্তসাপেক্ষে প্রতিস্থাপন রিফ্যাক্টরিং সর্বদা কাজ করে: আপনি আপনার প্রোগ্রামের সর্বদা যে কোনও এবং শর্তসাপেক্ষে পলিমারফিক ম্যাসেজ প্রেরণের মাধ্যমে প্রতিস্থাপন করতে পারেন, কারণ আমরা যেমন দেখিয়েছি যে পলিমারফিক ম্যাসেজ প্রেরণা কেবলমাত্র প্রয়োগের মাধ্যমে শর্তাবলিকে প্রতিস্থাপন করতে পারে। স্মলটালক, সেল্ফ এবং নিউজসিয়াকের মতো ভাষাগুলি এর অস্তিত্বের প্রমাণ, কারণ সেই ভাষাগুলিতে শর্ত থাকে না। (তাদের কাছে পলিমারফিক ম্যাসেজ প্রেরণ ওরফে ভার্চুয়াল পদ্ধতি কল ব্যতীত লুপস, বিটিডাব্লু বা সত্যিই কোনও ভাষা অন্তর্নির্মিত নিয়ন্ত্রণ কাঠামো নেই))
প্যাটার্ন ম্যাচিং (হাস্কেল)
আপনি or
প্যাটার্ন ম্যাচিং বা হাস্কেলের আংশিক ফাংশন সংজ্ঞার মতো কিছু ব্যবহার করে সংজ্ঞাও দিতে পারেন:
True ||| _ = True
_ ||| b = b
অবশ্যই, প্যাটার্ন ম্যাচিং শর্তসাপেক্ষ কার্যকরকরণের একটি রূপ, তবে আবার, অবজেক্ট-ভিত্তিক বার্তা প্রেরণ।