पायथन डेकोरेटर्स और लिस्प मैक्रोज़


18

जब पायथन डेकोरेटर्स को देखते हुए किसी ने बयान दिया, कि वे लिस्प मैक्रोज़ (विशेष रूप से क्लीजुर) के समान शक्तिशाली हैं।

PEP 318 में दिए गए उदाहरणों को देखते हुए यह मुझे ऐसा लगता है जैसे वे लिस्प में सादे पुराने उच्च-क्रम के कार्यों का उपयोग करने का सिर्फ एक फैंसी तरीका हैं:

def attrs(**kwds):
    def decorate(f):
        for k in kwds:
            setattr(f, k, kwds[k])
        return f
    return decorate

@attrs(versionadded="2.2",
       author="Guido van Rossum")
def mymethod(f):
    ...

मैंने किसी भी उदाहरण में किसी भी कोड को रूपांतरित नहीं देखा है, जैसे कि क्लोजर मैक्रो के एनाटॉमी में वर्णित है । इसके अलावा, पायथन के लापता समलैंगिकता कोड परिवर्तन को असंभव बना सकता है

तो, इन दोनों की तुलना कैसे की जाती है और क्या आप कह सकते हैं कि आप जो कर सकते हैं, उसमें वे बराबर हैं? साक्ष्य इसके खिलाफ इशारा करते हैं।

संपादित करें: एक टिप्पणी के आधार पर, मैं दो चीजों की तलाश कर रहा हूं: "के रूप में शक्तिशाली" और "के साथ भयानक चीजें करने में आसान" पर तुलना करें।


12
बेशक सज्जाकार असली मैक्रोज़ नहीं हैं। वे एक अनियंत्रित भाषा का अनुवाद नहीं कर सकते (पूरी तरह से अलग वाक्यविन्यास के साथ) अजगर में। जो लोग इसके विपरीत दावा करते हैं, वे मैक्रों को नहीं समझते हैं।
SK-तर्क

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

हो सकता है कि मैं इस सवाल को बदल दूं कि "जबर्दस्त चीजें करना आसान है"। ;)
प्रपत्च

शायद कोई पायथन उदाहरण के लिए कुछ तुलनीय क्लोजर उच्च-क्रम फ़ंक्शन को हैक कर सकता है। मैंने कोशिश की, लेकिन इस प्रक्रिया में मेरे दिमाग को तोड़ दिया। चूंकि पायथन उदाहरण ऑब्जेक्ट विशेषताओं का उपयोग करता है इसलिए इसे थोड़ा अलग होना चाहिए।
प्रोफैट्सच

@ घोषी को रन-टाइम पर संकलित एएसटी के रूप में जाना जाता है: स्व-संशोधित कोड
कज़

जवाबों:


16

एक डेकोरेटर मूल रूप से केवल एक फ़ंक्शन है

आम लिस्प में उदाहरण:

(defun attributes (keywords function)
  (loop for (key value) in keywords
        do (setf (get function key) value))
  function)

फ़ंक्शन के ऊपर एक प्रतीक है (जो द्वारा लौटा दिया जाएगा DEFUN ) और हमने विशेषताओं को प्रतीक की संपत्ति सूची में डाल दिया ।

अब हम इसे एक फंक्शन परिभाषा के आसपास लिख सकते हैं:

(attributes
  '((version-added "2.2")
    (author "Rainer Joswig"))

  (defun foo (a b)
    (+ a b))

)  

यदि हम पाइथन में एक फैंसी सिंटैक्स जोड़ना चाहते हैं, तो हम एक पाठक मैक्रो लिखते हैं । एक पाठक मैक्रो हमें एस-एक्सप्रेशन सिंटैक्स के स्तर पर प्रोग्राम करने की अनुमति देता है:

