ফাংশনাল প্রোগ্রামিং সংজ্ঞা
দ্য জয় অফ ক্লোজারের সাথে পরিচয় করিয়ে দিয়েছিলেন :
ফাংশনাল প্রোগ্রামিং এমন একটি কম্পিউটিং শর্ত যা একটি নিরাকার সংজ্ঞা আছে। আপনি যদি 100 প্রোগ্রামারকে তাদের সংজ্ঞার জন্য জিজ্ঞাসা করেন তবে আপনি সম্ভবত 100 টি বিভিন্ন উত্তর পাবেন ...
ক্রিয়ামূলক প্রোগ্রামিং উদ্ভাবন করে এবং ফাংশনগুলির সংযোজন এবং প্রয়োগের সুবিধার্থে ... কোনও ভাষা কার্যকরী বিবেচনা করার জন্য, তার কার্যকারিতাটির ধারণাটি অবশ্যই প্রথম শ্রেণির হতে হবে। প্রথম শ্রেণীর ফাংশনগুলি সংরক্ষণ করা, পাস এবং ডেটা যেমন অন্য কোনও অংশের মতো ফিরে আসতে পারে। এই মূল ধারণার বাইরে, [এফপির সংজ্ঞাগুলিতে অন্তর্ভুক্ত থাকতে পারে] বিশুদ্ধতা, অপরিবর্তনীয়তা, পুনরাবৃত্তি, আলস্যতা এবং প্রাসঙ্গিক স্বচ্ছতা।
স্কালার দ্বিতীয় সংস্করণে প্রোগ্রামিং পি। 10 এর নিম্নলিখিত সংজ্ঞা রয়েছে:
কার্যকরী প্রোগ্রামিং দুটি প্রধান ধারণা দ্বারা পরিচালিত হয়। প্রথম ধারণাটি হ'ল ফাংশনগুলি হ'ল প্রথম শ্রেণীর মান ... আপনি অন্যান্য ক্রিয়াকলাপগুলিতে যুক্তি হিসাবে ফাংশনগুলি পাস করতে পারেন, ফাংশন থেকে ফলাফল হিসাবে তাদের ফিরিয়ে দিতে পারেন বা এগুলি ভেরিয়েবলে সঞ্চয় করতে পারেন ...
ফাংশনাল প্রোগ্রামিংয়ের দ্বিতীয় প্রধান ধারণাটি হ'ল কোনও প্রোগ্রামের ক্রিয়াকলাপগুলিতে ডাটা পরিবর্তনের পরিবর্তে আউটপুট মানগুলিতে ম্যাপ করা উচিত।
যদি আমরা প্রথম সংজ্ঞা গ্রহণ করি, তবে আপনার কোডটিকে "কার্যকরী" করার জন্য আপনার কেবলমাত্র লুপগুলি ভিতরে আউট করা উচিত। দ্বিতীয় সংজ্ঞায় অপরিবর্তনীয়তা অন্তর্ভুক্ত।
প্রথম শ্রেণির কার্যাদি
কল্পনা করুন যে আপনি বর্তমানে আপনার বাসের অবজেক্ট থেকে যাত্রীদের একটি তালিকা পেয়েছেন এবং প্রতিটি যাত্রীর ব্যাংক অ্যাকাউন্টে বাসের পরিমাণ কমিয়ে হ্রাস করার বিষয়ে আপনি পুনরাবৃত্তি করছেন। এই একই ক্রিয়াটি সম্পাদন করার কার্যকরী উপায়টি হ'ল বাসে একটি পদ্ধতি থাকতে পারে, যাকে ফোরএচপ্যাসেঞ্জার বলা হয় যা একটি যুক্তির ফাংশন নেয় takes তারপরে বাসটি তার যাত্রীদের উপরে পুনরাবৃত্তি করবে তবে এটি সর্বোত্তমভাবে সম্পন্ন হয়েছে এবং আপনার ক্লায়েন্ট কোড যা যাত্রার জন্য ভাড়া আদায় করে তা কোনও ফাংশনে রাখা হবে এবং প্রতিটি যাত্রীর জন্য প্রেরণ করা হবে। ভাল খবর! আপনি কার্যকরী প্রোগ্রামিং ব্যবহার করছেন।
অনুজ্ঞাসূচক:
for (Passenger p : Bus.getPassengers()) {
p.debit(fare);
}
কার্যকরী (স্কালায় একটি বেনাম ফাংশন বা "ল্যাম্বদা" ব্যবহার করে):
myBus = myBus.forEachPassenger(p:Passenger -> { p.debit(fare) })
আরও চিনিযুক্ত স্কেল সংস্করণ:
myBus = myBus.forEachPassenger(_.debit(fare))
প্রথম-শ্রেণীর ক্রিয়াকলাপ
যদি আপনার ভাষা প্রথম শ্রেণির ফাংশনগুলি সমর্থন করে না, তবে এটি খুব কুশ্রী হতে পারে। জাভা 7 বা তার আগে, আপনাকে "ফাংশনাল অবজেক্ট" ইন্টারফেসটি এইভাবে সরবরাহ করতে হবে:
// Java 8 has java.util.function.Consumer, but in earlier
// versions you have to roll your own:
public interface Consumer<T> {
public void accept(T t);
}
তারপরে বাস শ্রেণি একটি অভ্যন্তরীণ পুনরুক্তি সরবরাহ করে:
public void forEachPassenger(Consumer<Passenger> c) {
for (Passenger p : passengers) {
c.accept(p);
}
}
অবশেষে, আপনি একটি বেনাম ফাংশন অবজেক্টটি বাসে পাস করুন:
// Java 8 has syntactic sugar to make this look more like
// the Scala solution, but earlier versions require manually
// instantiating a "Function Object," in this case, a
// Consumer:
Bus.forEachPassenger(new Consumer<Passenger>() {
@Override
public void accept(final Passenger p) {
p.debit(fare);
}
}
জাভা 8 স্থানীয় ভেরিয়েবলগুলিকে একটি বেনামি ফাংশনের সুযোগ ক্যাপচার করার অনুমতি দেয় তবে পূর্ববর্তী সংস্করণগুলিতে, এই জাতীয় কোনও ভেরিয়েবল অবশ্যই চূড়ান্ত হিসাবে ঘোষণা করতে হবে। এটি পেতে আপনাকে একটি মিউটেবল রেফারেন্স রেপার ক্লাস করতে হবে। এখানে একটি পূর্ণসংখ্যা-নির্দিষ্ট শ্রেণি যা আপনাকে উপরের কোডটিতে একটি লুপ কাউন্টার যুক্ত করতে দেয়:
public static class MutableIntWrapper {
private int i;
private MutableIntWrapper(int in) { i = in; }
public static MutableIntWrapper ofZero() {
return new MutableIntWrapper(0);
}
public int value() { return i; }
public void increment() { i++; }
}
final MutableIntWrapper count = MutableIntWrapper.ofZero();
Bus.forEachPassenger(new Consumer<Passenger>() {
@Override
public void accept(final Passenger p) {
p.debit(fare);
count.increment();
}
}
System.out.println(count.value());
এমনকি এই কদর্যতা সহ, কখনও কখনও কোনও অভ্যন্তরীণ পুনরুক্তি সরবরাহ করে আপনার প্রোগ্রাম জুড়ে ছড়িয়ে পড়া লুপগুলি থেকে জটিল এবং পুনরাবৃত্তি যুক্তিগুলি সরিয়ে ফেলা কখনও কখনও উপকারী।
এই কদর্যতা জাভা 8-এ স্থির করা হয়েছে, তবে প্রথম শ্রেণির ফাংশনের অভ্যন্তরে পরীক্ষিত ব্যতিক্রমগুলি পরিচালনা করা এখনও সত্যই খারাপ এবং জাভা এখনও তার সমস্ত সংগ্রহগুলিতে পরিবর্তনের অনুমান বহন করে। যা আমাদের প্রায়শই এফপির সাথে যুক্ত অন্যান্য লক্ষ্যে নিয়ে আসে:
অপরিবর্তনীয়তা
জোশ ব্লচের আইটেম 13 হ'ল অপরিবর্তনীয়তা পছন্দ করুন। বিপরীতে সাধারণ ট্র্যাশের কথা বলা সত্ত্বেও, ওওপি অপরিবর্তনীয় জিনিসগুলির সাথে করা যেতে পারে এবং এটি করা এটি আরও ভাল করে তোলে। উদাহরণস্বরূপ, জাভা স্ট্রিং অপরিবর্তনীয়। স্ট্রিংবফার, অপরিবর্তনীয় স্ট্রিং তৈরির জন্য ওটিওএইচকে পরিবর্তন করতে হবে। কিছু কাজ যেমন বাফারদের সাথে কাজ করার মতো অন্তর্নিহিত পরিবর্তন প্রয়োজন।
বিশুদ্ধতা
প্রতিটি ফাংশন কমপক্ষে স্মরণযোগ্য হওয়া উচিত - যদি আপনি এটি একই ইনপুট পরামিতিগুলি দেন (এবং এটির আসল যুক্তি ছাড়া কোনও ইনপুট না থাকা উচিত) তবে প্রতিবার বিশ্বব্যাপী রাষ্ট্র পরিবর্তনের মতো "পার্শ্ব প্রতিক্রিয়া" না ঘটানো, আমি সম্পাদন করে একই আউটপুট তৈরি করা উচিত / ও, বা ব্যতিক্রম ছোঁড়া।
এটি ফাংশনাল প্রোগ্রামিংয়ে বলা হয়েছে যে, "কাজ শেষ করার জন্য সাধারণত কিছু অশুভের প্রয়োজন হয়।" 100% বিশুদ্ধতা সাধারণত লক্ষ্য নয়। পার্শ্ব প্রতিক্রিয়া হ্রাস করা হয়।
উপসংহার
সত্যই, উপরের সমস্ত ধারণার মধ্যে, অপসারণযোগ্যতা আমার কোডটি সহজ করার জন্য ব্যবহারিক প্রয়োগগুলির ক্ষেত্রে সবচেয়ে বড় একক জয় O ওওপি, বা এফপি হোক। পুনরাবৃত্তির কাছে ফাংশনগুলি পাস করা দ্বিতীয় বৃহত্তম জয়। জাভা 8 Lambdas ডকুমেন্টেশন কেন শ্রেষ্ঠ ব্যাখ্যা হয়েছে। গাছগুলি প্রক্রিয়াজাতকরণের জন্য পুনরাবৃত্তি দুর্দান্ত। অলসতা আপনাকে অসীম সংগ্রহের সাথে কাজ করতে দেয়।
আপনি যদি জেভিএম পছন্দ করেন তবে আমি আপনাকে স্কেলা এবং ক্লোজুরে একবার দেখে নেওয়ার পরামর্শ দিই। উভয়ই ফাংশনাল প্রোগ্রামিংয়ের অন্তর্দৃষ্টিপূর্ণ ব্যাখ্যা। স্কলা কিছুটা সি-এর মতো সিনট্যাক্স সহ টাইপ-নিরাপদ, যদিও এটি হাস্কেলের সাথে সত্যিকারের সিটেক্সের সাথে সি এর মতোই সাধারণ সিনট্যাক্সের সাথে রয়েছে যদিও ক্লোজুর টাইপ-নিরাপদ নয় এবং এটি একটি লিস্প। আমি সম্প্রতি একটি নির্দিষ্ট রিফ্যাক্টরিং সমস্যার ক্ষেত্রে জাভা, স্কেলা এবং ক্লোজারের একটি তুলনা পোস্ট করেছি । গেম অফ লাইফ ব্যবহার করে লোগান ক্যাম্পবেলের তুলনাতে হাস্কেল এবং টাইপড ক্লোজারও অন্তর্ভুক্ত রয়েছে।
দ্রষ্টব্য
জিমি হোফা উল্লেখ করেছিলেন যে আমার বাসের ক্লাসটি পরিবর্তনযোগ্য। আসলটি সংশোধন করার পরিবর্তে, আমি মনে করি যে এটি এই ধরণের রিফ্যাক্টরিংয়ের ধরণেরটি প্রদর্শন করবে। বাসে প্রতিটি পদ্ধতিতে একটি নতুন বাস তৈরির জন্য কারখানা তৈরি করে, যাত্রীর প্রতিটি পদ্ধতিতে নতুন যাত্রী তৈরির কারখানা তৈরি করে এটি স্থির করা যায়। সুতরাং আমি সমস্ত কিছুর সাথে একটি রিটার্ন টাইপ যুক্ত করেছি যার অর্থ আমি জাভা 8 এর java.util.function.Function কপি করেছি কনজিউমার ইন্টারফেসের পরিবর্তে:
public interface Function<T,R> {
public R apply(T t);
// Note: I'm leaving out Java 8's compose() method here for simplicity
}
তারপরে বাসে:
public Bus mapPassengers(Function<Passenger,Passenger> c) {
// I have to use a mutable collection internally because Java
// does not have immutable collections that return modified copies
// of themselves the way the Clojure and Scala collections do.
List<Passenger> newPassengers = new ArrayList(passengers.size());
for (Passenger p : passengers) {
newPassengers.add(c.apply(p));
}
return Bus.of(driver, Collections.unmodifiableList(passengers));
}
শেষ অবধি, বেনামে ফাংশন অবজেক্টগুলি জিনিসগুলির পরিবর্তিত স্থিতি (নতুন যাত্রী সহ একটি নতুন বাস) প্রদান করে। এটি ধরে নিয়েছে যে পি.ডিবিট () এখন মূলের চেয়ে কম অর্থ নিয়ে একটি নতুন অচল যাত্রী ফিরিয়ে দেয়:
Bus b = b.mapPassengers(new Function<Passenger,Passenger>() {
@Override
public Passenger apply(final Passenger p) {
return p.debit(fare);
}
}
আশা করি আপনি নিজের অপরিহার্য ভাষাটি কীভাবে কার্যকর করতে চান সে সম্পর্কে আপনি এখনই নিজের সিদ্ধান্ত নিতে পারেন এবং কার্যকরী ভাষা ব্যবহার করে আপনার প্রকল্পটি নতুন করে ডিজাইন করা ভাল কি না তা সিদ্ধান্ত নিতে পারেন। স্কালা বা ক্লোজারে, সংগ্রহগুলি এবং অন্যান্য এপিআইগুলি কার্যকরী প্রোগ্রামিং সহজ করার জন্য ডিজাইন করা হয়েছে। উভয়ের জাভা ইন্টারপ খুব ভাল, তাই আপনি ভাষা মিশ্রিত করতে এবং মেলাতে পারেন। প্রকৃতপক্ষে, জাভা ইন্টারঅ্যাপেরিবিলিটির জন্য, স্কালা তার প্রথম শ্রেণির ফাংশনগুলি বেনাম শ্রেণীর সাথে সংকলন করে যা জাভা 8 ফাংশনাল ইন্টারফেসের সাথে প্রায় উপযুক্ত। আপনি গভীরতা বিভাগে স্কালায় বিশদ সম্পর্কে পড়তে পারেন । 1.3.2 ।