বেনামে পুনরাবৃত্ত পিএইচপি ফাংশন


197

এটি কি পিএইচপি ফাংশন থাকা সম্ভব যা পুনরাবৃত্ত এবং বেনামে উভয়ই? এটি কাজ করার জন্য এটি আমার চেষ্টা, তবে এটি ফাংশনটির নামে পাস করে না।

$factorial = function( $n ) use ( $factorial ) {
    if( $n <= 1 ) return 1;
    return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );

আমি আরও সচেতন যে এটি কৌতুক বাস্তবায়ন করার একটি খারাপ উপায়, এটি কেবল একটি উদাহরণ।


আমার কাছে চেক করার জন্য পিএইচপি 5.3.0 নেই তবে আপনি কি ব্যবহারের চেষ্টা করেছিলেন global $factorial?
কেনেটিএম

5
(সিডনোট) একটি লাম্বা একটি বেনামি ফাংশন, যখন উপরেরটি বন্ধ রয়েছে।
গর্ডন

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

1
print $factorial( 0);
নিক

পিএইচপি ম্যানুয়াল উদাহরণ

উত্তর:


355

এটি কাজ করার জন্য আপনাকে একটি রেফারেন্স হিসাবে ফ্যাক্টরিয়াল পাস করতে হবে

$factorial = function( $n ) use ( &$factorial ) {
    if( $n == 1 ) return 1;
    return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );

এটি অদ্ভুত বিসি অবজেক্টগুলি সর্বদা রেফারেন্স এবং অনন দ্বারা পাস করা উচিত। ফাংশনগুলি
হ'ল

25
@ ইলাবায়িউটি সেই সময়ে $ কিতাবটি পাস হয়েছে, এটি এখনও নাল (সংজ্ঞায়িত নয়), এজন্য আপনাকে এটিকে রেফারেন্স দিয়ে পাস করতে হবে। সচেতন থাকুন, আপনি যদি ফাংশনটি কল করার আগে ফ্যাক্টরিয়ালটি সংশোধন করেন তবে রেফারেন্স অনুসারে এটি পাস করার সাথে সাথে ফলাফলটি পরিবর্তিত হবে।
মারিয়াস বালিয়েটিস

9
@ ইলাবায়িউটি: না, আপনি এটি পুরোপুরি ভুল বুঝবেন। ব্যতীত সমস্ত কিছু &মূল্য দিয়ে। সহ সবকিছু &রেফারেন্স সহ। "অবজেক্টস" পিএইচপি 5 এ মান হয় না এবং বরাদ্দ বা পাস করা যায় না। আপনি এমন একটি ভেরিয়েবলের সাথে কাজ করছেন যার মান একটি অবজেক্ট রেফারেন্স। সমস্ত ভেরিয়েবলের মতো এটির মান নির্ভর করে বা রেফারেন্স দ্বারা ক্যাপচার করা যেতে পারে, এটির উপর নির্ভর করে কোনও আছে কিনা &
newacct

3
মন উড়িয়ে! অনেক ধন্যবাদ! আমি এখন পর্যন্ত এই সম্পর্কে কিভাবে জানতাম না? পুনরাবৃত্তিক বেনামি কার্যগুলির জন্য আমার কাছে যে পরিমাণ অ্যাপ্লিকেশন রয়েছে তা বিশাল। এখন আমি অবশেষে বিন্যাসে কোনও পদ্ধতি স্পষ্টভাবে সংজ্ঞায়িত না করে এবং আমার সমস্ত লেআউট ডেটা আমার ক্লাসের বাইরে রেখেই বিন্যাসে নেস্টেড স্ট্রাকচারগুলি লুপ করতে পারি।
ডিয়েটার গ্রিবনিটস

@ বারিয়াস যেমন বলেছেন, ভবিষ্যতে এটি ব্যবহার করার সময় সাবধানতা অবলম্বন করুন। $factorialফাংশন বলার আগে পরিবর্তন করা হবে এবং এর ফলে অদ্ভুত আচরণের ফলাফল হতে পারে।
stil

24

আমি জানি এটি একটি সহজ পদ্ধতির নাও হতে পারে তবে আমি কার্যকরী ভাষা থেকে "ফিক্স" নামক একটি কৌশল সম্পর্কে শিখেছি । fixHaskell, থেকে ফাংশন হিসাবে আরো সাধারণভাবে পরিচিত হয় ওয়াই combinator , যা সবচেয়ে সুপরিচিত এক নির্দিষ্ট বিন্দু combinators

