2017-11-27 27 views
7

मैं गुना कम हो/से एन-कार्यों के लिए एक संरचना समारोह प्राप्त करने के लिए चाहते हैं, लेकिन यह अपेक्षा के अनुरूप काम नहीं करता है:रिटर्न रिटर्न को कम करके मेरे फ़ंक्शन कंपोज़िशन को लागू क्यों किया जाता है?

$id = function ($x) { 
    return $x; 
}; 

$comp = function ($f) { 
    return function ($g) use ($f) { 
    return function ($x) use ($f, $g) { 
     return $f($g($x)); 
    }; 
    }; 
}; 

$fold = function ($f, $acc) { 
    return function ($xs) use ($f, &$acc) { 
    return array_reduce($xs, $f, $acc); 
    }; 
}; 

$compn = function($fs) {/* apply $fold here */}; 

$inc = function ($n) { 
    return $n + 1; 
}; 

$fold($comp, $id) ([$inc, $inc, $inc]) (0); // yields a closure instead of 3 

मैं एक ही समारोह जावास्क्रिप्ट में कार्यान्वित किया है और यह काम करता है। मैं PHP 7.0.8 क्ली का उपयोग करता हूं। मुझे PHP के बारे में बहुत कुछ पता नहीं है, इसलिए शायद मैं कुछ दिख रहा हूं।

+0

