ওয়াই-কম্বিনেটর কী? [বন্ধ]


392

ওয়াই-কম্বিনেটর হ'ল "কার্যকরী" জিনিসের দিক থেকে কম্পিউটার বিজ্ঞান ধারণা। বেশিরভাগ প্রোগ্রামার সংযুক্তকারীদের সম্পর্কে তেমন কিছু জানেন না, যদি তারা তাদের সম্পর্কে শুনেও থাকে।

  • ওয়াই-কম্বিনেটর কী?
  • সংযুক্তকারীরা কীভাবে কাজ করবেন?
  • তারা কি জন্য ভাল?
  • এগুলি কি পদ্ধতিগত ভাষাগুলিতে কার্যকর?

12
একটি অগ্রভাগের বিট, আমি কি চাই আপনি কার্মিক ভাষা সম্পর্কে শিখছে, ভাল ছুটি combinators পর্যন্ত আপনি এটি দিয়ে আরামদায়ক পেতে, অন্যথায় এটি উন্মাদ করার জন্য একটি রাস্তা আছে ...
ইগর Zevaka

3
এই প্রশ্নের সম্পাদকের গুরুতাতরে
বেনজল


1
আমি ওয়াই কম্বিনেটর সম্পর্কে আমার বোঝার সাথে একটি সংক্ষিপ্তসার লিখেছি: gist.github.com/houtianze/b274e4b975a28fe08aee681699c3f7d0 আমি ব্যাখ্যা করেছি (আমার বোঝার জন্য) "Y কম্বিনেটর কীভাবে পুনরাবৃত্ত ফাংশন তোলে"
আইবিক

1
কিভাবে এই প্রশ্ন "খুব বিস্তৃত"?
রেই মিয়াসাকা

উত্তর:


201

আপনি যদি দীর্ঘ পড়ার জন্য প্রস্তুত হন তবে মাইক ভ্যানিয়ারের একটি দুর্দান্ত ব্যাখ্যা রয়েছে । দীর্ঘ গল্প সংক্ষিপ্ত, এটি আপনাকে এমন ভাষায় পুনরাবৃত্তি প্রয়োগ করতে দেয় যা অগত্যা স্থানীয়ভাবে সমর্থন করে না।


14
যদিও এটি একটি লিঙ্কের চেয়ে কিছুটা বেশি; এটি একটি খুব সংক্ষিপ্ত সারাংশ সহ একটি লিঙ্ক । একটি দীর্ঘ সংক্ষিপ্তসার প্রশংসা করা হবে।
মার্টিজন পিটারস

2
এটি কেবল একটি লিঙ্ক তবে এটি এর চেয়ে ভালতর হতে পারে না। এই উত্তরটি প্রস্থান করার জন্য কোনও বেস কেস শর্ত ছাড়াই (1 টি ভোট যোগ করুন) প্রাপ্য; ওরফে অসীম পুনরাবৃত্তি।
ইয়াবার

7
@ আন্ড্রে ম্যাকফি: আমি প্রচেষ্টা সম্পর্কে মন্তব্য করি নি, আমি গুণমান সম্পর্কে মন্তব্য করেছি। সাধারণভাবে, স্ট্যাক ওভারফ্লো সম্পর্কে নীতি হ'ল উত্তরগুলি আরও তথ্যের লিঙ্ক সহ স্বতঃ অন্তর্ভুক্ত থাকা উচিত।
জর্জেন ফোগ

1
@ গেগড্রে ঠিক আছে। এটি একটি দুর্দান্ত লিঙ্ক, তবে এটি কেবল একটি লিঙ্ক। এটি নীচে অন্য 3 টি উত্তরেও উল্লেখ করা হয়েছে তবে কেবলমাত্র একটি সহায়ক দলিল হিসাবে তারা নিজেরাই সমস্ত ভাল ব্যাখ্যা দেয়। এই উত্তরটি ওপি-র প্রশ্নের উত্তর দেওয়ার চেষ্টাও করে না।
toraritte

290

ওয়াই-কম্বিনেটর হ'ল "ফাংশনাল" (একটি ফাংশন যা অন্যান্য ফাংশনগুলিতে পরিচালনা করে) যা পুনরাবৃত্তি সক্ষম করে, যখন আপনি নিজের মধ্যে থেকে ফাংশনটি উল্লেখ করতে না পারেন। কম্পিউটার-বিজ্ঞান তত্ত্বে, এটি পুনরাবৃত্তিকে সাধারণীকরণ করে , এর প্রয়োগকে বিমূর্ত করে তোলে এবং এর ফলে এটিকে প্রশ্নবিদ্ধ কার্যের আসল কাজ থেকে পৃথক করে। পুনরাবৃত্তির জন্য ফাংশনটির জন্য একটি সংকলন-কালীন নাম না লাগানোর সুবিধাটি হ'ল একটি বোনাস। =)

ল্যাম্বডা ফাংশন সমর্থন করে এমন ভাষায় এটি প্রযোজ্য । অভিব্যক্তি lambdas এর ভিত্তিক প্রকৃতি সাধারণত এর অর্থ হল তারা নামে নিজেদের পড়ুন করতে পারবে না। এবং ভেরিয়েবল ঘোষণার মাধ্যমে এটিকে চারপাশে কাজ করা, এটিকে উল্লেখ করে, তারপরে ল্যাম্বডাকে স্বতঃ-রেফারেন্স লুপটি সম্পূর্ণ করার জন্য এটি ভঙ্গুর। ল্যাম্বদা ভেরিয়েবলটি অনুলিপি করা যায় এবং আসল ভেরিয়েবলটি পুনরায় বরাদ্দ করা হয়, যা স্ব-উল্লেখটি ভঙ্গ করে।

ওয়াই-সংযুক্তকারীগুলি স্থির-টাইপযুক্ত ভাষায় (যা পদ্ধতিগত ভাষাগুলি প্রায়শই হয়) প্রয়োগ করার জন্য এবং ব্যবহার করার জন্য জটিল , কারণ সাধারণত টাইপিং নিষেধাজ্ঞাগুলি সংকলনের সময় জ্ঞাত হওয়ার জন্য প্রশ্নটির ফাংশনটির জন্য আর্গুমেন্টের সংখ্যা প্রয়োজন। এর অর্থ হ'ল যে কোনও যুক্তিযুক্ত গণনাটি ব্যবহার করা দরকার তার জন্য একটি y- সংযুক্তকারী অবশ্যই লিখতে হবে।

নীচে সি # তে কীভাবে ওয়াই-কম্বিনেটর ব্যবহার এবং কার্যকারিতা রয়েছে তার একটি উদাহরণ।

ওয়াই-কম্বিনেটর ব্যবহার করে পুনরাবৃত্ত ফাংশন তৈরির একটি "অস্বাভাবিক" উপায় জড়িত। প্রথমে আপনাকে নিজের ফাংশনটি কোডের একটি অংশ হিসাবে লিখতে হবে যা নিজের পরিবর্তে পূর্ব-বিদ্যমান ফাংশনটি কল করে:

// Factorial, if func does the same thing as this bit of code...
x == 0 ? 1: x * func(x - 1);

তারপরে আপনি এটিকে একটি ফাংশনে পরিণত করেন যা কল করতে কোনও ফাংশন নেয় এবং এমন ফাংশনটি ফিরিয়ে দেয়। একে ফাংশনাল বলা হয়, কারণ এটি একটি ফাংশন নেয়, এবং এটির সাথে একটি ক্রিয়াকলাপ সম্পাদন করে যা অন্য ফাংশনের ফলাফল করে।

// A function that creates a factorial, but only if you pass in
// a function that does what the inner function is doing.
Func<Func<Double, Double>, Func<Double, Double>> fact =
  (recurs) =>
    (x) =>
      x == 0 ? 1 : x * recurs(x - 1);

এখন আপনার কাছে একটি ফাংশন রয়েছে যা একটি ফাংশন নেয় এবং অন্য ফাংশনটি দেয় যা সাজানোর মতো দেখায় তবে নিজেকে কল করার পরিবর্তে এটি আর্গুমেন্টটিকে বাইরের ফাংশনে প্রবেশ করে বলে। আপনি কীভাবে এটি ঘটনাচক্রে পরিণত করেন? ভিতরের ফাংশনটি নিজেই পাস করুন Pass ওয়াই-কম্বিনেটর এটি করে, স্থায়ী নামের সাথে একটি ফাংশন হয়ে, যা পুনরাবৃত্তি প্রবর্তন করতে পারে।

