2014-04-06 7 views
5

मैं सामान्य रूप से परिशोधन के साथ कार्यों को लपेटने की कोशिश कर रहा हूं ताकि उन्हें परिष्करण के बिना बुलाया जा सके। उदाहरण के लिए, ARRAY-INITIAL size valueARRAY/INITIAL size value के बजायएक परिष्करण के साथ एक समारोह को कैसे लपेटें ताकि परिशोधन की आवश्यकता न हो?

wrap: function [refined [path!] args [block!]] [ 
    function args compose [ 
     (refined) (args) 
    ] 
] 

array-initial wrap 'array/initial [size value] 

भी कल्पना नहीं। सामान्य रूप में काम करने के लिए लगता है, लेकिन यह कुछ अजीब है अगर आप इसे एक समारोह का उपयोग कर फोन:

>> source array-initial 
array-initial: make function! [[size value][array/initial size value]] 

ठीक है, तो समारोह है कि क्या हो रहा है यह है:

>> n: 0 array/initial 4 does [++ n] 
== [10 11 12 13] 

>> n: 10 array-initial 4 does [++ n] 
== [10 10 10 10] 

जब मैंने इसे source मैं इस मिल रैपर में बुलाया जा रहा है और कॉल का नतीजा पारित हुआ ... कार्य नहीं। एक कार्यवाही मूल्यांकन से बचने के लिए एक शब्द-शब्द का उपयोग करना होगा:

>> array-initial-2: function [size value] [array/initial size :value] 

>> array-initial-2: 10 array-initial-2 4 does [++ n] 
[10 11 12 13] 

लेकिन मैं एक सामान्य दृष्टिकोण की तलाश में था। ऐसा होने के बिना पैरामीटर प्रॉक्सी करने का सबसे अच्छा तरीका क्या है?

+0

@ endo64 आप [एक प्रति जोड़ा] (http://stackoverflow.com/revisions/22892499/3) ... वह Rebol2 फ़ंक्शन है। Rebol3 में निर्णय समारोह के उस रूप को खत्म करने के लिए बनाया गया था ... यह अब क्या एक बार Funct रूप में जाना जाता था। उस तरह से अधिक उपयोगकर्ता के अनुकूल (और लाल संगत)। मेरे सुझाव हम मूल रूप से सिर्फ सभी कार्य Rebol2 कोड नमूने में उपयोग करता है और उसके बाद Rebol3 में कार्य करने के लिए सभी Funct स्विच ax करने की कोशिश है। – HostileFork

+0

ओह ठीक है, मैं इसे भूल गया। – endo64

उत्तर

1

यह एक आकर्षक व्यायाम, होगा प्रेम इतना था।

बाहर कर देता है आप वास्तव में एक "कम करते हैं" get-शब्द तर्क के साथ काम करता है रैप करने के लिए जरूरत है ...

R3 केवल इस समय:

unrefine: func [ 
    "Return an equivalent function with the given refinements wired in." 
    refined [any-path! block!] "The function, with the refinements to include." 
    /local ospec spec body found p s w b r 
] [ 
    ospec: spec-of get first refined: to lit-path! :refined 
    body: append copy spec: make block! length? ospec copy/deep [do reduce []] 
    append/only body/3 :refined 
    parse ospec [ 
    set s 0 1 string! (all [s append spec s]) 
    any [ 
     set w [word! | get-word! | lit-word!] (
     append spec :w 
     append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w]) 
     set b 0 1 block! (
     all [b append/only spec copy b]) 
     set s 0 1 string! (
     all [s append spec copy s]) 
    | 
     /local to end 
    | 
     set r refinement! (
     p: any [p tail spec] 
     if not found: find next refined r [append spec r]) 
     set s 0 1 string! (all [not found s append spec copy s]) 
     any [ 
     set w [word! | get-word! | lit-word!] (
      either found [p: insert p :w][append spec :w] 
      append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w]) 
     set b 0 1 block! (
      all [b either found [p: insert/only p copy b][append/only spec copy b]]) 
     set s 0 1 string! (
      all [s either found [p: insert p copy s][append spec copy s]]) 
     ] 
    ] 
    ] 
    func spec body 
] 
+0

यह एक मुट्ठी भर है! लेकिन हम किसी भी मामले में, इसके जवाब के रूप में इसके साथ आगे बढ़ेंगे। – HostileFork

1

मेरा मानना ​​है कि सामान्य दृष्टिकोण यह है कि आपको फ़ंक्शन तर्कों के भीतर शब्दों का उपयोग करने के तरीके और कार्यों के लिए पारित होने के तरीके के लिए खाते हैं।