একটি নির্দিষ্ট বিন্দু এমন একটি মান যা কোনও ফাংশন দ্বারা অপরিবর্তিত থাকে: ফাংশন এফের একটি নির্দিষ্ট বিন্দু এমন কোনও এক্স যেমন x = f (x)। একটি স্থির বিন্দু সংমিশ্রণ y একটি ফাংশন যা কোনও ফাংশনের জন্য একটি নির্দিষ্ট পয়েন্ট ফেরত দেয়। যেহেতু y (f) f এর একটি নির্দিষ্ট বিন্দু, তাই আমাদের y (f) = f (y (f)) থাকে।

মূলত, ওয়াই কম্বিনেটর একটি নতুন ফাংশন তৈরি করে যা মূলগুলির সমস্ত আর্গুমেন্ট গ্রহণ করে, এবং অতিরিক্ত যুক্তি যা পুনরাবৃত্তির কাজ করে। এটি কীভাবে তীক্ষ্ণ স্বরলিপি ব্যবহার করে আরও সুস্পষ্ট। পরিবর্তে বন্ধনীর মধ্যে আর্গুমেন্ট লেখার ( f(x,y,...)), তাদের ফাংশন পর লিখুন: f x y ...। ওয়াই সংযুক্তকারী হিসাবে সংজ্ঞায়িত করা হয় Y f = f (Y f); বা, পুনরাবৃত্তি ফাংশন জন্য একক যুক্তি সহ Y f x = f (Y f) x,।

যেহেতু পিএইচপি স্বয়ংক্রিয়ভাবে কার্যগুলি কারি করে না , fixকাজ করার জন্য এটি কিছুটা হ্যাক , তবে আমি মনে করি এটি আকর্ষণীয়।

function fix( $func )
{
    return function() use ( $func )
    {
        $args = func_get_args();
        array_unshift( $args, fix($func) );
        return call_user_func_array( $func, $args );
    };
}

$factorial = function( $func, $n ) {
    if ( $n == 1 ) return 1;
    return $func( $n - 1 ) * $n;
};
$factorial = fix( $factorial );

print $factorial( 5 );

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


10
এটি call_user_func_array()ক্রিসমাস হিসাবে ধীর যে লক্ষণীয় ।
শিওনক্রস

11
@ এক্সনক্রস বাকি পিএইচপি বিরোধী যা স্থল গতির রেকর্ড স্থাপন করছে? : পি
কেন্ডাল হপকিন্স

1
দ্রষ্টব্য, আপনি এখন (5.6+) এর পরিবর্তে যুক্তি আনপ্যাকিং ব্যবহার করতে পারেন call_user_func_array
ফাবিয়েন সা

@ কেনডালহপकिनস কেন এই অতিরিক্ত যুক্তি array_unshift( $args, fix($func) );? আরোগুলি ইতিমধ্যে পরামিতিগুলি দিয়ে বোঝা হয়েছে, এবং প্রকৃত পুনরাবৃত্তি কল_ইউজার_ফুনস_আরে () দ্বারা সম্পন্ন হয়, সুতরাং সেই লাইনটি কী করে?
আমি উত্তরগুলি চাই

5

যদিও এটি ব্যবহারিক ব্যবহারের জন্য নয়, সি-লেভেল এক্সটেনশন এমপিইউ-জঞ্জস / পিপ্পেক্সট-ক্যালি ভেরিয়েবলগুলি বরাদ্দ না করে বেনামে পুনরাবৃত্তি সরবরাহ করে ।

<?php

var_dump((function ($n) {
    return $n < 2 ? 1 : $n * callee()($n - 1);
})(5));

// 5! = 5 * 4 * 3 * 2 * 1 = int(120)

0

পিএইচপি এর নতুন সংস্করণগুলিতে আপনি এটি করতে পারেন:

$x = function($depth = 0) {
    if($depth++)
        return;

    $this($depth);
    echo "hi\n";
};
$x = $x->bindTo($x);
$x();

এটি সম্ভবত অদ্ভুত আচরণের দিকে পরিচালিত করতে পারে।


0

আপনি নীচের মতো পিএইচপি 7.1+ এ ওয়াই কম্বিনেটর ব্যবহার করতে পারেন:

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

$le =
function ($factorial)
{return
    function
    ($n) use ($factorial)
    {return
        $n < 2 ? $n
        : $n * $factorial($n - 1);
    };
};

$factorial = Y($le);

echo $factorial(1) . PHP_EOL; // 1
echo $factorial(2) . PHP_EOL; // 2
echo $factorial(5) . PHP_EOL; // 120

এটি খেলুন: https://3v4l.org/7AUn2

উত্স কোডগুলি থেকে: https://github.com/ whitephp/the-little-phper/blob/master/ src / chapter_9.php


0

কোনও ভেরিয়েবল সংজ্ঞায়িত না করে একটি বেনাম শ্রেণীর (পিএইচপি 7+) ​​সহ:

echo (new class {
    function __invoke($n) {
        return $n < 2 ? 1 : $n * $this($n - 1);
    }
})(5);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.