2009-02-24 8 views
53

Jamie Zawinski अपने (1997) article "java sucks" में उस शब्द के रूप में अगर आपको पता होना चाहिए कि इसका क्या मतलब का उपयोग करता है:"डाउनवर्ड मजेदार" क्या हैं?

मैं वास्तव में नीचे की funargs की कमी से नफरत है; गुमनाम वर्ग एक लंगड़ा विकल्प हैं। (मैं लंबे समय से रहते थे बंदी बिना रह सकते हैं, लेकिन मैं समारोह की कमी एक बड़ी दर्द सूचक मात्र हैं।)

यह Lisper की खिचड़ी प्रतीत हो रहा है, और मैं मिल सकता है संक्षिप्त परिभाषा here, लेकिन किसी भी तरह, मुझे लगता है कि निम्नलिखित मुझे अभी भी यह नहीं मिला:

कई बंदरगाहों का उपयोग केवल बाइंडिंग की सीमा के दौरान ही किया जाता है; इन्हें लिस्प पार्लान्स में "डाउनवर्ड मजेदार" के रूप में जाना जाता है।

यह Steve Yegge के लिए नहीं थे, मैं सिर्फ अब बेवकूफ लग रहा था, लेकिन ऐसा लगता है, यह पूछने के लिए ठीक हो सकता है:

जेमी ज़विन्सकी एक हीरो है। एक जीवित किंवदंती। [...] एक लड़का जो "डाउनवर्ड फ़ेगर्ग" शब्द का उपयोग कर सकता है और फिर आप पर चमक कर सकता है, बस आपको उसे समझाने के लिए कहने के लिए साहसी करता है, आप cretin।

- XEmacs is dead, long live XEmacs

तो वहाँ यहाँ एक Lisper जो मेरे जैसे सी-शैली-प्रोग्रामर के लिए यह संकलन कर सकते हैं?

+1

मुझे लगता है कि jwz क्या मतलब है, जबकि यह समझा जा सकता है कि सामान्य रूप में funargs जावा में समर्थित नहीं हैं, नीचे की ओर funargs चर जिस पर बंद हो जाती हैं की नियमित ढेर-आधारित भंडारण के लिए किसी भी परिवर्तन के बिना समर्थित जा सकता था। "Funarg_problem" पर विकिपीडिया पृष्ठ वास्तव में इसके बारे में बहुत स्पष्ट है। –

उत्तर

50

डाउनवर्ड फ़ंक्शन स्थानीय फ़ंक्शंस हैं जो वापस नहीं आते हैं या अन्यथा उनके घोषणा दायरे को छोड़ देते हैं। वे वर्तमान क्षेत्र से अन्य कार्यों के लिए केवल नीचे पारित किया जा सकता है।

दो उदाहरण।

function() { 
    var a = 42; 
    var f = function() { return a + 1; } 
    foo(f); // `foo` is a function declared somewhere else. 
} 

हालांकि यह नहीं है::

function() { 
    var a = 42; 
    var f = function() { return a + 1; } 
    return f; 
} 
+0

पहला उदाहरण कहना चाहिए वर foo = समारोह ... –

+0

ईसाई: ठीक है, पहले का तात्पर्य है कि 'foo' एक समारोह में परिभाषित * कहीं भी *, जरूरी नहीं कि स्थानीय स्तर पर है। मैं इसे स्पष्ट कर दूंगा। –

+7

मुख्य मुद्दा यह है कि एक ढेर जब च मार डाला जाता है पर है, तो यह (एक तथाकथित बंद में ढेर पर आमतौर पर एक साथ च) के साथ कहीं और स्टोर करने के लिए कोई जरूरत नहीं है। तो "डाउनवर्ड मजेदार" "मजेदार" का आसान हिस्सा है। – starblue

11

वहाँ विकी पर एक बहुत वर्णनात्मक लेख कहा जाता Funarg problem

"एक नीचे की ओर funarg भी एक समारोह के राज्य जब कि समारोह वास्तव में क्रियान्वित नहीं है। हालांकि, का उल्लेख कर सकते है, क्योंकि, परिभाषा के द्वारा, अस्तित्व नीचे दिए गए मज़ेदार में फ़ंक्शन का निष्पादन है जो बनाता है, के लिए सक्रियण रिकॉर्ड आमतौर पर स्टैक पर संग्रहीत हो सकता है। "

