להתגבר על העצלנות!

24 views
Skip to first unread message

amit gal

unread,
Feb 27, 2014, 10:31:44 AM2/27/14
to israel-r-...@googlegroups.com
לפעמים האבלואציה העצלנית של R מוציאה אותי מדעתי. אני רוצה להכניס לרשימה מספר פונקציות (לקריאה מאוחרת שלהן). כל פונקציה נסמכת קצת על קודמתה. הנה קוד שמתאר משהו דומה (תקראו את הקוד, תבינו מה אני רוצה. אבל R לא אוהב את הקוד הזה)

f = function(x) x
fl = list(f)
for (i in 2:10) {
  fl[[i]] = function(x) fl[[i-1](x)+1
}

בקיצור הפונקציה הראשונה היא פונקצית הזהות, וכל פונקציה מחזירה ערך הגדול באחד ממה שהפונקציה הקודמת מחזירה.

אבל זה לא עובד!!!!!
האבלואציה העצלנית של R גורמת לזה שהפונקציה שנכנסת לרשימה עוד לא נוצרה. היא נוצרת רק כשקוראים לה (למשל)

fl[[3]](5)

אבל אז לא בטוח שi מוגדר בכלל. ספציפית אם מנסים לעשות זאת מיד אחרי הלולאה הנ"ל, אז הערך של i הוא 10, אז הקריאה לפונקציה שלי מנסה לבדוק את הערך של הפונקציה ה9 ברשימה, שגם היא לא נוצרה, אז הוא מנסה ליצור אותה, שוב, הוא בודק את הערך של i (עדיין 10), ולכן הוא שוב מנסה לבדוק את הפונקציה ה9 ברשימה. לולאה אינסופית של אבלואציה. אם מנסים לעשות זאת כש i לא מוגדר, אז R צועק שחסר לו המשתנה הזה.

ואני שואל - כיצד? כיצד אפשר להגדיר רשימת פונקציות כמו שאני צריך? איך אפשר לגרום לR להעריך את הביטוי ברגע הכנסתו לביטוי הבא (כלומר להעריך את i, או אפילו יותר טוב, להעריך את fl[[i-1] בזמן ההשמה לתוך fl[[i]]?

אוף....



Jonathan Rosenblatt

unread,
Feb 27, 2014, 2:24:19 PM2/27/14
to israel-r-user-group
For proper recursion, have a look at Recall()
You can force evaluation by using force() but judging from your example, I suspect you are already familiar with it.
I guess in this example it would look like:

f = function(x) { force(x) ; function() x }

fl = list(f)
for (i in 2:10) {
  fl[[i]] = function(x) {force(x) ; function() fl[[i-1]](x)+1 }
}


Does this help?



--
You received this message because you are subscribed to the Google Groups "Israel R User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to israel-r-user-g...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Jonathan Rosenblatt
www.john-ros.com

amit gal

unread,
Feb 27, 2014, 3:56:04 PM2/27/14
to israel-r-...@googlegroups.com
There is no recursion here, so I can't see how to use Recall to accomplish what I need.
Also, I have tried "force()" in many configurations, but couldn't make anything to work properly. your examples doesn't work either.

I think that beyond the laziness of R, it is the lack of call by reference. what I really need is a reference to the functions and not the functions themselves.

anyway, after match trial and error I came around with the following ugly workaround:

f = function(x)
fl = list(f)
for (i in 2:10) {
  tmp = paste("function(x) { fl[[",i-1,"]](x)+1}")
  fl[[i]] = eval(parse(text=tmp))
}

## fl[[4]](8) = 11

or more generally, if you don't want to rely on list structure, the more extreme way (and much uglier) to do it is:


gl = list(f)
for (i in 2:10) {
  tmp = paste("function(x) { a=(",paste(deparse(gl[[i-1]]),collapse="\n"),")(x);a+1}")
  gl[[i]] = eval(parse(text=tmp))
}


amit gal

unread,
Feb 27, 2014, 4:03:07 PM2/27/14
to israel-r-...@googlegroups.com
Or, on second thought, you can make it recursive!

f = function(x) x

ff = function(level,x) {
  if(level==1) return(f(x))
  return(Recall(level-1,x)+1
}

Reply all
Reply to author
Forward
0 new messages