// One-argument Y-Combinator.
public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
{
  return
    t =>  // A function that...
      F(  // Calls the factorial creator, passing in...
        Y(F)  // The result of this same Y-combinator function call...
              // (Here is where the recursion is introduced.)
        )
      (t); // And passes the argument into the work function.
}

ফ্যাক্টরিয়াল কলিংয়ের পরিবর্তে যা ঘটে তা হ'ল ফ্যাক্টরিয়ালটি ফ্যাক্টরিয়াল জেনারেটরকে ডেকে তোলে (ওয়াই-কম্বিনেটরে পুনরাবৃত্ত কল দিয়ে ফিরে আসে)। আর টি টির বর্তমান মানের উপর নির্ভর করে জেনারেটর থেকে ফিরিয়ে নেওয়া ফাংশনটি আবার জেনারেটরকে টি - 1 দিয়ে আবার কল করবে, বা পুনরাবৃত্তিটি বন্ধ করে 1 টি ফিরে আসবে।

এটি জটিল এবং রহস্যজনক, তবে এটি সমস্ত রান-টাইমে নাড়া দেয় এবং এর কাজের মূল চাবিকাঠি হ'ল "পিছিয়ে দেওয়া কার্যকর" এবং দুটি ফাংশন ছড়িয়ে দেওয়ার জন্য পুনরাবৃত্তি ভাঙা। অভ্যন্তরীণ এফটি আর্গুমেন্ট হিসাবে পাস করা হয়, পরবর্তী পুনরাবৃত্তিতে ডাকা প্রয়োজন , কেবলমাত্র প্রয়োজন হলে


5
ওহ কেন আপনাকে এটিকে 'ওয়াই' এবং প্যারামিটারটি 'এফ' বলতে হবে! এগুলি কেবল প্রকার আর্গুমেন্টে হারিয়ে যায়!
ব্রায়ান হেন্ক

3
হাসকেলে আপনি বিমূর্ততা পুনরাবৃত্তিটি এর সাথে করতে পারেন: fix :: (a -> a) -> aএবং aআপনি চান যতগুলি আর্গুমেন্টের ফাংশন হতে পারে। এর অর্থ হ'ল স্থির টাইপিং সত্যই এই জটিল করে তোলে না।
পিক

12
মাইক Vanier বর্ণনা মতে, ওয়াই জন্য আপনার সংজ্ঞা আসলে না একটি combinator কারণ এটি রিকার্সিভ আছে। "এলিমিনেটিং (সর্বাধিক) সুস্পষ্ট পুনরাবৃত্তি (অলস সংস্করণ)" এর অধীনে আপনার সি # কোডের সমান অলস স্কিম রয়েছে তবে পয়েন্ট 2 এ ব্যাখ্যা করেছেন: "এটি সংযুক্তকারী নয়, কারণ সংজ্ঞার মূল অংশে ওয়াই একটি মুক্ত পরিবর্তনশীল যা সংজ্ঞাটি সম্পূর্ণ হওয়ার পরে কেবল আবদ্ধ ... "আমি মনে করি ওয়াই-কম্বিনেটরগুলির সম্পর্কে দুর্দান্ত জিনিসটি হ'ল তারা কোনও ফাংশনের নির্দিষ্ট পয়েন্টটি মূল্যায়ন করে পুনরাবৃত্তি উত্পাদন করে। এইভাবে, তাদের সুস্পষ্ট পুনরাবৃত্তি দরকার নেই।
গ্রান্টজে

@ গ্রান্টজে আপনি একটি ভাল বক্তব্য রেখেছেন। এই উত্তরটি পোস্ট করার পরে বেশ কয়েক বছর হয়ে গেছে। ভ্যানিয়ারের পোস্টটি এখন স্কিমিং আমি দেখতে পাচ্ছি যে আমি ওয়াই লিখেছি, তবে কোনও ওয়াই-কম্বিনেটর নয়। আমি শীঘ্রই তার পোস্টটি আবার পড়ব এবং আমি কোনও সংশোধন পোস্ট করতে পারব কিনা তা দেখুন। আমার অন্ত্রে আমাকে সতর্ক করে দিচ্ছে যে সি # এর কঠোর স্ট্যাটিক টাইপিংটি শেষ পর্যন্ত এটি প্রতিরোধ করতে পারে, তবে আমি কী করব তা দেখতে পাচ্ছি।
ক্রিস আম্মারম্যান

1
@ ওয়েইনবারকেট এটি গণিতে খুব সাধারণ একটি অনুশীলন।
YoTengoUnLCD

102

আমি এটি http://www.mail-archive.com/boston-pm@mail.pm.org/msg02716.html থেকে তুলে নিয়েছি যা এটি বেশ কয়েক বছর আগে লিখেছিলাম explanation

আমি এই উদাহরণটিতে জাভাস্ক্রিপ্ট ব্যবহার করব, তবে আরও অনেক ভাষাও কাজ করবে।

আমাদের লক্ষ্যটি হল 1 ভেরিয়েবলের কেবল 1 ফাংশন এবং কোনও অ্যাসাইনমেন্ট ব্যবহার করে নাম পরিবর্তন করে কোনও জিনিস ব্যবহার করে 1 ভেরিয়েবলের একটি পুনরাবৃত্ত ফাংশন লিখতে সক্ষম হবেন (কেন এটি আমাদের লক্ষ্য কেন অন্য প্রশ্ন, আসুন আমরা একে চ্যালেঞ্জ হিসাবে গ্রহণ করি দেওয়া হয়েছে।) অসম্ভব বলে মনে হচ্ছে, তাই না? উদাহরণ হিসাবে, আসুন বাস্তবিক বাস্তবায়ন করা যাক।

ভাল পদক্ষেপ 1 বলতে কিছুটা প্রতারিত হলে আমরা সহজেই এটি করতে পারতাম। 2 ভেরিয়েবল এবং অ্যাসাইনমেন্টের ফাংশন ব্যবহার করে আমরা কমপক্ষে পুনরাবৃত্তি সেট আপ করতে অ্যাসাইনমেন্টটি ব্যবহার করা এড়াতে পারি।

// Here's the function that we want to recurse.
X = function (recurse, n) {
  if (0 == n)
    return 1;
  else
    return n * recurse(recurse, n - 1);
};

// This will get X to recurse.
Y = function (builder, n) {
  return builder(builder, n);
};

// Here it is in action.
Y(
  X,
  5
);

এখন দেখা যাক আমরা কম ঠকাই কিনা। ভাল প্রথমে আমরা অ্যাসাইনমেন্ট ব্যবহার করছি, কিন্তু আমাদের দরকার নেই। আমরা কেবল এক্স এবং ওয়াই ইনলাইন লিখতে পারি।

// No assignment this time.
function (builder, n) {
  return builder(builder, n);
}(
  function (recurse, n) {
    if (0 == n)
      return 1;
    else
      return n * recurse(recurse, n - 1);
  },
  5
);

তবে আমরা 1 ভেরিয়েবলের ফাংশন পেতে 2 ভেরিয়েবলের ফাংশন ব্যবহার করছি। আমরা কি তা ঠিক করতে পারি? হাস্কেল কারির নামে একটি স্মার্ট লোকের ঝরঝরে কৌশল রয়েছে, যদি আপনার উচ্চতর অর্ডার ফাংশন থাকে তবে আপনার কেবলমাত্র 1 ভেরিয়েবলের ফাংশন প্রয়োজন। এর প্রমাণটি হ'ল আপনি 2 (বা সাধারণ ক্ষেত্রে আরও বেশি) ভেরিয়েবলগুলি এর থেকে খাঁটি যান্ত্রিক পাঠ্য রূপান্তরের মাধ্যমে 1 ভেরিয়েবলে পেতে পারেন:

// Original
F = function (i, j) {
  ...
};
F(i,j);

// Transformed
F = function (i) { return function (j) {
  ...
}};
F(i)(j);

যেখানে ... ঠিক একইরকম থাকে। (এই কৌশলটিকে আবিষ্কারকের পরে "কারিইং" বলা হয় Has ভাষাটি হাসকলও হ্যাশেল কারির জন্য নামকরণ করেছে File ফাইলটি যে অকেজো ট্রাইভিয়ার অধীনে File) এখন কেবল সর্বত্রই এই রূপান্তরটি প্রয়োগ করুন এবং আমরা আমাদের চূড়ান্ত সংস্করণ পাই।

