क्या कोई डिज़ाइन पैटर्न हैं जो केवल पायथन जैसी गतिशील रूप से टाइप की जाने वाली भाषाओं में संभव हैं?


30

मैंने एक संबंधित प्रश्न पढ़ा है कि क्या पायथन जैसी गतिशील भाषाओं में कोई डिज़ाइन पैटर्न अनावश्यक हैं? और इस उद्धरण को Wikiquote.org पर याद किया

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

--- सॉफ्टवेयर इंजीनियरिंग रेडियो एपिसोड 140: गिलक ब्राच के साथ समाचार पत्र और प्लग करने योग्य प्रकार

मुझे आश्चर्य है, क्या उपयोगी डिज़ाइन पैटर्न या रणनीतियाँ हैं, जो बोली के निर्माण का उपयोग करते हुए, "प्रकार के रूप में काम नहीं करती हैं"?


3
मैंने दोहरे प्रेषण और विज़िटर पैटर्न को सांख्यिकीय रूप से टाइप की गई भाषाओं में पूरा करने के लिए बहुत मुश्किल पाया है, लेकिन गतिशील भाषाओं में आसानी से उपलब्ध है। उदाहरण के लिए यह उत्तर (और प्रश्न) देखें: programmers.stackexchange.com/a/288153/122079
user3002473

7
बेशक। कोई भी पैटर्न जिसमें रनटाइम पर नई कक्षाएं बनाना शामिल है, उदाहरण के लिए। (यह जावा में भी संभव है, लेकिन C ++ में नहीं; इसमें डायनामिज्म का स्लाइडिंग स्केल है)।
user253751

1
यह बहुत कुछ इस बात पर निर्भर करेगा कि आपका सिस्टम कितना परिष्कृत है :-) कार्यात्मक भाषाएं आमतौर पर इस पर काफी अच्छा करती हैं।
बरगी

1
हर कोई Haskell या OCaml के बजाय Java और C # जैसे टाइप सिस्टम पर बात कर रहा है। एक शक्तिशाली प्रकार की प्रणाली वाली भाषा एक गतिशील भाषा के रूप में संक्षिप्त हो सकती है, लेकिन प्रकार की सुरक्षा रख सकती है।
एंड्रयू कहते हैं मोनिका

@ नौबत यह गलत है। स्टेटिक टाइप सिस्टम रन-टाइम पर बिल्कुल नई, "गतिशील" कक्षाएं बना सकते हैं। प्रोग्रामिंग भाषाओं के लिए व्यावहारिक नींव के अध्याय 33 को देखें।
बाग़

जवाबों:


4

प्रथम श्रेणी के प्रकार

डायनेमिक टाइपिंग का मतलब है कि आपके पास प्रथम श्रेणी के प्रकार हैं: आप रनटाइम के प्रकारों का निरीक्षण, निर्माण और भंडारण कर सकते हैं, जिसमें भाषा के अपने प्रकार भी शामिल हैं। इसका अर्थ यह भी है कि मान टाइप किए जाते हैं, चर नहीं ।

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

हालांकि, गतिशील प्रकार सिस्टम शायद ही कभी हो ही प्रथम श्रेणी के प्रकार के। आपके पास प्रथम श्रेणी के प्रतीक, प्रथम श्रेणी के पैकेज, प्रथम श्रेणी .... सब कुछ हो सकते हैं। यह संकलक की भाषा और स्टेटिक भाषा में रनटाइम भाषा के बीच सख्त अलगाव के विपरीत है। संकलक या दुभाषिया रनटाइम क्या कर सकता है, भी कर सकता है।

अब, मान लेते हैं कि टाइप इंफ़ेक्शन एक अच्छी बात है और इसे चलाने से पहले मुझे अपना कोड चेक करना पसंद है। हालाँकि, मैं रनटाइम पर कोड का उत्पादन और संकलन करना भी पसंद करता हूं। और मुझे संकलन-समय पर भी चीजों को पसंद करना पसंद है। गतिशील रूप से टाइप की गई भाषा में, यह उसी भाषा के साथ किया जाता है। OCaml में, आपके पास मॉड्यूल / फ़ंक्टर प्रकार प्रणाली है, जो मुख्य प्रकार की प्रणाली से अलग है, जो प्रीप्रोसेसर भाषा से अलग है। C ++ में, आपके पास टेम्पलेट भाषा है, जिसका मुख्य भाषा से कोई लेना-देना नहीं है, जो आम तौर पर निष्पादन के दौरान प्रकारों से अनभिज्ञ होती है। और यह ठीक है उन भाषाओं में है, क्योंकि वे अधिक प्रदान नहीं करना चाहते हैं।

अंततः, यह वास्तव में नहीं बदलता है कि आप किस प्रकार का सॉफ़्टवेयर विकसित कर सकते हैं, लेकिन अभिव्यक्तता कैसे बदलती है आप उन्हें विकसित करते हैं और यह कठिन है या नहीं।

पैटर्न्स

डायनामिक प्रकारों पर भरोसा करने वाले पैटर्न वे पैटर्न होते हैं जिनमें डायनामिक वातावरण शामिल होते हैं: ओपन क्लास, डिस्पैचिंग, इन-मेमोरी डेटाबेस ऑफ़ ऑब्जेक्ट्स, सीरियलाइज़ेशन, आदि जेनेरिक कंटेनर्स जैसी सिंपल चीज़ें काम करती हैं क्योंकि एक वेक्टर रनटाइम को ऑब्जेक्ट्स के प्रकार के बारे में नहीं भूलता है। (पैरामीट्रिक प्रकार की कोई आवश्यकता नहीं)।

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