wrap: func [ 
    'refined [path!] 
    args [block!] 
][ 
    func map-each arg args [ 
     either get-word? :arg [to word! arg] [:arg] 
    ] compose [ 
     (refined) (
      map-each arg args [ 
       either lit-word? :arg [to get-word! arg] [:arg] 
      ] 
     ) 
    ] 
] 

यहां दो मुद्दे हैं- शब्द परिभाषित करने वाले शब्द, और कार्य को पारित शब्दों। पूर्व दो मुख्य रूपों में आते हैं: शब्द! सामान्य तर्कों के लिए और जलाया शब्द! शाब्दिक तर्क के लिए। हमारे spec में, अगर हमारे पास मिलता है शब्द! तर्क, हम चाहते हैं कि वे सामान्य तर्क हों और शब्द में परिवर्तित करें!। जब तर्क पारित करने की बात आती है, तो हमारे पास दो रूप होते हैं: शब्द! तर्क का मूल्यांकन करने के लिए और शब्द प्राप्त करें! शब्द को इंगित करने के लिए। यदि हमारा spec जला-शब्द संभालता है!, हमें शब्द प्राप्त करने की आवश्यकता है!शब्द के रूप में! सचमुच पारित किया जाएगा।

उम्मीद है कि सभी समझ में आता है!

वैसे भी, यह कैसे बाहर खेलता है:

wrapped-foobar: wrap foo/bar ['literal evaluated :referred] 

हम अपने तीन प्रकार है, पहले आप जलाया-शब्द का उपयोग किए बिना शब्दों के रूप में सचमुच-तरह के माध्यम से मूल्यों पारित करने के लिए अनुमति देता है; दूसरा गुजरने से पहले तर्क का मूल्यांकन करता है; और तीसरा निर्दिष्ट मूल्य पारित करेगा-यह फ़ॉर्म आपको कार्यों के माध्यम से पारित करने की अनुमति देता है। आप के साथ अंत:

make function! [ 
    ['literal evaluated referred] [ 
     foo/bar :literal evaluated :referred 
    ] 
] 

अब सरणी की पसंद/प्रारंभिक पर है:

array-initial: wrap array/initial [size :value] 
n: 1 
array-initial 4 does [++ n] 
+0

ठीक है, बढ़िया। यह एक बग को हल करता है जो मुझे गिटहब पर पूछ रहा था। :-) मैं यह महसूस हो रहा है एक आम पर्याप्त इच्छा है कि यह अच्छा होगा अगर समारोह विनिर्देश बोली आप और अधिक आसानी से विशेषज्ञता के कुछ प्रकार करते हैं सकता है। मैं नहीं बल्कि प्रतिबिंब के साथ ऐसा होता है लेकिन शायद किसी को एक और जवाब यह है कि उस के लिए समायोजित कर देता है अगर वे ऊब रहे हैं जोड़ सकते हैं ... – HostileFork

+0

GitHub उपयोगकर्ताओं, हाँ? – rgchris

+0

एचएम ... यहां एक मुद्दा यह है कि प्रोटोटाइप लपेटा हुआ फ़ंक्शन से मेल नहीं खाता है। तो उदाहरण के लिए, रैपर एक उद्धृत तर्क के साथ समाप्त हो सकता है जब मूल में यह नहीं था * (यह '/ प्रारंभिक मान 'नहीं है ... लेकिन लपेटा हुआ सरणी-प्रारंभिक' मान 'लेता है) *। क्या लपेटा प्रोटोटाइप लाइन मूल के साथ बनाने का कोई तरीका है? – HostileFork

0

सीधे शब्दों में कहें, तो आप (मुझे उर्फ) समारोह तर्क ब्लॉक को दर्शाती बिना यह पूरा नहीं कर सकते कि आप लपेट रहे हैं। और कोई रास्ता नहीं है।

एक समारोह जलाया-शब्द फार्म या एक बहस के get-शब्द प्रपत्र उपयोग करता है, उस भेद अपने आवरण में नजर आता जाना चाहिए।

Why doesn't Rebol 3 honor quoted function parameters that are parenthesized?

@ rgchris की टिप्पणी के अनुसार, आप क्या करना (यानी मैं) जरूरत parse the argument block है: क्या फर्क पैरामीटर का :foo और 'foo प्रपत्र के बीच है के विवरण के लिए इस उत्तर देखें। एक उचित उत्तर में कोड होगा जो ऐसा करता है, इसलिए लोगों को इसे जोड़ने में स्वतंत्र महसूस होना चाहिए।

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

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