// The dreaded Y-combinator in action!
function (builder) { return function (n) {
  return builder(builder)(n);
}}(
  function (recurse) { return function (n) {
    if (0 == n)
      return 1;
    else
      return n * recurse(recurse)(n - 1);
  }})(
  5
);

এটি চেষ্টা করুন নির্দ্বিধায়। সতর্কতা () যা ফিরে আসে, এটিকে কোনও বোতামে টাই করুন, যাই হোক না কেন। এই কোডটি অ্যাসাইনমেন্ট, ঘোষণা এবং 2 ভেরিয়েবলের ফাংশন ব্যবহার না করে পুনরাবৃত্তভাবে ফ্যাকটোরিয়াল গণনা করে। (তবে এটি কীভাবে কাজ করে তা সনাক্ত করার চেষ্টা করা আপনার মাথাকে স্পিন করে তুলবে And

আপনি চান এমন 4 টি লাইন প্রতিস্থাপন করতে পারেন যা ঘটনাক্রমে সংক্ষিপ্তভাবে সংজ্ঞায়িত করে যে কোনও অন্য পুনরাবৃত্তীয় ক্রিয়াকলাপ with


সুন্দর ব্যাখ্যা। এর function (n) { return builder(builder)(n);}বদলে লেখেন কেন builder(builder)?
v7d8dpo4

@ v7d8dpo4 কারি কারিং ব্যবহার করে আমি 2 ভেরিয়েবলের একটি ফাংশনটিকে একটি ভেরিয়েবলের একটি উচ্চতর ক্রম ফাংশনে পরিণত করছিলাম।
btilly

আমাদের কি ক্লোজার দরকার এই কারণেই?
থেটেন

1
@ চেচেন ক্লোজারগুলি আমাদের একটি অনামী কার্যক্রমে কল করার পিছনে স্বনির্ধারিত আচরণটি বেঁধে দেয়। এটি কেবল আরেকটি বিমূর্ত কৌশল।
বেটিলি

85

আমি অবাক হই যে এটিকে ভিত্তি থেকে তৈরি করার চেষ্টা করার যদি কোনও ব্যবহার হয়। দেখা যাক. এখানে একটি মৌলিক, পুনরাবৃত্ত কল্পিত কার্য রয়েছে:

function factorial(n) {
    return n == 0 ? 1 : n * factorial(n - 1);
}

আসুন রিফ্যাক্টর এবং একটি নতুন ফাংশন তৈরি করি factযা গণনা নিজেই সম্পাদন করার পরিবর্তে একটি বেনাম ফ্যাটোরিয়াল-কম্পিউটিং ফাংশন দেয়:

function fact() {
    return function(n) {
        return n == 0 ? 1 : n * fact()(n - 1);
    };
}

var factorial = fact();

এটি কিছুটা অদ্ভুত, তবে এতে কোনও ভুল নেই। আমরা প্রতিটি পদক্ষেপে একটি নতুন ফ্যাক্টরিয়াল ফাংশন তৈরি করছি।

এই পর্যায়ে পুনরাবৃত্তি এখনও মোটামুটি সুস্পষ্ট। factফাংশন নিজস্ব নাম সচেতন হতে হবে। আসুন পুনরাবৃত্তির কলটিকে পরামিতি করি:

function fact(recurse) {
    return function(n) {
        return n == 0 ? 1 : n * recurse(n - 1);
    };
}

function recurser(x) {
    return fact(recurser)(x);
}

var factorial = fact(recurser);

এটি দুর্দান্ত, তবে recurserতার নিজের নামটি এখনও জানতে হবে। এটিও পরামিতি করা যাক:

function recurser(f) {
    return fact(function(x) {
        return f(f)(x);
    });
}

var factorial = recurser(recurser);

এখন, recurser(recurser)সরাসরি কল করার পরিবর্তে আসুন একটি মোড়ক ফাংশন তৈরি করি যা এর ফলাফলটি দেয়:

function Y() {
    return (function(f) {
        return f(f);
    })(recurser);
}

var factorial = Y();

আমরা এখন recurserপুরোপুরি নামটি থেকে মুক্তি পেতে পারি ; এটি ওয়াই এর অভ্যন্তরীণ ফাংশনের কেবল একটি যুক্তি, যা নিজেই ফাংশন দিয়ে প্রতিস্থাপন করা যেতে পারে:

function Y() {
    return (function(f) {
        return f(f);
    })(function(f) {
        return fact(function(x) {
            return f(f)(x);
        });
    });
}

var factorial = Y();

কেবলমাত্র বাহ্যিক নাম এখনও উল্লেখ করা হয়েছে fact, তবে এটি এখনই পরিষ্কার হওয়া উচিত যে এটি সহজেই প্যারামিটারাইজড হয়ে গেছে, সম্পূর্ণ, জেনেরিক, সমাধান তৈরি করে:

function Y(le) {
    return (function(f) {
        return f(f);
    })(function(f) {
        return le(function(x) {
            return f(f)(x);
        });
    });
}

var factorial = Y(function(recurse) {
    return function(n) {
        return n == 0 ? 1 : n * recurse(n - 1);
    };
});

জাভাস্ক্রিপ্টে একইরকম ব্যাখ্যা: igstan.ro/posts/…
পোপস

1
আপনি ফাংশনটি চালু করার সময় আমাকে হারিয়েছেন recurser। এটি কী করছে বা কেন করছে তা সম্পর্কে সামান্যতম ধারণা নয়।
মেরি

2
আমরা স্পষ্টভাবে পুনরাবৃত্তি না করে এমন ফাংশনগুলির জন্য একটি জেনেরিক পুনরাবৃত্ত সমাধান সমাধান করার চেষ্টা করছি। recurserফাংশন, এই লক্ষ্য দয়া করে কারণ এটি আমাদের একটি recursive সংস্করণ দেয় factযে নাম স্বত রেফারেন্স না।
ওয়েইন

@WayneBurkett পারেন আমি ভালো ওয়াই combinator পুনর্লিখন: function Y(recurse) { return recurse(recurse); } let factorial = Y(creator => value => { return value == 0 ? 1 : value * creator(creator)(value - 1); });। আর এভাবেই আমি এটা ডাইজেস্ট (যদি নিশ্চিত না এটি সঠিক কিনা) হল: স্পষ্টভাবে ফাংশন (ক যেমন মঞ্জুরিপ্রাপ্ত নয় উল্লেখ না করে combinator ), আমরা দুই ব্যবহার করতে পারেন আংশিকভাবে প্রযুক্ত / curried ফাংশন (ক স্রষ্টা ফাংশন এবং ক্যালকুলেট ফাংশন), সঙ্গে যা আমরা ল্যাম্বদা / বেনামে ফাংশন তৈরি করতে পারি যা গণনা কার্যের জন্য কোনও নামের প্রয়োজন ছাড়াই পুনরাবৃত্তি অর্জন করে?
neevek

50

উত্তর অধিকাংশই উপরে বর্ণনা কি ওয়াই-combinator হয় কিন্তু এটা কি জন্য

ফিক্সড পয়েন্ট কম্বিনেটরগুলি লাম্বডা ক্যালকুলাস সম্পূর্ণরূপে টুরিং হয় তা দেখাতে ব্যবহার করা হয় । এটি গণনা তত্ত্বের একটি অত্যন্ত গুরুত্বপূর্ণ ফলাফল এবং কার্যকরী প্রোগ্রামিংয়ের জন্য একটি তাত্ত্বিক ভিত্তি সরবরাহ করে

ফিক্সড পয়েন্ট কম্বিনেটর অধ্যয়নও আমাকে কার্যকরী প্রোগ্রামিং বুঝতে সত্যই সহায়তা করেছে। যদিও সত্যিকারের প্রোগ্রামিংয়ে আমি তাদের জন্য কোনও ব্যবহার পাইনি।


24

জাভাস্ক্রিপ্টে y- সংযুক্তকারী :

var Y = function(f) {
  return (function(g) {
    return g(g);
  })(function(h) {
    return function() {
      return f(h(h)).apply(null, arguments);
    };
  });
};

var factorial = Y(function(recurse) {
  return function(x) {
    return x == 0 ? 1 : x * recurse(x-1);
  };
});

factorial(5)  // -> 120

সম্পাদন করা : কোডটি দেখে আমি অনেক কিছু শিখেছি, তবে এটি ব্যাকগ্রাউন্ড ছাড়াই গিলতে কিছুটা শক্ত - এটি সম্পর্কে দুঃখিত is অন্যান্য উত্তর দ্বারা উপস্থাপিত কিছু সাধারণ জ্ঞানের সাহায্যে, আপনি যা ঘটছে তা আলাদা করতে শুরু করতে পারেন।

Y ফাংশনটি হ'ল "y-combinator"। এখন var factorialকোথায় লাইনটি ব্যবহার করা হচ্ছে তা একবার দেখুন। লক্ষ্য করুন আপনি এটিতে কোনও ফাংশন পাস করেছেন যার একটি প্যারামিটার রয়েছে (এই উদাহরণে recurse) যা পরে অভ্যন্তরীণ ফাংশনেও ব্যবহৃত হয় in প্যারামিটারের নামটি মূলত অভ্যন্তরীণ ফাংশনটির নাম হয়ে যায় যা এটি পুনরাবৃত্ত কল করতে পারে (যেহেতু recurse()এটি এর সংজ্ঞায় ব্যবহৃত হয়) ওয়াই-কম্বিনেটর অন্যথায় বেনামে অভ্যন্তরীণ ফাংশনটি ফাংশনের প্যারামিটার নামের সাথে সংযুক্ত করার যাদু সম্পাদন করে ওয়াই

ওয়াই কীভাবে যাদু করে তার পুরো ব্যাখ্যার জন্য, লিঙ্কযুক্ত নিবন্ধটি পরীক্ষা করে দেখুন (আমার বিটিডাব্লু দ্বারা নয়)


6
জাভাস্ক্রিপ্ট বেনামী পুনরাবৃত্তির করতে একটি ওয়াই-combinator দরকার নেই কারণ আপনার arguments.callee বর্তমান ফাংশন অ্যাক্সেস করতে পারেন (দেখুন en.wikipedia.org/wiki/... )
xitrium

6
arguments.callee কঠোর মোডে অনুমোদিত নয়:
কড়া

2
আপনি এখনও কোনও ফাংশনকে একটি নাম দিতে পারেন, এবং যদি এটি ফাংশন এক্সপ্রেশন হয় তবে সেই নামটি কেবলমাত্র ফাংশনের ভিতরেই পরিচিত। (function fact(n){ return n <= 1? 1 : n * fact(n-1); })(5)
ইসাইলিজা


18

প্রোগ্রামারদের জন্য যারা গভীরভাবে কার্যকরী প্রোগ্রামিংয়ের মুখোমুখি হয়নি, এবং এখনই শুরু করার যত্ন নেন না, তবে হালকা কৌতূহলী:

ওয়াই কম্বিনেটর এমন একটি সূত্র যা আপনাকে এমন পরিস্থিতিতে পুনরাবৃত্তি কার্যকর করতে দেয় যেখানে ফাংশনগুলির নাম থাকতে পারে না তবে আর্গুমেন্ট হিসাবে ফেরত দেওয়া যায়, ফেরতের মান হিসাবে ব্যবহৃত হয় এবং অন্যান্য ফাংশনগুলির মধ্যে সংজ্ঞায়িত হয়।

এটি একটি আর্গুমেন্ট হিসাবে ফাংশনটি নিজের মধ্যে স্থান দিয়ে কাজ করে, তাই এটি নিজেই কল করতে পারে।

এটি ল্যাম্বডা ক্যালকুলাসের অংশ, যা সত্যিই গণিত তবে কার্যকরভাবে একটি প্রোগ্রামিং ভাষা এবং এটি কম্পিউটার বিজ্ঞানের এবং বিশেষত ক্রিয়ামূলক প্রোগ্রামিংয়ের জন্য বেশ মৌলিক।

Y সংযুক্তকারীটির প্রতিদিনের ব্যবহারিক মান সীমিত, যেহেতু প্রোগ্রামিং ভাষাগুলি আপনাকে ফাংশনগুলির নাম দিতে দেয়।

আপনার যদি কোনও পুলিশ লাইনআপে এটি সনাক্ত করতে হয় তবে এটি দেখতে এটির মতো দেখাচ্ছে:

Y = .f। (.X.f (xx)) (.x.f (xx))

আপনি সাধারণত এটি পুনরুক্ত কারণ স্পট করতে পারেন (λx.f (x x))

λপ্রতীক গ্রিক বর্ণ ল্যামডা, যা তার নাম ক্যালকুলাস ল্যামডা দেয়, আর সেখানে অনেক (λx.t)শৈলী পদ যে কারণ কি ল্যামডা ক্যালকুলাস দেখে মনে হচ্ছে।


এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। বিটিডাব্লু, সহ U x = x x, Y = U . (. U)(হাস্কেল-জাতীয় স্বরলিপিটি আপত্তিজনক)। আইওডাব্লু, সঠিক সংযোজক সহ Y = BU(CBU),। এইভাবে Yf = U (f . U) = (f . U) (f . U) = f (U (f . U)) = f ((f . U) (f . U)),।
নেস

13

নামবিহীন পুনরুক্তি

একটি স্থির-পয়েন্ট সংযোজক হ'ল একটি অর্ডার ফাংশন fixযা সংজ্ঞায়িত করে সমতাটি সন্তুষ্ট করে

forall f.  fix f  =  f (fix f)

fix fxস্থির-পয়েন্ট সমীকরণের একটি সমাধান উপস্থাপন করে

               x  =  f x

একটি প্রাকৃতিক সংখ্যার বর্ণনাকারী দ্বারা প্রমাণ করা যায়

fact 0 = 1
fact n = n * fact (n - 1)

fixসাধারণ / rec-রিকার্সিভ ফাংশনগুলির তুলনায় নির্বিচারে গঠনমূলক প্রমাণগুলি ব্যবহার করে স্বতঃস্ফূর্ততা ব্যতীত ছাড়াই পাওয়া যায়।

fact n = (fix fact') n

কোথায়

fact' rec n = if n == 0
                then 1
                else n * rec (n - 1)

যেমন যে

   fact 3
=  (fix fact') 3
=  fact' (fix fact') 3
=  if 3 == 0 then 1 else 3 * (fix fact') (3 - 1)
=  3 * (fix fact') 2
=  3 * fact' (fix fact') 2
=  3 * if 2 == 0 then 1 else 2 * (fix fact') (2 - 1)
=  3 * 2 * (fix fact') 1
=  3 * 2 * fact' (fix fact') 1
=  3 * 2 * if 1 == 0 then 1 else 1 * (fix fact') (1 - 1)
=  3 * 2 * 1 * (fix fact') 0
=  3 * 2 * 1 * fact' (fix fact') 0
=  3 * 2 * 1 * if 0 == 0 then 1 else 0 * (fix fact') (0 - 1)
=  3 * 2 * 1 * 1
=  6

এই আনুষ্ঠানিক প্রমাণ যে

fact 3  =  6

পদ্ধতিগতভাবে পুনর্লিখনের জন্য স্থির-পয়েন্ট সংযোজক সমতা ব্যবহার করে

fix fact'  ->  fact' (fix fact')

ল্যাম্বদা ক্যালকুলাস

Untyped ল্যামডা ক্যালকুলাস লৌকিকতা একটি প্রেক্ষাপটে মুক্ত ব্যাকরণ গঠিত

E ::= v        Variable
   |  λ v. E   Abstraction
   |  E E      Application

যেখানে বিটা এবং এটা হ্রাস বিধি vএকসাথে ভেরিয়েবলের ব্যাপ্তি রয়েছে

(λ x. B) E  ->  B[x := E]                                 Beta
  λ x. E x  ->  E          if x doesn’t occur free in E   Eta

বিটা হ্রাস বিমোচন x("ফাংশন") শরীরে পরিবর্তন B("যুক্তি") দ্বারা শরীরের সমস্ত মুক্ত ইভেন্টকে প্রতিস্থাপন করে E। এটা হ্রাস অপ্রয়োজনীয় বিমূর্ততা দূর করে। এটি কখনও কখনও আনুষ্ঠানিকতা থেকে বাদ দেওয়া হয়। একটি অদম্য অভিব্যক্তি, যার কোনও হ্রাস বিধি প্রযোজ্য নয়, এটি স্বাভাবিক বা প্রমিত আকারে

λ x y. E

সংক্ষিপ্ত

λ x. λ y. E

(বিমূর্ততা বহুগুণ),

E F G

সংক্ষিপ্ত

(E F) G

(অ্যাপ্লিকেশন বাম-সমিতি),

λ x. x

এবং

λ y. y

হয় আলফা-সমতুল্য

অ্যাবস্ট্রাকশন এবং অ্যাপ্লিকেশন হ'ল ল্যাম্বদা ক্যালকুলাসের কেবল দুটি "ভাষা আদিম", তবে তারা এনকোডিংয়ের অনুমতি দেয় নির্বিচারে জটিল ডেটা এবং ক্রিয়াকলাপকে ।

চার্চ সংখ্যা হ'ল পিয়ানো-অ্যাক্সিয়োমেটিক প্রাকৃতিকগুলির মতো প্রাকৃতিক সংখ্যার এনকোডিং।

   0  =  λ f x. x                 No application
   1  =  λ f x. f x               One application
   2  =  λ f x. f (f x)           Twofold
   3  =  λ f x. f (f (f x))       Threefold
    . . .

SUCC  =  λ n f x. f (n f x)       Successor
 ADD  =  λ n m f x. n f (m f x)   Addition
MULT  =  λ n m f x. n (m f) x     Multiplication
    . . .

একটি আনুষ্ঠানিক প্রমাণ যে

1 + 2  =  3

বিটা হ্রাসের পুনর্লিখনের নিয়মটি ব্যবহার করে:

   ADD                      1            2
=  (λ n m f x. n f (m f x)) (λ g y. g y) (λ h z. h (h z))
=  (λ m f x. (λ g y. g y) f (m f x)) (λ h z. h (h z))
=  (λ m f x. (λ y. f y) (m f x)) (λ h z. h (h z))
=  (λ m f x. f (m f x)) (λ h z. h (h z))
=  λ f x. f ((λ h z. h (h z)) f x)
=  λ f x. f ((λ z. f (f z)) x)
=  λ f x. f (f (f x))                                       Normal form
=  3

Combinators

ল্যামডা ক্যালকুলাসে combinators বিমূর্ত কোনো বিনামূল্যে ভেরিয়েবল ধারণ হয়। সর্বাধিক সহজভাবে I:, পরিচয় সংযোজক

λ x. x

আইসনমোরফিক আইডেন্টিফিকেশন ফাংশন

id x = x

এই জাতীয় সংযোগকারীরা এসকেআই সিস্টেমের মতো কম্বিনেটর ক্যালকুলির আদিম অপারেটর ।

S  =  λ x y z. x z (y z)
K  =  λ x y. x
I  =  λ x. x

বিটা হ্রাস দৃ strongly়ভাবে স্বাভাবিক হচ্ছে না ; সমস্ত হ্রাসযোগ্য এক্সপ্রেশন, "রিডেক্সেস" বিটা হ্রাসের আওতায় স্বাভাবিক আকারে রূপান্তরিত করে না। একটি উত্তম উদাহরণ ওমেগা বিপথগামী আবেদন ωcombinator

λ x. x x

নিজেই:

   (λ x. x x) (λ y. y y)
=  (λ y. y y) (λ y. y y)
. . .
=  _|_                     Bottom

বামতম স্যুট এক্সপ্রেসনগুলি ("মাথা") হ্রাসকে অগ্রাধিকার দেওয়া হয়েছে। প্রয়োগমূলক আদেশ প্রতিস্থাপনের আগে যুক্তিগুলিকে স্বাভাবিক করে তোলে, স্বাভাবিক আদেশ দেয় না। দুটি কৌশল হ'ল আগ্রহী মূল্যায়নের সাথে সমান, যেমন সি এবং অলস মূল্যায়ন, যেমন হাস্কেল।

   K          (I a)        (ω ω)
=  (λ k l. k) ((λ i. i) a) ((λ x. x x) (λ y. y y))

উত্সাহী আবেদনকারী-আদেশ বিটা হ্রাস অধীনে পরিবর্তন

=  (λ k l. k) a ((λ x. x x) (λ y. y y))
=  (λ l. a) ((λ x. x x) (λ y. y y))
=  (λ l. a) ((λ y. y y) (λ y. y y))
. . .
=  _|_

যেহেতু কঠোর শব্দার্থক শব্দে

forall f.  f _|_  =  _|_

তবে অলস স্বাভাবিক-অর্ডার বিটা হ্রাসের আওতায় আসে

=  (λ l. ((λ i. i) a)) ((λ x. x x) (λ y. y y))
=  (λ l. a) ((λ x. x x) (λ y. y y))
=  a

যদি কোনও অভিব্যক্তির একটি সাধারণ ফর্ম থাকে, তবে স্বাভাবিক-ক্রমের বিটা হ্রাস এটি খুঁজে পাবে।

ওয়াই

স্থির-পয়েন্ট সংযোজকের প্রয়োজনীয় সম্পত্তিY

λ f. (λ x. f (x x)) (λ x. f (x x))

দেওয়া হয়

   Y g
=  (λ f. (λ x. f (x x)) (λ x. f (x x))) g
=  (λ x. g (x x)) (λ x. g (x x))           =  Y g
=  g ((λ x. g (x x)) (λ x. g (x x)))       =  g (Y g)
=  g (g ((λ x. g (x x)) (λ x. g (x x))))   =  g (g (Y g))
. . .                                      . . .

সমতা

Y g  =  g (Y g)

isomorphic হয়

fix f  =  f (fix f)

টাইপযুক্ত ল্যাম্বডা ক্যালকুলাস সাধারণ / μ-পুনরাবৃত্ত ফাংশনগুলির তুলনায় নির্বিচারে গঠনমূলক প্রমাণগুলি এনকোড করতে পারে।

 FACT  =  λ n. Y FACT' n
FACT'  =  λ rec n. if n == 0 then 1 else n * rec (n - 1)

   FACT 3
=  (λ n. Y FACT' n) 3
=  Y FACT' 3
=  FACT' (Y FACT') 3
=  if 3 == 0 then 1 else 3 * (Y FACT') (3 - 1)
=  3 * (Y FACT') (3 - 1)
=  3 * FACT' (Y FACT') 2
=  3 * if 2 == 0 then 1 else 2 * (Y FACT') (2 - 1)
=  3 * 2 * (Y FACT') 1
=  3 * 2 * FACT' (Y FACT') 1
=  3 * 2 * if 1 == 0 then 1 else 1 * (Y FACT') (1 - 1)
=  3 * 2 * 1 * (Y FACT') 0
=  3 * 2 * 1 * FACT' (Y FACT') 0
=  3 * 2 * 1 * if 0 == 0 then 1 else 0 * (Y FACT') (0 - 1)
=  3 * 2 * 1 * 1
=  6

(বহুগুণে বিলম্ব, সঙ্গম)

চার্চিয়ান অব টাইপযুক্ত ল্যাম্বডা ক্যালকুলাসের জন্য সেখানে স্থির-পয়েন্ট সংযোজকগুলির পাশাপাশি পুনরাবৃত্তিযোগ্যভাবে গণনাযোগ্য অনন্ত উপস্থিত রয়েছে বলে প্রমাণিত হয়েছে Y

 X  =  λ f. (λ x. x x) (λ x. f (x x))
Y'  =  (λ x y. x y x) (λ y x. y (x y x))
 Z  =  λ f. (λ x. f (λ v. x x v)) (λ x. f (λ v. x x v))
 Θ  =  (λ x y. y (x x y)) (λ x y. y (x x y))
  . . .

সাধারণ অর্ডার বিটা হ্রাস অব্যক্ত অবধি অবহিত ল্যাম্বদা ক্যালকুলাসকে একটি টুরিং-সম্পূর্ণ পুনর্লিখন সিস্টেম করে।

হাস্কেলে, স্থির-পয়েন্ট সংযোজকটি মার্জিতভাবে প্রয়োগ করা যেতে পারে

fix :: forall t. (t -> t) -> t
fix f = f (fix f)

সমস্ত সাফল্য মূল্যায়নের আগে মূল্যায়ন করার আগে হাস্কেলের অলসতা এক চূড়ান্ত পর্যায়ে পৌঁছে যায়।

primes :: Integral t => [t]
primes = sieve [2 ..]
   where
      sieve = fix (\ rec (p : ns) ->
                     p : rec [n | n <- ns
                                , n `rem` p /= 0])


4
আমি উত্তরটির পুরোপুরি প্রশংসা করি, তবে প্রথম লাইনের বিরতির পরে কোনও প্রোগ্রামারের কাছে এটি কোনওভাবেই সামান্য আনুষ্ঠানিক গণিতের পটভূমির কাছে পৌঁছানো যায় না।
জারেড স্মিথ

4
@ জারেড-স্মিথ উত্তরটির অর্থ ওয়াই সংযুক্তকারীটির পিছনে সিএস / গণিতের ধারণা সম্পর্কে পরিপূরক ওয়াঙ্কাইয়ান গল্প বলা। আমি মনে করি, সম্ভবত, পরিচিত ধারণাগুলির সেরা সম্ভাব্য উপমা ইতিমধ্যে অন্যান্য উত্তরদাতারা আঁকেন drawn ব্যক্তিগতভাবে, আমি সর্বদা একটি সুন্দর উপমা দিয়ে সত্যের উত্স, একটি ধারণার মূল অভিনবত্বের সাথে মুখোমুখি হতে পছন্দ করি । আমি বেশিরভাগ বিস্তৃত উপমাগুলি অনুপযুক্ত এবং বিভ্রান্তিকর খুঁজে পাই।

1
হ্যালো, পরিচয় সমন্বয়কারী λ x . x, আজ কেমন আছেন?
মাইয়াভিক্টর

আমি এই উত্তরটি সবচেয়ে পছন্দ করি । এটি কেবল আমার সমস্ত প্রশ্ন পরিষ্কার করেছে!
শিক্ষার্থী

11

অন্যান্য জবাবগুলি একটি গুরুত্বপূর্ণ সত্য ছাড়াই এটির পক্ষে খুব সংক্ষিপ্ত উত্তর সরবরাহ করে: আপনাকে এই জটিল আকারে কোনও ব্যবহারিক ভাষায় স্থির বিন্দু সংযোজক প্রয়োগ করার দরকার নেই এবং এর ফলে কোনও ব্যবহারিক উদ্দেশ্য হয় না ("দেখুন, আমি জানি ওয়াই-কম্বিনেটর কী হয় ")। এটি গুরুত্বপূর্ণ তাত্ত্বিক ধারণা, তবে ব্যবহারিক মূল্য খুব কম।


6

এখানে ওয়াই-কম্বিনেটর এবং ফ্যাক্টরিয়াল ফাংশনটির একটি জাভাস্ক্রিপ্ট বাস্তবায়ন রয়েছে (ডগলাস ক্রকফোর্ডের নিবন্ধ থেকে: http://javascript.crockford.com/little.html এ উপলব্ধ )।

function Y(le) {
    return (function (f) {
        return f(f);
    }(function (f) {
        return le(function (x) {
            return f(f)(x);
        });
    }));
}

var factorial = Y(function (fac) {
    return function (n) {
        return n <= 2 ? n : n * fac(n - 1);
    };
});

var number120 = factorial(5);

6

একটি ওয়াই-কম্বিনেটর ফ্লাক্স ক্যাপাসিটরের অন্য নাম।


4
খুবি হাস্যকর. :) অল্প বয়স্ক (এর) তারা যদিও উল্লেখটি সনাক্ত করতে পারে না।
নেস

2
হা হা! হ্যাঁ, যুবকটি (আমি) এখনও বুঝতে পারে ...

আমি ভাবলাম এটি বাস্তব এবং আমি এখানেই শেষ হয়েছি। youtube.com/watch?v=HyWqxkaQpPw সাম্প্রতিক নিবন্ধ ফিউচারিজম
সায়েন্টিস্টস-মেডেল-রিয়েল-লাইফ- ফ্লাক- ক্যাপাসিটর

আমি মনে করি এই উত্তরটি ইংরেজী অ স্পিকারের জন্য বিশেষত বিভ্রান্তিকর হতে পারে। এই দাবিটি বোঝার জন্য কেউ এই দাবিটি বোঝার জন্য যথেষ্ট সময় ব্যয় করতে পারে (বা কখনই নয়) যে এটি একটি হাস্যকর জনপ্রিয় সংস্কৃতি উল্লেখ। (আমি এটি পছন্দ করি, আমি যদি খারাপ উত্তর পাই তবে আমি এটির উত্তর দিয়েছি এবং শিখেছি যে কেউ শেখা এটির দ্বারা নিরুৎসাহিত হয়েছে)
মাইকে

5

নিজেকে এটিকে আরও শক্ত করে ধরতে সহায়তা করার জন্য আমি ক্লোজার এবং স্কিম উভয় ক্ষেত্রে ওয়াই-কম্বিনেটরকে এক ধরণের "ইডিয়ট গাইড" লিখেছি। তারা "দ্য লিটল স্কিমার" এর উপাদান দ্বারা প্রভাবিত

স্কিমে: https://gist.github.com/z5h/238891

বা ক্লোজার: https://gist.github.com/z5h/5102747

উভয় টিউটোরিয়াল মন্তব্যগুলির সাথে ছেদ করা কোড এবং আপনার পছন্দসই সম্পাদককে কাটা এবং পেকেটে নেওয়া উচিত।


5

সংযুক্তকারীদের নবাগত হিসাবে, আমি মাইক ভ্যানিয়ারের নিবন্ধটি (ধন্যবাদ নিকোলাস মানকুসো) সত্যিই সহায়ক বলে খুঁজে পেয়েছি । আমি আমার বোঝার ডকুমেন্টিংয়ের পাশাপাশি একটি সংক্ষিপ্ত বিবরণ লিখতে চাই, যদি এটি অন্য কারওর পক্ষে সহায়ক হতে পারে তবে আমি খুব আনন্দিত হতে পারি।

থেকে ন্যক্কারজনক করতে কম ন্যক্কারজনক

উদাহরণ হিসাবে উদাহরণস্বরূপ ব্যবহার করে, আমরা almost-factorialসংখ্যার ফ্যাকটোরিয়াল গণনা করতে নিম্নলিখিত ফাংশনটি ব্যবহার করি x:

def almost-factorial f x = if iszero x
                           then 1
                           else * x (f (- x 1))

উপরের সিউডো কোডে, almost-factorialফাংশন fএবং সংখ্যা গ্রহণ করে x( almost-factorialতরকারিযুক্ত, তাই এটি ফাংশন গ্রহণ fএবং একটি 1-আরটি ফাংশন ফেরত হিসাবে দেখা যায় )।

যখন এর almost-factorialজন্য ফ্যাক্টরিয়াল গণনা করা হয় x, এটি x - 1কাজ করার জন্য ফ্যাক্টরিয়াল গণনার প্রতিনিধিত্ব করে fএবং ফলাফলটি সংগ্রহ করেx (এই ক্ষেত্রে এটি x এর সাথে (x - 1) ফলাফলকে বহুগুণ করে)।

এটিকে ফ্যাক্টরিয়াল ফাংশনের almost-factorialএকটি কৃপণ সংস্করণ হিসাবে গ্রহণ করা যেতে পারে (যা কেবল সংখ্যা পর্যন্ত গণনা করতে পারে x - 1) এবং ফ্যাকটোরিয়াল (যা সংখ্যার অবধি গণনা করে ) এর একটি কম-কৃপণ সংস্করণ দেয় x। এই ফর্ম হিসাবে:

almost-factorial crappy-f = less-crappy-f

যদি আমরা বারবার ফ্যাকটোরিয়ালটির কম-কৃপণ সংস্করণটি পাস almost-factorialকরি তবে শেষ পর্যন্ত আমরা আমাদের কাঙ্ক্ষিত ফ্যাক্টরিয়াল ফাংশনটি পেয়ে যাব f। যেখানে এটি হিসাবে বিবেচনা করা যেতে পারে:

almost-factorial f = f

ফিক্স দফা

এর almost-factorial f = fঅর্থ fহল ফাংশনের ফিক্স পয়েন্টalmost-factorial

উপরের ফাংশনগুলির সম্পর্কগুলি দেখার এটি একটি সত্যই আকর্ষণীয় উপায় ছিল এবং এটি আমার জন্য একটি আহ মুহুর্ত ছিল। (দয়া করে মাইকের পোস্টটি ফিক্স পয়েন্টে পড়ুন যদি না থাকেন)

তিনটি ফাংশন

সাধারণের জন্য, আমরা একটি আছে অ রিকার্সিভ ফাংশন fn(আমাদের প্রায়-গৌণিক মত), আমরা তার আছে ফিক্স দফা ফাংশন fr(আমাদের চ মত), তাহলে কি Yআপনি দিতে না হয় Y fn, Yএর ফিক্স দফা ফাংশনটি fn

তাই সংক্ষেপে বলা (অভিমানী দ্বারা সরলীকৃত frকেবলমাত্র একটি প্যারামিটার নেয় xকরার বিচ্যুত হয়ে x - 1, x - 2: ... পুনরাবৃত্তির মধ্যে)

  • আমরা মূল গণনাগুলি এই হিসাবে সংজ্ঞায়িত করি fn: def fn fr x = ...accumulate x with result from (fr (- x 1))এটি প্রায় কার্যকর কার্য - যদিও আমরা fnসরাসরি ব্যবহার করতে পারি না x, এটি খুব শীঘ্রই কার্যকর হবে। এই পুনরাবৃত্তি তার ফলাফল গণনা করতে fnএকটি ফাংশন ব্যবহার করেfr
  • fn fr = fr, frএর ফিক্স দফা হয় fn, frহয় দরকারী funciton, আমরা ব্যবহার করতে পারেন frউপর xআমাদের ফলাফল পেতে
  • Y fn = fr, Yফেরৎ একটি ফাংশন এর ফিক্স দফা, Y আমাদের সক্রিয় প্রায়-দরকারী ফাংশন fnমধ্যে দরকারী fr

ডেরাইভিং Y(অন্তর্ভুক্ত নয়)

আমি এর উত্সটি এড়িয়ে Yযাব এবং বুঝতে পারব Y। মাইক ভাইয়ের পোস্টে অনেকগুলি বিশদ রয়েছে।

এই ফর্মটি Y

Yহিসাবে সংজ্ঞায়িত করা হয়েছে ( ল্যাম্বদা ক্যালকুলাস ফর্ম্যাটে):

Y f = λs.(f (s s)) λs.(f (s s))

যদি আমরা sফাংশনগুলির বামে ভেরিয়েবলটি প্রতিস্থাপন করি তবে আমরা পাই

Y f = λs.(f (s s)) λs.(f (s s))
=> f (λs.(f (s s)) λs.(f (s s)))
=> f (Y f)

সুতরাং প্রকৃতপক্ষে, ফলাফল এর (Y f)ফিক্স পয়েন্ট f

(Y f)কাজ করে কেন ?

স্বাক্ষর নির্ভর করে f, (Y f)প্রক্রিয়া সহজ করার জন্য, কোনো arity একটি ফাংশন হতে পারে, এর অনুমান করা যাক (Y f)শুধুমাত্র আমাদের গৌণিক ফাংশন মত এক প্যারামিটার নেয়।

def fn fr x = accumulate x (fr (- x 1))

যেহেতু fn fr = fr, আমরা চালিয়ে যাচ্ছি

=> accumulate x (fn fr (- x 1))
=> accumulate x (accumulate (- x 1) (fr (- x 2)))
=> accumulate x (accumulate (- x 1) (accumulate (- x 2) ... (fn fr 1)))

অভ্যন্তরীণ-সর্বাধিক (fn fr 1)বেস কেস এবং গণনায় fnব্যবহার না করা হলে পুনরাবৃত্ত গণনাটি সমাপ্ত হয় fr

Yআবার তাকানো :

fr = Y fn = λs.(fn (s s)) λs.(fn (s s))
=> fn (λs.(fn (s s)) λs.(fn (s s)))

সুতরাং

fr x = Y fn x = fn (λs.(fn (s s)) λs.(fn (s s))) x

আমার কাছে, এই সেটআপের মায়াবী অংশগুলি হ'ল:

  • fnএবং frএকে অপরের উপর নির্ভরশীল: ভিতরে fr'মোড়ানো' fn, প্রতিটি সময় frগণনা করার জন্য ব্যবহৃত হয় x, এটি 'স্প্যানস' ('লিফটস'?) একটি করে fnএবং সেই হিসাবটি fn(নিজের মধ্যে চলে যাওয়া frএবং x) প্রতিনিধিত্ব করে; অন্যদিকে, fnনির্ভর করে frএবং frএকটি ছোট সমস্যার ফলাফল গণনা করতে ব্যবহার করে x-1
  • সময়ে frনির্ধারণ করতে ব্যবহৃত হয় fn(যখন fnব্যবহারসমূহ frতার অপারেশন মধ্যে), বাস্তব frএখনো সংজ্ঞায়িত করা হয় না।
  • এটি fnযা আসল ব্যবসায়ের যুক্তি সংজ্ঞায়িত করে। উপর ভিত্তি করে fn, Yসৃষ্টি করে fr- একটি নির্দিষ্ট আকারে একটি সাহায্যকারী ফাংশন - জন্য গণনা সহজতর fnএকটি রিকার্সিভ পদ্ধতিতে।

Yএই মুহূর্তে এটি আমাকে এইভাবে বুঝতে সহায়তা করেছে , আশা করি এটি সহায়তা করবে।

বিটিডাব্লু, আমি ল্যাম্বডা ক্যালকুলাসের মাধ্যমে আনকোনডাকশন টু ফাংশনাল প্রোগ্রামিংয়ের বইটিও খুব ভাল পেয়েছি, আমি এটির মধ্য দিয়েই এক অংশ এবং Yবইটিতে আমার মাথা পেতে পারি না এই বিষয়টি আমাকে এই পোস্টে নিয়ে যায় led


5

এখানে উত্তর হয় মূল প্রশ্ন থেকে সংকলিত প্রবন্ধ (যা TOTALY পড়া মূল্য) এ উল্লিখিত নিকোলাস থেকে খারাপের খারাপ দ্বারা উত্তর , পাশাপাশি অন্যান্য উত্তর:

ওয়াই-কম্বিনেটর কী?

ওয়াই-কম্বিনেটর হ'ল "ফাংশনাল" (বা একটি উচ্চতর অর্ডার ফাংশন - এমন ফাংশন যা অন্যান্য ফাংশনগুলিতে পরিচালনা করে) যা একটি একক যুক্তি গ্রহণ করে যা এমন ফাংশন যা পুনরাবৃত্তিযোগ্য নয় এবং ফাংশনের একটি সংস্করণ প্রদান করে যা পুনরাবৃত্তি.


কিছুটা পুনরাবৃত্ত =), তবে আরও গভীরতার সংজ্ঞা:

একটি সংযুক্তকারী - এটি কেবল একটি ল্যাম্বডা এক্সপ্রেশন যা কোনও নিখরচায় ভেরিয়েবলগুলি সহ।
ফ্রি ভেরিয়েবল - এমন একটি ভেরিয়েবল যা কোনও সীমাবদ্ধ পরিবর্তনশীল নয়।
বাউন্ডেবল ভেরিয়েবল - ভেরিয়েবল যা ল্যাম্বডা এক্সপ্রেশনের দেহের অভ্যন্তরে থাকে যা এর আর্গুমেন্টগুলির একটি হিসাবে সেই পরিবর্তনশীল নাম রয়েছে।

এ সম্পর্কে ভাবার আরেকটি উপায় হ'ল কম্বিনেটরটি এমন একটি ল্যাম্বডা এক্সপ্রেশন, যেখানে আপনি একটি সংযোজকের নামটি যেখানেই পাওয়া যায় তার সংজ্ঞা দিয়ে এটি প্রতিস্থাপন করতে সক্ষম হন এবং এখনও সমস্ত কিছু কাজ করে থাকে (সংযুক্তকারী যদি আপনি একটি অসীম লুপে প্রবেশ করতে পারেন তবে ল্যাম্বদা দেহের অভ্যন্তরে নিজেই উল্লেখ থাকে।

ওয়াই-কম্বিনেটর একটি স্থির-পয়েন্ট সংযোজক।

কোনও ফাংশনের স্থির বিন্দু হ'ল ফাংশনের ডোমেনের একটি উপাদান যা ফাংশন দ্বারা নিজেই ম্যাপ করা হয়।
অর্থাৎ, cফাংশন একটি নির্দিষ্ট বিন্দু হয় f(x)যদি f(c) = c
এই উপায়েf(f(...f(c)...)) = fn(c) = c

সংযুক্তকারীরা কীভাবে কাজ করবেন?

নীচের উদাহরণগুলিতে দৃ +় + গতিশীল টাইপিং ধরে নেওয়া :

অলস (স্বাভাবিক অর্ডার) ওয়াই-কম্বিনেটর:
এই সংজ্ঞাটি অলস (এছাড়াও পিছিয়ে দেওয়া, কল-বাই প্রয়োজন) মূল্যায়নের সাথে ভাষাগুলির ক্ষেত্রে প্রযোজ্য - মূল্যায়ন কৌশল যা কোনও অভিব্যক্তিটির মূল্য প্রয়োজন না হওয়া পর্যন্ত মূল্যায়ণকে বিলম্ব করে।

Y = λf.(λx.f(x x)) (λx.f(x x)) = λf.(λx.(x x)) (λx.f(x x))

এর অর্থ হ'ল কোনও প্রদত্ত ফাংশনের জন্য f(যা একটি পুনঃবিবেচনামূলক ফাংশন), সংশ্লিষ্ট পুনরাবৃত্তি ফাংশনটি প্রথমে কম্পিউটিংয়ের মাধ্যমে λx.f(x x)এবং তারপরে এই ল্যাম্বডা এক্সপ্রেশনটি নিজে প্রয়োগ করে পাওয়া যায়।

কঠোর (প্রয়োগমূলক-আদেশ) ওয়াই-সংযুক্তকারী:
এই সংজ্ঞাটি কঠোর (এছাড়াও: উত্সাহী, লোভী) মূল্যায়ন সহ ভাষাগুলিতে প্রযোজ্য - মূল্যায়নের কৌশল যেখানে কোনও ভেরিয়েবলের সাথে আবদ্ধ হওয়ার সাথে সাথে কোনও অভিব্যক্তি মূল্যায়ন করা হয়।

Y = λf.(λx.f(λy.((x x) y))) (λx.f(λy.((x x) y))) = λf.(λx.(x x)) (λx.f(λy.((x x) y)))

এটি প্রকৃতির স্বভাবের মতোই λঅলসতার মতো, ল্যাম্বডারের দেহের মূল্যায়ন বিলম্ব করতে এটিতে কেবল অতিরিক্ত মোড়ক রয়েছে। আমি এই বিষয়টির সাথে কিছুটা সম্পর্কিত, আরও একটি প্রশ্ন জিজ্ঞাসা করেছি ।

তারা কি জন্য ভাল?

চুরি ক্রিস আম্মারম্যান উত্তর থেকে ধার নিয়েছিলেন : ওয়াই-কম্বিনেটর পুনরাবৃত্তিকে সাধারণীকরণ করে, এর বাস্তবায়নকে বিমূর্ত করে তোলে এবং এর ফলে এটিকে প্রশ্নবিদ্ধ কার্যের আসল কাজ থেকে আলাদা করে দেয়।

যদিও, ওয়াই-কম্বিনেটরটির কিছু ব্যবহারিক প্রয়োগ রয়েছে, এটি মূলত একটি তাত্ত্বিক ধারণা, যার বোঝা আপনার সামগ্রিক দৃষ্টি প্রসারিত করবে এবং সম্ভবত আপনার বিশ্লেষণাত্মক এবং বিকাশকারী দক্ষতা বৃদ্ধি করবে।

এগুলি কি পদ্ধতিগত ভাষাগুলিতে কার্যকর?

যেমন মাইক Vanier বলেছেন : এটা অনেক স্ট্যাটিক্যালি টাইপ ভাষায় একটি ওয়াই combinator সংজ্ঞায়িত করা সম্ভব হয়, কিন্তু (উদাহরণ আমি দেখেছি অন্তত) যেমন সংজ্ঞা সাধারণত কিছু অ সুস্পষ্ট টাইপ গোরুর গাড়ি প্রয়োজন, কারণ ওয়াই combinator নিজেই doesn ' t এর একটি সোজা স্ট্যাটিক প্রকার রয়েছে। এটি এই নিবন্ধের আওতার বাইরে, সুতরাং আমি এটি আর উল্লেখ করব না

এবং হিসাবে ক্রিস আম্মারম্যান উল্লেখ করেছেন : বেশিরভাগ পদ্ধতিগত ভাষায় স্থির-টাইপ থাকে।

সুতরাং এই উত্তর - সত্য না।


4

Y- সংযুক্তকারী বেনামে পুনরুক্তি প্রয়োগ করে। পরিবর্তে তাই

function fib( n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }

আপনি করতে পারেন

function ( fib, n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }

অবশ্যই, ওয়াই-কম্বিনেটর কেবল কল-বাই-নাম ভাষায় কাজ করে। আপনি যদি কোনও সাধারণ কল-বাই-মান ভাষায় এটি ব্যবহার করতে চান, তবে আপনার সম্পর্কিত জেড-কম্বিনেটর (y- কম্বিনেটরটি ডাইভার্জ / অনন্ত-লুপ) প্রয়োজন হবে need


ওয়াই সংযুক্তকারী পাস-বাই-মান এবং অলস মূল্যায়নের সাথে কাজ করতে পারে।
কোয়েলক্লেফ

3

একটি নির্দিষ্ট পয়েন্ট সমন্বয়কারী (বা স্থির-পয়েন্ট অপারেটর) হ'ল-অর্ডার ফাংশন যা অন্যান্য ফাংশনের একটি নির্দিষ্ট পয়েন্টকে গণনা করে। প্রোগ্রামিং ভাষা তত্ত্বে এই অপারেশনটি প্রাসঙ্গিক কারণ এটি ভাষার রানটাইম ইঞ্জিনের সুস্পষ্ট সমর্থন ছাড়াই পুনর্লিখনের নিয়মের আকারে পুনরাবৃত্তি বাস্তবায়নের অনুমতি দেয়। (এসআরসি উইকিপিডিয়া)


3

এই অপারেটর আপনার জীবন সহজ করতে পারে:

var Y = function(f) {
    return (function(g) {
        return g(g);
    })(function(h) {
        return function() {
            return f.apply(h(h), arguments);
        };
    });
};

তারপরে আপনি অতিরিক্ত ক্রিয়াকলাপটি এড়িয়ে চলুন:

var fac = Y(function(n) {
    return n == 0 ? 1 : n * this(n - 1);
});

অবশেষে, আপনি কল fac(5)


0

আমি মনে করি এর উত্তর দেওয়ার সর্বোত্তম উপায় হ'ল জাভা স্ক্রিপ্টের মতো একটি ভাষা বাছাই:

function factorial(num)
{
    // If the number is less than 0, reject it.
    if (num < 0) {
        return -1;
    }
    // If the number is 0, its factorial is 1.
    else if (num == 0) {
        return 1;
    }
    // Otherwise, call this recursive procedure again.
    else {
        return (num * factorial(num - 1));
    }
}

এখন এটি পুনরায় লিখুন যাতে এটি ফাংশনের ভিতরে ফাংশনের নামটি ব্যবহার না করে তবে এটি পুনরাবৃত্তভাবে বলে।

ফাংশনটির নামটি factorialদেখা উচিত এমন একমাত্র স্থানটি কল সাইটে।

ইঙ্গিত: আপনি ফাংশনগুলির নাম ব্যবহার করতে পারবেন না, তবে আপনি পরামিতিগুলির নাম ব্যবহার করতে পারেন।

সমস্যা কাজ। এটি তাকান না। আপনি এটি সমাধান করার পরে, আপনি বুঝতে পারবেন যে ওয়াই-কম্বিনেটর কী সমস্যার সমাধান করে।


1
আপনি কি নিশ্চিত যে এটি সমাধানের চেয়ে বেশি সমস্যা তৈরি করে না?
নোকটিস স্কাইটওয়ার

1
রাতে, আপনি আপনার প্রশ্ন পরিষ্কার করতে পারেন? আপনি কি জিজ্ঞাসা করছেন যে কোনও ওয়াই-কম্বিনেটর ধারণাটি নিজেই এর সমাধানের থেকে আরও বেশি সমস্যার সৃষ্টি করে, বা আপনি বিশেষত জাভা স্ক্রিপ্ট ব্যবহার করে বা আমার নির্দিষ্ট প্রয়োগকরণ বা এটির নিজের হিসাবে আবিষ্কার করে এটি শিখতে আমার প্রস্তাবনাটি বেছে নেওয়ার বিষয়ে বিশেষভাবে কথা বলছেন? আমি বর্ণনা করেছি?
zumalifeguard
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.