13

कॉमन लिस्प में:

(let ((a 3)) 
    (mapcar (lambda (b) (+ a b)) 
      (list 1 2 3 4))) 

-> (4 5 6 7) 

ऊपर दिए गए फ़ॉर्म में लैम्ब्डा समारोह नीचे पारित कर दिया है यह एक नीचे funarg है। जब उच्च-आदेश फ़ंक्शन MAPCAR द्वारा कॉल किया जाता है (जो एक फ़ंक्शन और मानों की सूची को तर्क के रूप में प्राप्त करता है, और तब सूची के प्रत्येक तत्व में फ़ंक्शन लागू करता है और परिणामों की एक सूची देता है), लैम्ब्डा फ़ंक्शन अभी भी चर को संदर्भित करता है एलईटी अभिव्यक्ति से 'ए'। लेकिन यह एलईटी अभिव्यक्ति के भीतर होता है।

इस संस्करण के साथ ऊपर की तुलना करें:

(mapcar (let ((a 3)) 
      (lambda (b) (+ a b))) 
     (list 1 2 3 4)) 

यहाँ लैम्ब्डा देना समारोह से वापस आ रहा है। थोड़ा सा ऊपर। यह तब मकर को पास हो जाता है। जब एमएपीसीएआर लैम्ब्डा फ़ंक्शन को कॉल करता है, तो इसके आसपास के एलईटी अब निष्पादित नहीं होते हैं - फिर भी फ़ंक्शन को एलईटी से चर 'ए' को संदर्भित करने की आवश्यकता होती है।

24

बेहतर समझने के लिए जहाँ शब्द आता है, से आप कुछ इतिहास जानना चाहते हैं।

कारण है कि एक पुराने लिस्प हैकर सामान्य रूप में funargs से नीचे funargs भेद हो सकता है कि नीचे funargs, एक पारंपरिक लिस्प कि शाब्दिक चर का अभाव में लागू करना आसान है, जबकि सामान्य स्थिति कठिन है।

परंपरागत रूप से एक स्थानीय चर पर्यावरण करने के लिए एक बाध्यकारी (चर का प्रतीक नाम, अपने मूल्य के साथ जोड़ा) जोड़कर एक लिस्प दुभाषिया में लागू किया गया था। ऐसा वातावरण एक एसोसिएशन सूची का उपयोग करके लागू करना आसान था। प्रत्येक समारोह में अपना पर्यावरण था, और पैरेंट फ़ंक्शन के पर्यावरण के लिए एक सूचक था। वर्तमान वातावरण में देखकर एक परिवर्तनीय संदर्भ हल किया गया था, और यदि वहां नहीं मिला, तो माता-पिता वातावरण में, और पर्यावरण के ढेर तक वैश्विक वातावरण तक पहुंचने तक।

ऐसे कार्यान्वयन में, स्थानीय चर छाया उसी नाम के साथ वैश्विक चर। उदाहरण के लिए, Emacs लिस्प में, print-length एक वैश्विक चर निर्दिष्ट करता है कि सूची की अधिकतम लंबाई यह abbreviating से पहले मुद्रित करने के लिए है। एक समारोह के लिए कॉल के आसपास इस चर जुड़ कर आपको लगता है कि समारोह के भीतर प्रिंट बयान के व्यवहार को बदल सकते:

 
(defun foo() (print '(1 2 3 4 5 6))) ; output depends on the value of print-length 

(foo) ; use global value of print-length 
    ==> (1 2 3 4 5 6) 

(let ((print-length 3)) (foo)) ; bind print-length locally around the call to foo. 
    ==> (1 2 3 ...) 

आप देख सकते हैं कि इस तरह के एक कार्यान्वयन में, नीचे funargs, लागू करने के लिए वास्तव में आसान कर रहे हैं क्योंकि चर जब यह बनाया गया है तो फ़ंक्शन के वातावरण में तब भी कार्य के माहौल में होगा जब मूल्यांकन किया जाता है।

चर है कि इस तरह काम करते हैं विशेष या गतिशील चर कहा जाता है, और आप special घोषणा का उपयोग कर कॉमन लिस्प में उन्हें बना सकते हैं।

संबंधित मुद्दे