[R] tcl tk command function with arguments ??

peter dalgaard pdalgd at gmail.com
Sat Feb 25 01:03:48 CET 2012


On Feb 24, 2012, at 19:44 , ilai wrote:

> On Fri, Feb 24, 2012 at 12:58 AM, Alexander <juschitz_alexander at yahoo.de> wrote:
> 
>> I would like to know if its possible to use a function with arguments as a
>> command in tcl tk.
> 
> Yes
> 
> <snip>
> I think
>> this is due to the fact that the PressedOK(3) was the last call of the
>> function, but I don't understand why all the other buttons have now a
>> different command. Any idea?
>> 
> 
> Because in for loop i is overwritten every time - as you said i=3 is
> the last command.
> Replacing for with sapply should fix it:
> 
> require(tcltk)
> OK.but <- NULL
> PressedOK <- function(i)
> {
>   tkmessageBox(message=paste("You pressed OK!",i,sep=""))
> }
> 
> tt <- tktoplevel()
> sapply(1:3,function(i){
>  OK.but[[i]] <- tkbutton(tt,text="OK",command=function()PressedOK(i))
>  tkgrid(OK.but[[i]])
> })
> tkfocus(tt)
> 


Now that's just weird... Firstly, it has nothing to do with sapply vs. for loops. It just works because you are inserting yet another function environment. Secondly, if there was ever a point to having the buttons in the OK.but list, it is not going to work anymore because you are assigning each element to a different list, one per function environment.

The problem with the original suggestion:

for(i in seq(3)){
	OK.but[[i]] <- tkbutton(tt,text="OK",command=function()PressedOK(i))
	tkgrid(OK.but[[i]])
}

is that the callback function will access  i  in the enclosing environment since it is neither a local variable or a function argument. This will happen when the callback is _executed_, at which time the loop index has long since reached the value of 3.

A more straightforward fix could be to do 

command = local({i <- i; function() PressedOK(i)}) 

Other options might use the fact that command arguments can be R call objects, so you can insert the value of i  directly into the call using

command = substitute(PressedOK(i), list(i=i))

or 

command = bquote(PressedOK(.(i)))

[ There's a bug fixed in 2.14.2-RC which prevents this from working in a for loop; for 2.14.1 and earlier, you'll need .(force(i)) ]

> Cheers,
> Elai
> 
> 
>> Thanks
>> 
>> 
>> --
>> View this message in context: http://r.789695.n4.nabble.com/tcl-tk-command-function-with-arguments-tp4416470p4416470.html
>> Sent from the R help mailing list archive at Nabble.com.
>> 
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

-- 
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Email: pd.mes at cbs.dk  Priv: PDalgd at gmail.com



More information about the R-help mailing list