(set-macro-character
 #\@
 (lambda (stream char)
   (let ((decorator (read stream))
         (arg       (read stream))
         (form      (read stream)))
     `(,decorator ,arg ,form))))

हम फिर लिख सकते हैं:

@attributes'((version-added "2.2")
             (author "Rainer Joswig"))
(defun foo (a b)
  (+ a b))

लिस्प पाठक ऊपर पढ़ता है:

(ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
                    (AUTHOR "Rainer Joswig")))
            (DEFUN FOO (A B) (+ A B)))

अब हमारे पास कॉमन लिस्प में डेकोरेटर्स का एक रूप है ।

मैक्रोज़ और रीडर मैक्रोज़ का मेल।

वास्तव में मैं मैक्रो का उपयोग करके वास्तविक कोड में उपरोक्त अनुवाद करूँगा, न कि किसी फ़ंक्शन का।

(defmacro defdecorator (decorator arg form)
  `(progn
     ,form
     (,decorator ,arg ',(second form))))

(set-macro-character
 #\@
 (lambda (stream char)
   (declare (ignore char))
   (let* ((decorator (read stream))
          (arg       (read stream))
          (form      (read stream)))
     `(defdecorator ,decorator ,arg ,form))))

उपयोग एक ही पाठक मैक्रो के साथ ऊपर है। लाभ यह है कि लिस्प संकलक अभी भी इसे तथाकथित शीर्ष-स्तरीय रूप में देखता है - * फ़ाइल संकलक विशेष रूप से शीर्ष-स्तरीय रूपों का इलाज करता है, उदाहरण के लिए यह संकलन-समय के वातावरण में उनके बारे में जानकारी जोड़ता है । ऊपर के उदाहरण में हम देख सकते हैं कि मैक्रो स्रोत कोड में दिखता है और नाम को निकालता है।

लिस्प पाठक उपरोक्त उदाहरण में पढ़ता है:

(DEFDECORATOR ATTRIBUTES
  (QUOTE ((VERSION-ADDED "2.2")
           (AUTHOR "Rainer Joswig")))
  (DEFUN FOO (A B) (+ A B)))

जो तब मैक्रो में विस्तारित हो जाता है:

(PROGN (DEFUN FOO (A B) (+ A B))
       (ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
                           (AUTHOR "Rainer Joswig")))
                   (QUOTE FOO)))

मैक्रोज़ रीडर मैक्रोज़ से बहुत अलग हैं

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

(math y = 3 x ^ 2 - 4 x + 3)

अभिव्यक्ति y = 3 x ^ 2 - 4 x + 3वैध लिस्प कोड नहीं है, लेकिन मैक्रो उदाहरण के लिए इसे पार्स कर सकता है और इस तरह वैध लिस्प कोड लौटा सकता है:

(setq y (+ (* 3 (expt x 2))
           (- (* 4 x))
           3))

लिस्प में मैक्रोज़ के कई अन्य उपयोग के मामले हैं।


8

पायथन (भाषा) में डेकोरेटर फ़ंक्शन को संशोधित नहीं कर सकते हैं, केवल इसे लपेट सकते हैं, इसलिए वे निश्चित रूप से लिस्प मैक्रोज़ की तुलना में बहुत कम शक्तिशाली हैं।

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

ध्यान दें, कि आधुनिक लिस्प्स एस-एक्सप्रेशन को बाइटकोड के रूप में उपयोग नहीं करते हैं, इसलिए एस-एक्सप्रेशन सूचियों पर काम करने वाले मैक्रोज़ निश्चित रूप से बाइटकोड संकलन से पहले काम करते हैं जैसा कि ऊपर उल्लेख किया गया है, अजगर में डेकोरेटर इसके बाद चलता है।


1
आपको फ़ंक्शन को संशोधित करने की आवश्यकता नहीं है। आपको केवल किसी न किसी रूप में फ़ंक्शन के कोड को पढ़ने की आवश्यकता है (व्यवहार में, इसका मतलब बायटेकोड है)। ऐसा नहीं है कि यह इसे और अधिक व्यावहारिक बनाता है।

2
@ डायलेन: तकनीकी रूप से, लिस्प इसे संशोधित नहीं कर रहा है; यह इसे स्रोत के रूप में उपयोग कर रहा है ताकि एक नया उत्पन्न किया जा सके और इसलिए अजगर, हाँ। समस्या टोकन सूची या एएसटी के अभाव में है और तथ्य यह है कि संकलक ने पहले से ही कुछ चीजों के बारे में शिकायत की थी जो आप अन्यथा मैक्रो में अनुमति दे सकते हैं।
Jan Hudec

4

नए नियंत्रण प्रवाह तंत्रों को पेश करने के लिए पायथन डेकोरेटर्स का उपयोग करना काफी कठिन है।

यह नए नियंत्रण प्रवाह तंत्रों को पेश करने के लिए कॉमन लिस्प मैक्रो का उपयोग करने के लिए सीमा-पर-तुच्छ है।

इस से, यह संभवतः इस प्रकार है कि वे समान रूप से अभिव्यंजक नहीं हैं (मैं "शक्तिशाली" की व्याख्या "अभिव्यंजक" के रूप में करता हूं, क्योंकि मुझे लगता है कि उनका वास्तव में क्या मतलब है)।


मैं कहता हूँs/quite hard/impossible/

@delnan ठीक है, मैं जाना नहीं होगा काफी अब तक के रूप में कहने के लिए "असंभव" है, लेकिन आप निश्चित रूप से इस पर काम करना होगा।
वेटाइन

0

यह निश्चित रूप से संबंधित कार्यशीलता है, लेकिन पायथन डेकोरेटर से यह कहा जा रहा है कि विधि को संशोधित करने के लिए तुच्छ नहीं है (जो fआपके उदाहरण में पैरामीटर होगा )। इसे संशोधित करने के लिए आप एस्ट्रो मॉड्यूल के साथ पागल हो सकते हैं ), लेकिन आप कुछ बहुत जटिल प्रोग्रामिंग के लिए होंगे।

इस लाइन के साथ चीजें हालांकि की गई हैं: कुछ सचमुच दिमाग झुकने वाले उदाहरणों के लिए मैक्रोपी पैकेज देखें।


3
यहां तक ​​कि astअजगर में -transforming सामान लिस्प मैक्रोज़ के बराबर नहीं है। पायथन के साथ, स्रोत भाषा पाइथन होनी चाहिए, लिस्प मैक्रोज़ के साथ एक मैक्रो द्वारा परिवर्तित स्रोत भाषा, शाब्दिक, कुछ भी हो सकती है। इसलिए, पायथन मेटाप्रोग्रामिंग केवल साधारण चीजों (जैसे एओपी) के लिए उपयुक्त है, जबकि लिस्प मेटाप्रोग्रामिंग शक्तिशाली ईडीएसएल संकलक को लागू करने के लिए उपयोगी है।
एसके-लॉजिक

1
बात यह है कि सज्जाकारों का उपयोग करके मैक्रोपी को लागू नहीं किया गया है। यह डेकोरेटर सिंटैक्स का उपयोग करता है (क्योंकि यह एक मान्य पायथन सिंटैक्स का उपयोग करना चाहिए), लेकिन यह आयात हुक से बाइट संकलन प्रक्रिया को अपहरण करके कार्यान्वित किया जाता है।
जन हुदेक

@ एसके-तर्क: लिस्प में स्रोत भाषा को भी लिस्प होना चाहिए। बस लिस्प सिंटैक्स बहुत सरल लेकिन लचीला है, जबकि अजगर सिंटैक्स बहुत अधिक जटिल है और इतना लचीला नहीं है।
Jan Hudec

1
@ जानहुडक, लिस्प स्रोत भाषा में कोई भी हो सकता है (मेरा वास्तव में मतलब है, कोई भी ) वाक्यविन्यास - पाठक मैक्रोज़ देखें।
एसके-लॉजिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.