;;
;; Fetching systems, installing them, etc. 
;; ASDF and QL provide provide resp. a Make-like facility 
;; and system management inside the runtime: those are
;; not distinct programs.
;; Reflexivity allows to develop dedicated tools: for example,
;; being able to find the transitive reduction of dependencies
;; to parallelize builds. 
;; https://gitlab.common-lisp.net/xcvb/asdf-dependency-grovel
;;
(ql:quickload 'trivial-timeout)

;;
;; Readtables are part of the runtime.
;; See also NAMED-READTABLES.
;;
(defparameter *safe-readtable* (copy-readtable *readtable*))
(set-macro-character #\# nil t *safe-readtable*)
(set-macro-character #\: (lambda (&rest args)
                           (declare (ignore args))
                           (error "Colon character disabled."))
                     nil
                     *safe-readtable*)

;; eval-when is necessary when compiling the whole file.
;; This makes the result of the form available in the compile-time
;; environment. 
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defvar +WHITELISTED-LISP-SYMBOLS+ 
    '(+ - * / lambda labels mod rem expt round 
      truncate floor ceiling values multiple-value-bind)))

;;
;; Read-time evaluation #.+WHITELISTED-LISP-SYMBOLS+
;; The same language is used to control the reader.
;;
(defpackage :sandbox
  (:import-from
   :common-lisp . #.+WHITELISTED-LISP-SYMBOLS+)
  (:export . #.+WHITELISTED-LISP-SYMBOLS+))

(declaim (inline read-sandbox))

(defun read-sandbox (stream &key (timeout 3))
  (declare (type (integer 0 10) timeout))
  (trivial-timeout:with-timeout (timeout)
    (let ((*read-eval* nil)
          (*readtable* *safe-readtable*)
          ;;
          ;; Packages are first-class: no possible name collision.
          ;;
          (package (make-package (gensym "SANDBOX") :use '(:sandbox))))
      (unwind-protect
           (let ((*package* package))
             (loop
                with stop = (gensym)
                for read = (read stream nil stop)
                until (eq read stop)
                ;;
                ;; Eval at runtime
                ;;
                for value = (eval read)
                ;;
                ;; Type checking
                ;;
                unless (functionp value)
                do (error "Not a function")
                ;; 
                ;; Compile at run-time
                ;;
                collect (compile nil value)))
        (delete-package package)))))

;;
;; Static type checking.
;; warning: Constant 50 conflicts with its asserted type (MOD 11)
;;
(defun read-sandbox-file (file)
  (with-open-file (in file)
    (read-sandbox in :timeout 50)))

;; get it right, this time
(defun read-sandbox-file (file)
  (with-open-file (in file)
    (read-sandbox in)))

#| /tmp/plugin.lisp
(lambda (x) (+ (* 3 x) 100))
(lambda (a b c) (* a b))
|#

(read-sandbox-file #P"/tmp/plugin.lisp")

;; 
;; caught COMMON-LISP:STYLE-WARNING:
;;   The variable C is defined but never used.
;;

(#<FUNCTION (LAMBDA (#:X)) {10068B008B}>
 #<FUNCTION (LAMBDA (#:A #:B #:C)) {10068D484B}>)

अन्य भाषाओं के साथ करने के लिए ऊपर कुछ भी "असंभव" नहीं है। ब्लेंडर में प्लग-इन का दृष्टिकोण, संगीत सॉफ्टवेयर में या सांख्यिकीय रूप से संकलित भाषाओं के लिए IDEs, जो ऑन-द-फ्लाई recompilation करते हैं, आदि बाहरी उपकरणों के बजाय, गतिशील भाषाएं उन उपकरणों का पक्ष लेती हैं जो पहले से मौजूद जानकारी का उपयोग करते हैं। FOO के सभी ज्ञात कॉलर? बार के सभी उपवर्ग? सभी विधि जो वर्ग ZOT द्वारा विशेष हैं? यह आंतरिक डेटा है। प्रकार इस का सिर्फ एक पहलू है।


(यह भी देखें: CFFI )


39

संक्षिप्त उत्तर: नहीं, क्योंकि ट्यूरिंग तुल्यता।

लंबे उत्तर: यह आदमी एक ट्रोल है। हालांकि यह सही है कि टाइप सिस्टम "आपको एक सबसेट तक सीमित करता है," उस सब्मिट के बाहर का सामान, परिभाषा के अनुसार, वह सामान जो काम नहीं करता है।

कुछ भी आप किसी भी ट्यूरिंग-पूर्ण प्रोग्रामिंग भाषा में करने में सक्षम हैं (जो कि सामान्य-प्रयोजन प्रोग्रामिंग के लिए डिज़ाइन की गई भाषा है, साथ ही बहुत सारे हैं; यह स्पष्ट करने के लिए बहुत कम बार है और सिस्टम के कई उदाहरण हैं- ट्यूरिंग- अनायास ही) आप किसी भी अन्य ट्यूरिंग-पूर्ण प्रोग्रामिंग भाषा में करने में सक्षम हैं। इसे "ट्यूरिंग तुल्यता" कहा जाता है, और इसका केवल वही अर्थ है जो यह कहता है। महत्वपूर्ण रूप से, इसका मतलब यह नहीं है कि आप दूसरी चीज़ को दूसरी भाषा में आसानी से कर सकते हैं - कुछ यह तर्क देंगे कि पहली जगह में एक नई प्रोग्रामिंग भाषा बनाने का पूरा बिंदु है: आपको कुछ करने का एक बेहतर तरीका ऐसी चीजें जो मौजूदा भाषाएं चूसती हैं।

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

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

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

पहला, क्योंकि बिना किसी प्रकार के एनोटेशन वाले कोड को पढ़ना मुश्किल है। निम्नलिखित पायथन पर विचार करें:

def sendData(self, value):
   self.connection.send(serialize(value.someProperty))

आप क्या अपेक्षा करते हैं कि डेटा ऐसा दिखे कि कनेक्शन के दूसरे छोर पर सिस्टम प्राप्त हो? और अगर यह कुछ ऐसा प्राप्त कर रहा है जो पूरी तरह से गलत लगता है, तो आप कैसे पता लगा सकते हैं कि क्या चल रहा है?

यह सब की संरचना पर निर्भर करता है value.someProperty। लेकिन यह कैसा दिखता है? अच्छा प्रश्न! क्या बुला रहा है sendData()? क्या गुजर रहा है? वह चर कैसा दिखता है? यह कहां से आया? यदि यह स्थानीय नहीं है, तो आपको यह पता लगाने के valueलिए कि क्या चल रहा है , पूरे इतिहास को देखना होगा। हो सकता है कि आप कुछ और पास कर रहे हों someProperty, जिसमें एक संपत्ति भी हो , लेकिन यह वह नहीं करता जो आपको लगता है कि यह करता है?

अब इसे टाइप एनोटेशन के साथ देखते हैं, जैसा कि आप बू भाषा में देख सकते हैं, जो बहुत ही समान वाक्यविन्यास का उपयोग करता है लेकिन स्टेटिक टाइप है:

def SendData(value as MyDataType):
   self.Connection.Send(Serialize(value.SomeProperty))

अगर कुछ गलत हो रहा है, तो अचानक डिबगिंग का आपका काम सिर्फ परिमाण का एक आदेश आसान हो गया: ऊपर की परिभाषा देखें MyDataType! साथ ही, बुरा व्यवहार करने का मौका क्योंकि आप कुछ असंगत प्रकार से गुजरते हैं, जिसमें एक ही नाम वाली संपत्ति भी अचानक शून्य हो जाती है, क्योंकि टाइप सिस्टम आपको वह गलती नहीं करने देगा।

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

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


24
"इस आदमी का ट्रोल होना।" - मुझे यकीन नहीं है कि एक विज्ञापन होमिनम हमला आपके अन्यथा अच्छी तरह से प्रस्तुत मामले में मदद करने वाला है। और जब मैं अच्छी तरह से जानता हूं कि अधिकार से तर्क विज्ञापन गृहिणी के रूप में समान रूप से खराब है, तो मैं अभी भी यह बताना चाहूंगा कि गिल्ड ब्राचा ने शायद अधिक भाषाओं को डिजाइन किया है और (इस चर्चा के लिए सबसे अधिक) सबसे अधिक स्थिर प्रकार की प्रणालियां हैं। बस एक छोटा सा अंश: वे न्यूजपेपर के एकमात्र डिजाइनर, डार्ट के सह-डिजाइनर, जावा भाषा विनिर्देश और जावा वर्चुअल मशीन स्पेसिफिकेशन के सह-लेखक, जावा और जेवीएम के डिजाइन पर काम करते हैं, जिसे डिज़ाइन किया गया ...
जोर्ज डब्ल्यू मित्तग

10
स्ट्रोंगटॉक (स्मालटाकल के लिए एक स्थिर प्रकार की प्रणाली), डार्ट प्रकार प्रणाली, समाचार पत्र प्रकार प्रणाली, प्रतिरूपता पर उनकी पीएचडी थीसिस हर आधुनिक मॉड्यूल प्रणाली के लिए बहुत अधिक आधार है (जैसे जावा 9, ईसीएमएस्क्रिप्ट 2015, स्काला, डार्ट, समाचार पत्र, Ioke , सिपाही), मिक्सिंस पर उनके पेपर (एस) ने हमारे बारे में सोचने के तरीके में क्रांति ला दी। अब, यह करता है नहीं मतलब है कि वह सही है, लेकिन मैं करना डिज़ाइन किया गया हो रही है जो एक से अधिक स्थिर प्रकार प्रणाली उसे थोड़ा अधिक बनाता है एक "ट्रोल" की तुलना में लगता है।
जोर्ग डब्ल्यू मित्तग

17
"जबकि यह सच है कि टाइप सिस्टम" आपको एक सबसेट तक सीमित करता है, "उस सब्मिट के बाहर का सामान, परिभाषा के अनुसार, सामान काम नहीं करता है।" - ये गलत है। हम हॉल्टिंग प्रॉब्लम, चावल के प्रमेय, और अन्य अयोग्यता और असंख्यता के असंख्य परिणामों से जानते हैं कि एक स्थिर टाइप चेकर सभी प्रोग्रामों के लिए यह तय नहीं कर सकता है कि वे टाइप-सेफ हैं या टाइप-असुरक्षित। यह उन कार्यक्रमों (जिनमें से कुछ प्रकार-असुरक्षित हैं) को स्वीकार नहीं कर सकते हैं, इसलिए एकमात्र अस्वीकार विकल्प उन्हें अस्वीकार करना है (हालांकि, उनमें से कुछ टाइप-सुरक्षित हैं)। वैकल्पिक रूप से, भाषा को…
Jörg W Mittag

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

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

27

मैं 'पैटर्न' भाग को साइड-स्टेप करने जा रहा हूं क्योंकि मुझे लगता है कि यह इस बात की परिभाषा में है कि क्या पैटर्न है या नहीं है और मैंने उस बहस में लंबे समय तक रुचि खो दी है। मैं क्या कहूंगा कि कुछ चीजें हैं जो आप कुछ भाषाओं में कर सकते हैं जो आप दूसरों में नहीं कर सकते हैं। मुझे स्पष्ट होने दें, मैं यह नहीं कह रहा हूं कि ऐसी समस्याएं हैं जिन्हें आप एक भाषा में हल कर सकते हैं जिसे आप दूसरे में हल नहीं कर सकते। मेसन पहले ही ट्यूरिंग पूर्णता को इंगित कर चुके हैं।

उदाहरण के लिए, मैंने अजगर में एक वर्ग लिखा है जो XML DOM तत्व को लपेटता है और इसे प्रथम श्रेणी की वस्तु बनाता है। अर्थात्, आप कोड लिख सकते हैं:

doc.header.status.text()

और आपके पास पार्स की गई XML ऑब्जेक्ट से उस पथ की सामग्री है। साफ सुथरा, IMO। और अगर कोई सिर नोड नहीं है, तो यह सिर्फ एक डमी ऑब्जेक्ट देता है जिसमें डमी ऑब्जेक्ट (नीचे सभी तरह से कछुए होते हैं।) जावा, कहने का कोई वास्तविक तरीका नहीं है। आपको समय से पहले एक वर्ग संकलित करना होगा जो कि XML की संरचना के कुछ ज्ञान पर आधारित है। यह कहते हुए कि क्या यह एक अच्छा विचार है, इस तरह की बात वास्तव में एक गतिशील भाषा में समस्याओं को हल करने के तरीके को बदल देती है। मैं यह नहीं कह रहा हूं कि यह एक तरह से बदलता है जो जरूरी हमेशा बेहतर होता है। गतिशील दृष्टिकोण के लिए कुछ निश्चित लागतें हैं और मेसन का जवाब एक सभ्य अवलोकन देता है। चाहे वे एक अच्छे विकल्प हों, कई कारकों पर निर्भर करता है।

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


4
आप जावा में ऐसा नहीं कर सकते क्योंकि जावा का डिज़ाइन खराब है। यह C # प्रयोग में उतना कठिन नहीं होगा IDynamicMetaObjectProvider, और बू में यह सरल है। ( यहां 100 से भी कम लाइनों में कार्यान्वयन है, इसे गीथहब पर मानक स्रोत पेड़ के हिस्से के रूप में शामिल किया गया है, क्योंकि यह इतना आसान है!)
मेसन व्हीलर

6
@MasonWheeler "IDynamicMetaObjectProvider"? क्या यह C # dynamicकीवर्ड से संबंधित है ? ... जो प्रभावी रूप से सिर्फ C # को डायनेमिक टाइपिंग पर टॉक्स करता है? यकीन नहीं है कि अगर मैं सही हूं तो आपका तर्क मान्य है।
jpmc26

9
@MasonWheeler आप शब्दार्थ में हो रहे हैं। Minutiae के बारे में बहस किए बिना (हम यहाँ SE पर गणितीय औपचारिकता विकसित नहीं कर रहे हैं।), डायनेमिक टाइपिंग प्रकारों के चारों ओर संकलित समय निर्णयों का अभ्यास है, विशेष रूप से सत्यापन कि प्रत्येक प्रकार के विशेष सदस्यों को प्रोग्राम एक्सेस करता है। वह लक्ष्य है जो dynamicC # में पूरा होता है। "प्रतिबिंब और शब्दकोश देखने" रनटाइम पर होते हैं, संकलन समय नहीं। मुझे वास्तव में यकीन नहीं है कि आप एक ऐसा मामला कैसे बना सकते हैं कि यह भाषा में गतिशील टाइपिंग जोड़े। मेरा कहना है कि जिमी के अंतिम पैराग्राफ में यह शामिल है।
jpmc26

44
जावा का बहुत बड़ा प्रशंसक नहीं होने के बावजूद, मैं यह भी कहने की हिम्मत करता हूं कि जावा को "खराब रूप से डिजाइन" विशेष रूप से कॉल करना क्योंकि इसमें डायनामिक टाइपिंग नहीं जोड़ा गया है ... अति उत्साही।
jpmc26

5
थोड़ा और अधिक सुविधाजनक वाक्यविन्यास के अलावा, यह एक शब्दकोश से कैसे अलग है?
थियोडोरोस चट्जीगानियाकिस

10

उद्धरण सही है, लेकिन वास्तव में विवादास्पद भी है। आइए इसे तोड़ने के लिए देखें कि क्यों:

डायनामिक टाइपिंग के बारे में आश्चर्यजनक बात यह है कि यह आपको कुछ भी व्यक्त करने देता है जो कि कम्प्यूटेबल है।

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

और सिस्टम टाइप नहीं करते - टाइप सिस्टम आमतौर पर निर्णायक होते हैं, और वे आपको एक सबसेट तक सीमित रखते हैं।

यह सच है, लेकिन ध्यान दें कि अब हम दृढ़ता से बात कर रहे हैं कि किस प्रकार की प्रणाली की अनुमति है, न कि भाषा की जो टाइप सिस्टम का उपयोग करती है। हालांकि, संकलन समय पर सामान की गणना करने के लिए एक प्रकार की प्रणाली का उपयोग करना संभव है, यह आम तौर पर ट्यूरिंग पूरा नहीं होता है (जैसा कि टाइप सिस्टम आमतौर पर निर्णायक होता है), लेकिन लगभग कोई भी स्टेटिक टाइप की गई भाषा भी अपने रनटाइम में पूरी तरह से ट्यूरिंग होती है (निर्भर टाइप की हुई भाषाएं) नहीं, लेकिन मुझे विश्वास नहीं है कि हम यहां उनके बारे में बात कर रहे हैं)।

स्टैटिक टाइप सिस्टम का पक्ष लेने वाले लोग कहते हैं, "यह ठीक है, यह काफी अच्छा है; जितने भी दिलचस्प कार्यक्रम आप लिखना चाहते हैं वे सभी प्रकार के काम करेंगे ”। लेकिन यह हास्यास्पद है - एक बार जब आपके पास एक प्रकार की प्रणाली होती है, तो आप यह भी नहीं जानते हैं कि क्या दिलचस्प कार्यक्रम हैं।

मुसीबत यह है कि गतिशील प्रकार की भाषाओं में एक स्थिर प्रकार होता है। कभी-कभी सब कुछ एक स्ट्रिंग है, और आमतौर पर कुछ टैग किए गए संघ होते हैं जहां हर चीज या तो गुणों का एक बैग होती है या एक इंट या डबल जैसा मूल्य होता है। परेशानी यह है कि स्थिर भाषाएं ऐसा कर सकती हैं, ऐतिहासिक रूप से ऐसा करने के लिए यह थोड़ा क्लंकियर था, लेकिन आधुनिक रूप से टाइप की गई भाषाएं गतिशील रूप से टाइप की गई भाषा का उपयोग करने के लिए इसे बहुत आसान बनाती हैं, इसलिए इसमें अंतर कैसे हो सकता है प्रोग्रामर एक दिलचस्प कार्यक्रम के रूप में क्या देख सकता है? स्टेटिक भाषाओं में ठीक उसी तरह के टैग किए गए यूनियनों के साथ-साथ अन्य प्रकार हैं।

शीर्षक में प्रश्न का उत्तर देने के लिए: नहीं, कोई डिज़ाइन पैटर्न नहीं है जो कि एक सांख्यिकीय रूप से टाइप की गई भाषा में लागू नहीं किया जा सकता है, क्योंकि आप उन्हें प्राप्त करने के लिए हमेशा पर्याप्त गतिशील प्रणाली को लागू कर सकते हैं। ऐसे पैटर्न हो सकते हैं जो आपको गतिशील भाषा में 'मुक्त' के लिए मिलते हैं; यह YMMV के लिए उन भाषाओं के डाउनसाइड के साथ डालने या नहीं हो सकता है ।


2
मुझे पूरा यकीन नहीं है कि आपने सिर्फ हां या ना में जवाब दिया है। मेरे लिए एक नहीं की तरह अधिक लगता है।
user7610

1
@TheodorosChatzigiannakis हां, गतिशील भाषाओं को और कैसे लागू किया जाएगा? सबसे पहले, आप एक अंतरिक्ष यात्री वास्तुकार के लिए पास होंगे यदि आप कभी भी एक डायनामिक क्लास सिस्टम या कुछ और शामिल करना चाहते हैं। दूसरा, आपके पास संभवतः इसे डीबग करने योग्य, पूरी तरह से आत्मनिरीक्षण करने वाला, परफ़ॉर्मेंट ("बस एक शब्दकोश का उपयोग करें" यह है कि कैसे धीमी गति से भाषाओं को लागू किया जाता है) बनाने के लिए संसाधन नहीं है। तीसरा, कुछ गतिशील सुविधाओं को पूरी भाषा में एकीकृत करते समय सबसे अच्छा उपयोग किया जाता है, न कि केवल एक पुस्तकालय के रूप में: उदाहरण के लिए कचरा संग्रह सोचो ( पुस्तकालयों के रूप में जीसी हैं, लेकिन वे आमतौर पर उपयोग नहीं किए जाते हैं)।
coredump

1
@ थियोडोरस के अनुसार मैं पहले से ही एक बार यहां से जुड़ा हुआ हूं, लेकिन संरचनाओं के 2.5% (पायथन मॉड्यूल जिन शोधों को देखा गया था) उन्हें आसानी से टाइप की गई भाषा में व्यक्त किया जा सकता है। हो सकता है कि 2.5% गतिशील टाइपिंग की लागत का भुगतान करता है। यह अनिवार्य रूप से मेरा सवाल था। neverworkintheory.org/2016/06/13/polymorphism-in-python.html
user7610

3
@JiriDanek जहां तक ​​मैं बता सकता हूं, ऐसा कुछ भी नहीं है जो एक सांख्यिकीय रूप से टाइप की गई भाषा को पॉलीमॉर्फिक कॉल स्पॉट होने से रोकता है और प्रक्रिया में स्थिर टाइपिंग बनाए रखता है। मल्टी-विधियों की स्टेटिक प्रकार की जाँच देखें । शायद मैं आपके लिंक को गलत समझ रहा हूं।
थियोडोरोस चट्जीगानियाकिस

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

4

निश्चित रूप से ऐसी चीजें हैं जो आप केवल गतिशील रूप से टाइप की गई भाषाओं में कर सकते हैं। लेकिन वे जरूरी अच्छा डिजाइन नहीं होगा ।

आप पहले एक पूर्णांक 5 को फिर एक स्ट्रिंग 'five', या एक Catऑब्जेक्ट को एक ही चर में असाइन कर सकते हैं । लेकिन आप अपने कोड के एक पाठक के लिए केवल यह जानना कठिन बना रहे हैं कि हर चर का उद्देश्य क्या है।

आप लाइब्रेरी रूबी वर्ग में एक नई विधि जोड़ सकते हैं और इसके निजी क्षेत्रों तक पहुँच प्राप्त कर सकते हैं। ऐसे मामले हो सकते हैं जहां इस तरह की हैक उपयोगी हो सकती है लेकिन यह इनकैप्सुलेशन का उल्लंघन होगा। (मुझे सार्वजनिक इंटरफ़ेस पर भरोसा करने के तरीकों को जोड़ने में कोई आपत्ति नहीं है, लेकिन ऐसा कुछ भी नहीं है जो सांख्यिकीय रूप से टाइप किया गया C # एक्सटेंशन विधियां नहीं कर सकता है।)

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

आमतौर पर, आप जितना अधिक संगठित रहना चाहते हैं आपका कोड उतना ही कम लाभ उठाएगा, जो आपको गतिशील रूप से टाइप परिभाषाओं को बदलने में सक्षम होना चाहिए या विभिन्न प्रकारों के मूल्यों को एक ही चर में असाइन करना चाहिए। लेकिन तब आपका कोड उस तरह से अलग नहीं होता है, जिसे आप वैधानिक रूप से टाइप की गई भाषा में हासिल कर सकते हैं।

डायनेमिक चीनी कितनी अच्छी हैं उदाहरण के लिए, एक deserialized JSON ऑब्जेक्ट को पढ़ते समय आप किसी नेस्टेड मान का उल्लेख कर सकते हैं obj.data.article[0].content- जैसा कि कहना है obj.getJSONObject("data").getJSONArray("article").getJSONObject(0).getString("content")

रूबी डेवलपर्स विशेष रूप से जादू के बारे में लंबाई पर बात कर सकता है जिसे लागू करके प्राप्त किया जा सकता है method_missing, जो एक ऐसी विधि है जो आपको अघोषित तरीकों से प्रयास किए गए कॉल को संभालने की अनुमति देती है। उदाहरण के लिए, ActiveRecord ORM इसका उपयोग करता है ताकि आप User.find_by_email('joe@example.com')कभी भी find_by_emailविधि की घोषणा किए बिना कॉल कर सकें । बेशक यह कुछ भी नहीं है कि UserRepository.FindBy("email", "joe@example.com")एक सांख्यिकीय रूप से टाइप की गई भाषा के रूप में हासिल नहीं किया जा सकता है , लेकिन आप इसे इसकी नीरसता से इनकार नहीं कर सकते।


4
निश्चित रूप से ऐसी चीजें हैं जो आप केवल सांख्यिकीय रूप से टाइप की गई भाषाओं में कर सकते हैं। लेकिन वे जरूरी अच्छा डिजाइन नहीं होगा।
coredump

2
सिंटैक्टिक शुगर के बारे में डायनामिक टाइपिंग और सब कुछ, अच्छी तरह से, सिंटैक्स के साथ करने के लिए बहुत कम है।
23

@leftaroundabout पैटर्न में सिंटैक्स के साथ सब कुछ है। टाइप सिस्टम का भी इसके साथ बहुत कुछ है।
user253751

4

डायनेमिक प्रॉक्सी पैटर्न प्रॉक्सी वस्तुओं को लागू करने के लिए एक शॉर्टकट है, जिसमें किसी भी वर्ग को प्रति प्रॉक्सी की आवश्यकता के बिना एक वर्ग की आवश्यकता होती है।

class Proxy(object):
    def __init__(self, obj):
        self.__target = obj

    def __getattr__(self, attr):
        return getattr(self.__target, attr)

इसका उपयोग करते हुए, Proxy(someObject) एक नई वस्तु का निर्माण होता है जो उसी के समान व्यवहार करती है someObject। जाहिर है आप किसी तरह अतिरिक्त कार्यक्षमता जोड़ना चाहते हैं, लेकिन यह शुरू करने के लिए एक उपयोगी आधार है। एक संपूर्ण स्थिर भाषा में, आपको या तो एक प्रॉक्सी क्लास लिखना होगा, जिसे आप प्रॉक्सी कोड या डायनामिक कोड जेनरेशन का उपयोग करना चाहते हैं (जो कि, माना जाता है कि कई स्थिर भाषाओं के मानक पुस्तकालय में शामिल है, बड़े पैमाने पर क्योंकि उनके डिजाइनर जानते हैं समस्याओं को इस कारण करने में सक्षम नहीं किया जा रहा है)।

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


मुझे लगता है कि मैं गो में इसका अनुकरण करने में सक्षम हो सकता हूं। वहाँ तरीकों का एक सेट है जो सभी अनुमानित वस्तुओं के पास होना चाहिए (अन्यथा बत्तख भी शांत नहीं हो सकती और सभी अलग हो जाते हैं)। मैं इन विधियों के साथ एक गो इंटरफ़ेस बना सकता हूं। मुझे इस पर अधिक सोचना होगा, लेकिन मुझे लगता है कि मेरे मन में जो काम है वह काम करेगा।
user7610

आप RealProxy और जेनरिक के साथ किसी भी .NET लैंग्वेज में ऐसा ही कुछ कर सकते हैं।
लिटिलएवोक

@LittleEwok - RealProxy रनटाइम कोड पीढ़ी का उपयोग करता है - जैसे मैं कहता हूं, कई आधुनिक स्थिर भाषाओं में इस तरह का वर्कअराउंड है, लेकिन यह गतिशील भाषा में अभी भी आसान है।
जूल्स

सी # विस्तार के तरीके थोड़े बंदर की तरह सुरक्षित हैं। आप मौजूदा तरीकों को नहीं बदल सकते, लेकिन आप नए जोड़ सकते हैं।
एंड्रयू का कहना है कि मोनिका

3

हाँ , कई पैटर्न और तकनीकें हैं जो केवल गतिशील रूप से टाइप की गई भाषा में ही संभव हैं।

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

यह साबित किया जा सकता है कि यदि कोई भाषा बंदर के पैचिंग का समर्थन करती है (या रनटाइम में प्रकारों को संशोधित करने के लिए इसी तरह की तकनीक), तो यह सांख्यिकीय रूप से जाँच नहीं की जा सकती है। इसलिए यह वर्तमान में विद्यमान भाषाओं में केवल एक सीमा नहीं है, यह स्थैतिक टाइपिंग की एक मौलिक सीमा है।

इसलिए उद्धरण निश्चित रूप से सही है - एक गतिशील भाषा की तुलना में गतिशील भाषा में अधिक चीजें संभव हैं। दूसरी ओर, कुछ प्रकार के विश्लेषण is only possible in a statically typed language. For example you always know which operations are allowed on a given type, which allows you to detect illegal operations at compile type. No such verification is possible in a dynamic language when operations can be added or removed at runtime.

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

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

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


+1 your second to last paragraph I think is the crucial argument. I'd still argue that there is a difference though as with static types you have full control of where and what you can monkey patch
jk.

2

I wonder, are there useful design patterns or strategies that, using the formulation of the quote, "don't work as types"?

Yes and no.

ऐसी स्थिति होती है जिसमें प्रोग्रामर एक चर के प्रकार को अधिक सटीकता के साथ जानता है फिर एक संकलक। संकलक को पता चल सकता है कि कुछ वस्तु है, लेकिन प्रोग्रामर को पता चल जाएगा (प्रोग्राम के अपरिवर्तकों के कारण) कि यह वास्तव में एक स्ट्रिंग है।

मुझे इसके कुछ उदाहरण दिखाइए:

Map<Class<?>, Function<?, String>> someMap;
someMap.get(object.getClass()).apply(object);

मुझे पता है कि मैंने someMap.get(T.class)कुछ Function<T, String>कैसे निर्माण किया, इस वजह से वापस आ जाएगा । लेकिन जावा केवल यकीन है कि मुझे एक फंक्शन मिला है।

एक और उदाहरण:

data = parseJSON(someJson)
validate(data, someJsonSchema);
print(data.properties.rowCount);

मुझे पता है कि data.properties.rowCount एक वैध संदर्भ और पूर्णांक होगा, क्योंकि मैंने एक स्कीमा के खिलाफ डेटा को मान्य किया है। यदि वह क्षेत्र गायब था, तो एक अपवाद फेंक दिया गया होगा। लेकिन एक कंपाइलर को केवल यह पता होगा कि या तो एक अपवाद फेंक रहा है या किसी प्रकार का सामान्य JSONValue लौटाएगा।

एक और उदाहरण:

x, y, z = struct.unpack("II6s", data)

"II6s" उस तरीके को परिभाषित करता है जो डेटा तीन चर को एनकोड करता है। चूंकि मैंने प्रारूप निर्दिष्ट किया है, मुझे पता है कि कौन से प्रकार वापस किए जाएंगे। एक संकलक को केवल यह पता होगा कि यह एक टपल लौटाता है।

इन सभी उदाहरणों का एकीकृत विषय यह है कि प्रोग्रामर प्रकार जानता है, लेकिन एक जावा स्तर प्रकार प्रणाली को प्रतिबिंबित नहीं कर पाएगी। कंपाइलर के प्रकारों का पता नहीं चलेगा, और इस प्रकार एक सांख्यिकीय रूप से टाइप की गई भाषा मुझे उन्हें कॉल नहीं करने देगी, जबकि एक गतिशील रूप से टाइप की गई भाषा होगी।

यही मूल भाव इसे प्राप्त कर रहा है:

डायनामिक टाइपिंग के बारे में आश्चर्यजनक बात यह है कि यह आपको कुछ भी व्यक्त करने देता है जो कि कम्प्यूटेबल है। और सिस्टम टाइप नहीं करते - टाइप सिस्टम आमतौर पर निर्णायक होते हैं, और वे आपको एक सबसेट तक सीमित रखते हैं।

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

हालाँकि, अपने प्रश्न पर लौटने के लिए:

मुझे आश्चर्य है, क्या उपयोगी डिज़ाइन पैटर्न या रणनीतियाँ हैं, जो बोली के निर्माण का उपयोग करते हुए, "प्रकार के रूप में काम नहीं करती हैं"?

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

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


1
java कट ऑफ पॉइंट क्यों है जिस पर आपको 'अधिक उन्नत / जटिल प्रकार की प्रणाली' में नहीं जाना चाहिए?
जे.के.

2
@jk, आपको लगता है कि मैं क्या कह रहा हूँ? मैंने स्पष्ट रूप से इस पर पक्ष लेने से परहेज किया कि क्या अधिक उन्नत / जटिल प्रकार की प्रणाली सार्थक थी या नहीं।
विंस्टन इर्वर्ट

2
इनमें से कुछ भयानक उदाहरण हैं, और अन्य टाइप किए हुए बनाम गैर-टाइप किए जाने के बजाय अधिक भाषा के निर्णय लगते हैं। मैं इस बात पर विशेष रूप से उलझन में हूँ कि लोग यह क्यों सोचते हैं कि टाइप की गई भाषाओं में deserialization बहुत जटिल है। टाइप किया हुआ परिणाम होगा data = parseJSON<SomeSchema>(someJson); print(data.properties.rowCount); और अगर किसी को क्लास से वशीकरण करने के लिए नहीं मिला है तो हम वापस आ सकते हैं data = parseJSON(someJson); print(data["properties.rowCount"]);- जो अभी भी टाइप है और उसी इरादे को व्यक्त करता है।
NPSF3000

2
@ NPSF3000, पार्सेसन कार्य कैसे करता है? यह या तो प्रतिबिंब या मैक्रोज़ का उपयोग करने के लिए प्रतीत होगा। डेटा ["properties.rowCount"] को स्थिर भाषा में कैसे टाइप किया जा सकता है? यह कैसे पता चल सकता है कि परिणामी मूल्य एक पूर्णांक है?
विंस्टन एवर्ट

2
@ NPSF3000, यदि आप इसका पूर्णांक नहीं जानते हैं, तो आप इसका उपयोग करने की योजना कैसे बनाते हैं? आप JSON में किसी सूची में तत्वों के बारे में जानने के बिना योजना कैसे बनाते हैं कि यह एक सरणी थी? मेरे उदाहरण का मुद्दा यह था कि मुझे पता था कि data.propertiesयह एक वस्तु थी और मुझे पता था कि data.properties.rowCountयह एक पूर्णांक था और मैं केवल उन कोड को लिख सकता था जो उनका उपयोग करते थे। आपका प्रस्तावित data["properties.rowCount"]वही चीज़ प्रदान नहीं करता है।
विंस्टन एवर्ट

1

उद्देश्य-सी (गतिशील रूप से टाइप किए गए) के कुछ उदाहरण यहां दिए गए हैं जो C ++ (सांख्यिकीय रूप से टाइप किए गए) में संभव नहीं हैं:

  • कई अलग-अलग वर्गों की वस्तुओं को एक ही कंटेनर में डालना।
    बेशक, इसके बाद कंटेनर की सामग्री की व्याख्या करने के लिए रनटाइम प्रकार निरीक्षण की आवश्यकता होती है, और स्थैतिक टाइपिंग के अधिकांश दोस्तों को इस बात पर आपत्ति होगी कि आप इसे पहली जगह में नहीं कर रहे हैं। लेकिन मैंने पाया है कि, धार्मिक बहसों से परे, यह काम आ सकता है।

  • उपवर्ग के बिना एक वर्ग का विस्तार करना।
    ऑब्जेक्टिव-सी में, आप मौजूदा कक्षाओं के लिए नए सदस्य कार्यों को परिभाषित कर सकते हैं, जिसमें भाषा परिभाषित व्यक्ति भी शामिल हैं NSString। उदाहरण के लिए, आप एक विधि जोड़ सकते हैं stripPrefixIfPresent:, ताकि आप कह सकें [@"foo/bar/baz" stripPrefixIfPresent:@"foo/"]( NSSringशाब्दिक के उपयोग पर ध्यान दें @"")।

  • Use of object-oriented callbacks.
    In statically typed languages like Java and C++, you have to go to considerable lengths to allow a library to call an arbitrary member of a user-supplied object. In Java, the workaround is the interface/adaptor pair plus an anonymous class, in C++ the workaround is usually template based, which implies that library code has to be exposed to user code. In Objective-C, you just pass the object reference plus the selector for the method to the library, and the library can simply and directly invoke the callback.


I can do the first in C++ by casting to void*, but that is circumventing the type system, so it does not count. I can do the second in C# with extension methods, perfectly within a type system. For the third, I think the "selector for the method" can be a lambda, so any statically typed language with lambdas can do the same, if I understand correctly. I am not familiar with ObjC.
user7610

1
@JiriDanek "I can do the first in C++ by casting to void*", not exactly, the code that reads elements has no way to retrieve the actual type on its own. You need type tags. Besides, I don't think that saying "I can do this in <language>" is the appropriate/productive way to look at this, because you can always emulate them. What matters is the gain in expressivity vs. complexity of implementation. Also, you seem to think that if a language has both static and dynamic capabilities (Java, C#), it belongs exclusively to the "static" family of languages.
coredump

1
@JiriDanek void* alone is not dynamic typing, it is lack of typing. But yes, dynamic_cast, virtual tables etc. make C++ not purely statically typed. Is that bad?
coredump

1
It suggests that having the option of subverting the type system when needed is useful. Having an escape hatch when you need it. Or somebody considered it useful. Otherwise they would not put it into the language.
user7610

2
@JiriDanek I think, you pretty much nailed it with your last comment. Those escape hatches can be extremely useful if used with care. Nevertheless, with great power comes great responsibility, and plenty are the people who abuse it... Thus, it feels a lot better to use a pointer to a generic base class that all other classes are derived from by definition (as is the case both in Objective-C and Java), and to rely on RTTI to tell the cases apart, than to cast a void* to some specific object type. The former produces a runtime error if you messed up, the later results in undefined behavior.
cmaster
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.