नए अंतर्निहित ऑपरेटरों को परिभाषित करना
मानक गोल्फस्क्रिप्ट दुभाषिया में शायद ही कभी इस्तेमाल की जाने वाली सुविधा होती है जो रूबी कोड को दोहरे उद्धृत स्ट्रिंग शाब्दिक रूप में प्रक्षेपित करने की अनुमति देती है।
इस सुविधा का अधिक सामान्यतः उपयोग न करने का एक कारण यह है कि अजीब तरह से, संकलित कोड को संकलन समय पर निष्पादित किया जाता है , और आउटपुट को GolfScript दुभाषिया द्वारा कैश किया जाता है, ताकि उसके बाद समान स्ट्रिंग शाब्दिक हमेशा एक ही मूल्य प्राप्त कर सके, अंदर भी स्ट्रिंग इम्फ़ाल।
हालांकि, एक बात यह है कि यह फीचर रूबी कोड में लागू नए गोल्फस्क्रिप्ट ऑपरेटरों को परिभाषित करने के लिए अच्छा है। उदाहरण के लिए, यहां नए बाइनरी एडिशन ऑपरेटर को परिभाषित करने का तरीका बताया गया है, जो बिल्ट-इन +
ऑपरेटर की तरह काम करता है :
"#{var'add','gpush a+b'.cc2}";
इससे कोई फर्क नहीं पड़ता कि आपने अपने कोड में परिभाषा कहाँ रखी है; जैसे ही रूबी कोड युक्त दोहरे भाग वाले स्ट्रिंग को पार्स किया जाता है, वैसे ही नया ऑपरेटर परिभाषित हो जाता है। add
ऑपरेटर ऊपर परिभाषित काम करता है वास्तव में की तरह निर्मित +
ऑपरेटर, और बिल्कुल उसी तरह इस्तेमाल किया जा सकता:
1 2 add # evaluates to 3
"foo" "bar" add # evaluates to "foobar"
बेशक, एक नए अतिरिक्त ऑपरेटर को परिभाषित करना बहुत बेकार है, जब तक कि आपने कुछ मूर्खतापूर्ण तरीके से नहीं किया है जैसे अंतर्निहित निर्माण को मिटा दें+
ऑपरेटर को । लेकिन आप नए ऑपरेटरों को परिभाषित करने के लिए उसी चाल का उपयोग कर सकते हैं जो गोल्फस्क्रिप्ट को आसानी से नहीं कर सकता है, जैसे कि कहते हैं, समान रूप से एक सरणी फेरबदल करना:
"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";
10,shuf # evaluates to 0,1,2,...,9 in random order
या पूरे स्टैक की सामग्री को प्रिंट करना:
"#{var'debug','puts Garray.new($stack).ginspect'.cc}";
4,) ["foo" debug # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched
या इंटरैक्टिव इनपुट:
"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";
]; { "> " print gets ~ ]p 1 } do # simple GolfScript REPL
या यहां तक कि वेब एक्सेस:
"#{
require 'net/http'
require 'uri'
var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";
"http://example.com" get
बेशक, कुछ हद तक गोल्फ खिलाड़ी (और जोखिम भरा!) उत्तरार्द्ध का कार्यान्वयन उदाहरण के लिए होगा:
"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";
अपने आप में विशेष रूप से गोल्फ नहीं है, यह आपको गोल्फस्क्रिप्ट की क्षमताओं का विस्तार करने की अनुमति देता है जो अंतर्निहित कमांड प्रदान करता है।
यह कैसे काम करता है?
इस तरह से नए गोल्फस्क्रिप्ट ऑपरेटरों को कैसे परिभाषित किया जाए, इस पर आधिकारिक संदर्भ, दुभाषिया के लिए स्रोत कोड है । उस ने कहा, यहाँ कुछ त्वरित सुझाव है:
name
रूबी कोड चलाने वाले एक नए ऑपरेटर को परिभाषित करने के लिए code
, उपयोग करें:
var'name','code'.cc
कोड के अंदर, gpop
स्टैक से एक मान को पढ़ने के लिए और gpush
एक को वापस धकेलने के लिए उपयोग करें। आप सरणी के माध्यम से सीधे स्टैक तक भी पहुंच सकते हैं $stack
। उदाहरण के लिए, दोनों को a
और b
ढेर पर धकेलने के लिए, यह करने के लिए गोल्फ खिलाड़ी $stack<<a<<b
है gpush a;gpush b
।
[
सरणी प्रारंभ मार्कर की स्थिति को सरणी में संग्रहीत किया जाता है $lb
। gpop
समारोह उनकी स्थिति ढेर सिकुड़ती नीचे अगर नीचे इन मार्कर का समायोजन, लेकिन जोड़ तोड़ का ख्याल रखता है $stack
सीधे सरणी नहीं करता है।
.cc
रूबी कोड को एक स्ट्रिंग में एक गोल्फस्क्रिप्ट ऑपरेटर में संकलित करने की स्ट्रिंग विधि सिर्फ एक सुविधा आवरण है Gblock.new()
। इसके वेरिएंट भी हैं .cc1
, .cc2
और .cc3
यह ऑपरेटर को स्वचालित रूप से स्टैक से 1, 2 या 3 तर्क देता है और उन्हें चर में असाइन करता है a
, b
और c
। एक ऐसी .order
विधि भी है जो काम करती है .cc2
, सिवाय इसके कि यह स्वचालित रूप से टाइप प्राथमिकता के आधार पर तर्क देती है ।
GolfScript ढेर पर सभी मान रहे हैं (और होना चाहिए!) प्रकार की वस्तुओं Gint
, Garray
, Gstring
या Gblock
। अंतर्निहित देशी पूर्णांक या सरणी, जहां आवश्यक हो, .val
विधि के माध्यम से पहुँचा जा सकता है ।
- हालाँकि, ध्यान दें कि
Gstring.val
एक सरणी देता है Gint
! Gstring
एक देशी रूबी स्ट्रिंग को चालू करने के लिए , .to_s
इसके बजाय उस पर कॉल करें (या इसे उस संदर्भ में उपयोग करें जो स्वचालित रूप से करता है, जैसे स्ट्रिंग प्रक्षेप)। .to_gs
किसी भी जीएस मूल्य पर कॉल करना इसे एक में बदल देता है Gstring
, इसलिए किसी भी जीएस मूल्य के साथ सख्ती की जा सकती है .to_gs.to_s
।
यह gpush
फ़ंक्शन संबंधित GS प्रकारों में देशी रूबी नंबर, स्ट्रिंग्स या सरणियों को ऑटो-रैप नहीं करता है, इसलिए आपको अक्सर यह स्वयं स्पष्ट रूप से कॉल करके करना होगा Gstring.new()
। यदि आप स्टैक पर GS मान प्रकारों में से एक के अलावा कुछ भी धक्का देते हैं, तो कोई भी कोड जो बाद में हेरफेर करने की कोशिश करता है, दुर्घटनाग्रस्त होने की संभावना है।
GS मान प्रकार में एक .factory
विधि भी होती है जो टाइप के कंस्ट्रक्टर को कॉल करती है, जो उनकी सामग्री में हेरफेर करने के बाद सरणियों / स्ट्रिंग्स को फिर से तैयार करने के लिए उपयोगी हो सकता है। सभी प्रकारों में एक .coerce
विधि भी होती है जो टाइप ज़बरदस्ती करती है : a.coerce(b)
एक जोड़ी युक्त रिटर्न देता है a
और b
एक ही प्रकार के लिए मजबूर किया जाता है।
... x
है... [x]
? सबसे अच्छा मैं देख सकता हूँ[.;]
।