कार्यात्मक प्रोग्रामिंग PHP में अच्छी तरह से महसूस नहीं करता है यह अच्छी तरह से महसूस नहीं करता है के रूप में कॉल जावास्क्रिप्ट में या तो। इन भाषाओं को बस एफपी के लिए डिजाइन नहीं किया गया था। यह किया जा सकता है, जैसा कि आप पहले से ही पता चला है, लेकिन यह बहुत सारे कोड है जिसके लिए आपको अपनी इच्छित दिशा में धक्का देने के लिए कई सारी चाल की आवश्यकता होती है। यह एक अभ्यास के रूप में अच्छा है लेकिन मैं इसे उत्पादन में उपयोग नहीं करता। कम से कम PHP में, एक समकक्ष ओओपी समाधान (शायद [धाराप्रवाह इंटरफ़ेस] के साथ (https://martinfowler.com/bliki/FluentInterface.html) अधिक पठनीय है और आपके इच्छित एपीआई को कम या ज्यादा प्रदान करता है। – axiac

उत्तर

2

आपका $compcurried है, और निश्चित रूप से आप की खोज की पीएचपी की मूल array_reduce फ़ंक्शन को कई मानकों को स्वीकार करने की अपेक्षा करता है - uncurry का एक त्वरित अनुप्रयोग आपके दर्द के कुछ लेता है, लेकिन यदि आप देखना चाहते हैं कि इसे समग्र रूप से कैसे सुधार किया जा सकता है, तो आपको पढ़ने की आवश्यकता होगी ...


PHP के विनम्र राय में ...

uncurry का उपयोग करते हुए काम कर देता है, लेकिन आप शायद अपने कार्यक्रम नापसंद पहुंच जाएंगे, तो सभी कार्यों $ -named चर के रूप में परिभाषित कर रहे हैं - मुझे उस शैली का उपयोग करके बहुत सी छोटी समस्याएं हैं।

पीएचपी एक callable "प्रकार" जो बातें करता है थोड़ा और पीएचपी-ish है - (उच्च क्रम कार्यों सहित) उपयोगकर्ता परिभाषित कार्यों अब आप अपने compn साथ call_user_func और call_user_func_array

namespace my\module; 

function identity ($x) { 
    return $x; 
} 

function comp ($f) { 
    return function ($g) use ($f) { 
    return function ($x) use ($f, $g) { 
     return call_user_func ($f, call_user_func ($g, $x)); 
    }; 
    }; 
} 

function uncurry ($f) { 
    return function ($x, $y) use ($f) { 
    return call_user_func (call_user_func ($f, $x), $y); 
    }; 
} 

function fold ($f, $acc) { 
    return function ($xs) use ($f, $acc) { 
    return array_reduce ($xs, uncurry ($f), $acc); 
    }; 
} 

का उपयोग कर बुलाया जाना चाहिए variadic इंटरफेस के रूप में उम्मीद

function compn (...$fs) { 
    return fold ('comp', 'identity') ($fs); 
} 

function inc ($x) { 
    return $x + 1; 
} 

echo compn ('inc', 'inc', 'inc') (0); // 3 

काम करता है लेकिन यह गुमनाम कार्यों के साथ भी

काम करता है
$double = function ($x) { return $x + $x; }; 

echo compn ($double, $double, 'inc') (2); // 12 

कार्यात्मक कोड, मॉड्यूलर कार्यक्रम

अपने कार्यों के साथ function सिंटेक्स के उपयोग की घोषणा की, आप उन्हें अपने कार्यक्रम

// single import 
use function my\module\fold; 

// aliased import 
use function my\module\fold as myfold; 

// multiple imports 
use function my\module\{identity, comp, compn, fold}; 

के अन्य क्षेत्रों में import कर सकते हैं और अब आप डॉन आपको use -blocks के साथ कोड को कूड़ा नहीं करना है जब भी आप अपने कार्यों में से किसी एक का उपयोग करना चाहते हैं

// before 
$compn = function (...$fs) use ($fold, $comp, $id) { 
    return $fold($comp, $id) ($fs); 
}; 

// after 
function compn (...$fs) { 
    return fold ('comp', 'id') ($fs); 
} 

यह डिबगिंग की बात आती है, इसमें कोई शक नहीं नामित कार्यों और अधिक उपयोगी स्टैक ट्रेस संदेश के रूप में अच्छी तरह से


प्रासंगिक लेकिन महत्वहीन

पीएचपी अन्य कारणों से है प्रदान करेगा कॉल करने योग्य प्रकार जोड़ने के लिए, लेकिन मुझे यकीन है कि चिंता न करें आप के रूप में वे कर रहे हैं OOP से संबंधित - जैसे,

वर्ग विधि

// MyClass::myFunc (1); 
call_user_func (['MyClass', 'myFunc'], 1); 

वस्तु प्रणाली को बुलाती है

// $me->myfunc (1); 
call_user_func ([$me, 'myfunc'], 1); 
+0

डॉन ' मुझे गलत नहीं लगता है, पीएचपी का कॉल करने योग्य "टाइप" घृणित है - यह जावास्क्रिप्ट के 'सेटटाइमआउट' की याद दिलाता है जो एक स्ट्रिंग को स्वीकार करता है जिसका उपयोग वैश्विक पर्यावरण में किसी फ़ंक्शन को देखने के लिए किया जा सकता है - PHP आपको नामों को तर्क के रूप में पास करने की अनुमति नहीं देता है अन्य कार्यों, इसलिए मुझे इसके चारों ओर एक और व्यावहारिक तरीके से पता नहीं है। – naomik

+0

PHP का कॉल करने योग्य प्रकार स्ट्रिंग क्वालीफायरों में नामस्थान स्वीकार करता है - उदाहरण के लिए '' मेरा \ मॉड्यूल \ foo'' - लेकिन अगर आप इसका उपयोग कर रहे हैं तो देखें डबल कोट्स! आपको स्लैश से बचना चाहिए "मेरा \\ मॉड्यूल \\ foo" '- गॉचाचा – naomik

+0

के बाद गॉचाचा शायद आप अपने प्रोग्राम को नापसंद कर देंगे यदि सभी कार्यों को $ नामित चर के रूप में परिभाषित किया गया है, तो मैं करता हूं। लेकिन स्ट्रिंग्स के रूप में कार्य एक हैं wkward भी: 'compn ($ डबल, $ डबल, 'inc')'। वैसे भी, इससे बहुत मदद मिली, धन्यवाद! – ftor

2

मुझे यह पता चला: array_reduce एक बहु-तर्क समारोह के रूप में $f पर कॉल करता है। तो मैं एक और गुमनाम समारोह शुरू करने की है:

$id = function ($x) { 
    return $x; 
}; 

$comp = function ($f) { 
    return function ($g) use ($f) { 
    return function ($x) use ($f, $g) { 
     return $f($g($x)); 
    }; 
    }; 
}; 

$fold = function ($f, $acc) { 
    return function ($xs) use ($f, &$acc) { 
    return array_reduce($xs, function ($acc_, $x) use ($f) { 
//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
     return $f($acc_) ($x); 
    }, $acc); 
    }; 
}; 

$compn = function($fs) {/* apply $fold here */}; 

$inc = function ($n) { 
    return $n + 1; 
}; 

echo $fold($comp, $id) ([$inc, $inc, $inc]) (0); // yields 3 

और यहाँ है कम करने/आवरण गुना एक अच्छे एपीआई पाने के लिए:

$compn = function (...$fs) use ($fold, $comp, $id) { 
    return $fold($comp, $id) ($fs); 
}; 

$compn($inc, $inc, $inc) (0); 
संबंधित मुद्दे