ऐसा लगता है कि आप कुछ नुकसान और फायदों से पहले ही परिचित हैं।
कुछ दूसरों: क) उचित पूंछ कॉल अनुकूलन का समर्थन करने के लिए यह संभव बनाता है, भले ही अंतर्निहित कार्यान्वयन यह ख) आसान एक भाषा के स्तर "स्टैक ट्रेस" ग) आसान जैसी चीजों का निर्माण करने के लिए कोई समर्थन नहीं है उचित निरंतरता जोड़ने के लिए, जैसा कि आपने
पर हाल ही में सी # में एक सरल "योजना" दुभाषिया लिखा था, जिसने शुरुआत में .NET स्टैक का उपयोग किया था। मैं तो एक स्पष्ट ढेर उपयोग करने के लिए फिर से लिखा था यह - तो शायद निम्नलिखित तुम्हारी मदद करेगा:
पहले संस्करण निहित .NET रनटाइम ढेर इस्तेमाल किया ...
प्रारंभ में, यह सिर्फ एक वर्ग पदानुक्रम था, विभिन्न रूपों (लैम्ब्डा, आइए, आदि) निम्नलिखित इंटरफेस की जा रही है कार्यान्वयन के साथ:
// A "form" is an expression that can be evaluted with
// respect to an environment
// e.g.
// "(* x 3)"
// "x"
// "3"
public interface IForm
{
object Evaluate(IEnvironment environment);
}
IEnvironment देखा के रूप में आप उम्मीद थी:
/// <summary>
/// Fundamental interface for resolving "symbols" subject to scoping.
/// </summary>
public interface IEnvironment
{
object Lookup(string name);
IEnvironment Extend(string name, object value);
}
जोड़ने के लिए "
/// <summary>
/// A function is either a builtin function (i.e. implemented directly in CSharp)
/// or something that's been created by the Lambda form.
/// </summary>
public interface IFunction
{
object Invoke(object[] args);
}
था कि जब यह अंतर्निहित .NET रनटाइम ढेर प्रयोग किया है: मेरी योजना दुभाषिया के लिए builtins ", मैं शुरुआत में निम्नलिखित इंटरफेस था। निश्चित रूप से कम कोड था, लेकिन उचित पूंछ रिकर्सन जैसी चीज़ों को जोड़ना असंभव था, और सबसे महत्वपूर्ण बात यह है कि मेरे दुभाषिया के लिए रनटाइम त्रुटि के मामले में "भाषा स्तर" स्टैक ट्रेस प्रदान करने में सक्षम होना अजीब था।
तो मैं इसे एक स्पष्ट (ढेर आवंटित) ढेर के लिए फिर से लिखता हूं।
मेरे "IFunction" इंटरफेस, निम्नलिखित को बदलने के लिए इतना है कि मैं "नक्शा" और "लागू करें" जैसी चीजों है, जो योजना दुभाषिया में वापस बुलाने को लागू कर सकता था:
/// <summary>
/// A function that wishes to use the thread state to
/// evaluate its arguments. The function should either:
/// a) Push tasks on to threadState.Pending which, when evaluated, will
/// result in the result being placed on to threadState.Results
/// b) Push its result directly on to threadState.Results
/// </summary>
public interface IStackFunction
{
void Evaluate(IThreadState threadState, object[] args);
}
और iform करने के लिए बदल :
public interface IForm
{
void Evaluate(IEnvironment environment, IThreadState s);
}
IThreadState इस प्रकार कहाँ है के रूप में:
/// <summary>
/// The state of the interpreter.
/// The implementation of a task which takes some arguments,
/// call them "x" and "y", and which returns an argument "z",
/// should follow the following protocol:
/// a) Call "PopResult" to get x and y
/// b) Either
/// i) push "z" directly onto IThreadState using PushResult OR
/// ii) push a "task" on to the stack which will result in "z" being
/// pushed on to the result stack.
///
/// Note that ii) is "recursive" in its definition - that is, a task
/// that is pushed on to the task stack may in turn push other tasks
/// on the task stack which, when evaluated,
/// ... ultimately will end up pushing the result via PushResult.
/// </summary>
public interface IThreadState
{
void PushTask(ITask task);
object PopResult();
void PushResult(object result);
}
और ITask है:
public interface ITask
{
void Execute(IThreadState s);
}
और अपने मुख्य "घटना" पाश है:
ThreadState threadState = new ThreadState();
threadState.PushTask(null);
threadState.PushTask(new EvaluateForm(f, environment));
ITask next = null;
while ((next = threadState.PopTask()) != null)
next.Execute(threadState);
return threadState.PopResult(); // Get what EvaluateForm evaluated to
EvaluateForm सिर्फ एक काम है कि एक विशेष वातावरण के साथ IForm.Evaluate कॉल है।
व्यक्तिगत रूप से, मुझे यह नया संस्करण एक कार्यान्वयन बिंदु से काम करने के लिए बहुत अधिक "अच्छा" मिला - एक स्टैक ट्रेस प्राप्त करना आसान है, इसे पूर्ण निरंतर कार्यान्वित करने में आसान है (हालांकि ... मैंने यह नहीं किया है अभी तक - सी # स्टैक का उपयोग करने के बजाय लगातार "स्टैक्स" को लगातार लिंक-सूचियां बनाने की आवश्यकता है, और आईटास्क इसे नए मल्टीस्टेट को "इसे वापस करने" के बजाय "थ्रेडस्टेट" देता है ताकि मेरे पास "कॉल-निरंतरता" कार्य हो) ... आदि। आदि
असल में, आप अंतर्निहित भाषा कार्यान्वयन पर केवल कम निर्भर हैं।
मुझे केवल एक ही नकारात्मक पक्ष के बारे में पता चल सकता है ... लेकिन मेरे मामले में, यह सिर्फ एक दुभाषिया है इसलिए मुझे प्रदर्शन के बारे में बहुत कुछ परवाह नहीं है।
मैं भी की फिर से लिखने के एक ढेर के साथ पुनरावृत्ति कोड के रूप में पुनरावर्ती कोड, काई सी ++ संकलक के लेखकों में से एक द्वारा लाभ पर यह बहुत ही अच्छा लेख के लिए आप बात करेंगे: Considering Recursion
दरअसल, प्रश्न मूल कोड एकीकरण पर विचार करने के लिए डाउनसाइड्स के बारे में था। लेकिन कहानी के लिए धन्यवाद। –