आर

2016-03-22 2 views
6

संक्षिप्त उदाहरण में स्वच्छ, सरल फ़ंक्शन फैक्ट्रियां। मैं विभिन्न "चश्मा", f(spec) के साथ परीक्षण करके एक फ़ंक्शन के व्यवहार की खोज कर रहा हूं। मैंने हाथ से एक spec लिखा, spec1, और इस पर विविधता के रूप में नई चश्मा बना रहा हूँ।आर

spec1 = list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x)) 

make_spec = function(f = function(x) 10-x, xtheta = 2) 
    list(fy = list(a = 1), fx = list(f1 = f, f2 = function(x) xtheta-x)) 

res1 = make_spec() 

# first problem: they don't match 

    all.equal(res1,spec1) 
    # [1] "Component “fx”: Component “f2”: target, current do not match when deparsed" 
    #^this happens, even though... 
    res1$fx$f2(4) == spec1$fx$f2(4) 
    # TRUE 

# second problem: res1 is fugly 

    res1 
    # $fy 
    # $fy$a 
    # [1] 1 
    # 
    # 
    # $fx 
    # $fx$f1 
    # function (x) 
    # 10 - x 
    # <environment: 0x000000000f8f2e20> 
    # 
    # $fx$f2 
    # function (x) 
    # xtheta - x 
    # <environment: 0x000000000f8f2e20> 

    str(res1) 
    # even worse 

make_spec के लिए मेरा लक्ष्य हैं ...

  1. all.equal(spec1, res1) और/या identical(spec1, res1)
  2. str(res1) मानव पठनीय होने के लिए (कोई <environment: ptr>: ऐसा करने के लिए, मैं एक समारोह लिखने का फैसला किया टैग या srcfilecopy)
  3. substitute और eval से बचने के लिए पूरी तरह से संभव है (उच्च प्राथमिकता नहीं)
  4. substitute के दूसरे आर्ग लिखने से बचने के लिए (देखें "पूर्ण" नीचे दिए गए उदाहरण)

वहाँ कुछ या इन लक्ष्यों के सभी प्राप्त करने के लिए एक मुहावरेदार रास्ता नहीं है?


पूर्ण उदाहरण। मुझे यकीन है कि अगर ऊपर के उदाहरण पूरी तरह से अपने प्रयोग के मामले को शामिल किया गया नहीं हूँ, इसलिए यहाँ उत्तरार्द्ध है:

spec0 = list(
    v_dist = list(
     pdf = function(x) 1, 
     cdf = function(x) x, 
     q = function(x) x, 
     supp = c(0,1) 
    ) 
    , 
    ucondv_dist = { 
     ucondv_dist = list() 
     ucondv_dist$condmean = function(v) 10-v 
     ucondv_dist$pdf   = function(u,v) dnorm(u, ucondv_dist$condmean(v), 50) 
     ucondv_dist$cdf   = function(u,v) pnorm(u, ucondv_dist$condmean(v), 50) 
     ucondv_dist 
    } 
) 

make_spec = function(ycondx_condmean = function(x) 10-x, ycondx_sd = 50){ 

    s = substitute(list(
    x_dist = list(
     pdf = function(x) 1, 
     cdf = function(x) x, 
     q = function(x) x, 
     supp = c(0,1) 
    ) 
    , 
    ycondx_dist = { 
     ycondx_dist = list() 
     ycondx_dist$condmean = ycondx_condmean 
     ycondx_dist$pdf  = function(u,v) dnorm(u, ycondx_dist$condmean(v), ycondx_sd) 
     ycondx_dist$cdf  = function(u,v) pnorm(u, ycondx_dist$condmean(v), ycondx_sd) 
     ycondx_dist 
    } 
) 
    , list(ycondx_condmean=ycondx_condmean, ycondx_sd = ycondx_sd)) 

    eval(s, .GlobalEnv) 
} 

res0 = make_spec() 

साइड नोट। मुझे नहीं पता कि "फ़ंक्शन फैक्ट्री" सही शब्द है, क्योंकि मैं कंप्यूटर वैज्ञानिक नहीं हूं, लेकिन ऐसा लगता है। मुझे केवल a paragraph on the concept related to R मिला।

+0

वास्तव में ऐसा लगता है तुम सिर्फ आर पसंद नहीं है और वास्तव में किसी अन्य भाषा, स्काला या erlang के लिए शायद देख रहे हैं .. 'str' समारोह काफी जटिल है, लेकिन आप निश्चित रूप से यह फिर से लिखने के लिए स्वागत कर रहे हैं। यह एक बड़ी परियोजना होगी, जो कि एक उचित एसओ सवाल होगा। 'Eval' और' विकल्प 'के बिना भाषा पर प्रोग्राम करने की कोशिश करने की धारणा विकृत और कहीं भी उचित नहीं लगती है। –

+1

@ 42- प्रतिक्रिया के लिए धन्यवाद। खैर, प्राथमिकता की मेरी सूची में 'eval' और 'substitute' से परहेज करना कम है, लेकिन अगर मैं सिर्फ उनसे बचने का कुछ तरीका देख रहा हूं, तो मैं इसे जानना चाहता हूं। – Frank

+1

आप 'लाइब्रेरी (pryr) ',' res1 $ fx <- lapply (res1 $ fx, unenclose)', 'all.equal (res1, spec1) का उपयोग करके भाग 1 प्राप्त कर सकते हैं (अजीब बात यह है कि आप केवल एक फ़ंक्शन से अधिक लौटते हैं) ' – Chris

उत्तर

3

कार्यों के संलग्न वातावरण अलग-अलग होते हैं जिससे बाहर निकलने में आउटपुट/अंतर में अंतर होता है।

  • वातावरण ही
  • स्थानापन्न समारोह शरीर में संलग्न वातावरण से चर बनाने: तो, वहाँ वांछित आउटपुट प्राप्त करने के लिए दो बातें कर रहे हैं।

हालांकि, ऐसा करने से आपको उस ईंधन/विकल्प की एक डबल खुराक मिलती है जिसे आप नहीं चाहते थे, इसलिए शायद एक विकल्प होगा।

make_spec <- function(f = function(x) 10-x, xtheta = 2) { 
    e <- parent.frame() 
    fixClosure <- function(func) 
    eval(eval(substitute(substitute(func)), parent.frame()), e) 

    list(fy = list(a = 1), fx = list(
    f1 = fixClosure(f), 
    f2 = fixClosure(function(x) xtheta-x) 
)) 
} 

spec1 <- list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x)) 
res1 <- make_spec() 

all.equal(res1, spec1) 
[1] TRUE 
+0

धन्यवाद। मैं यहाँ और इस दृष्टिकोण की तरह उपयोग के रूप में eval और विकल्प के साथ ठीक हूँ। प्रश्न थोड़ी देर के लिए छोड़ने के लिए जा रहे हैं, क्योंकि मुझे थोड़ी देर के लिए मेरी मूल समस्या के किसी भी समाधान को लागू करने का मौका नहीं मिलेगा। – Frank