0

With the package svSocket I'm trying to execute in the server a generic expression

expr <- "demo<-new.env()"
evalServer(con, expr, expr)
> evalServer(con, parse(text=expr))
Error in source(objcon, local = TRUE, echo = FALSE, verbose = FALSE) : 
  objcon:1:65: unexpected '<'
1: ..Last.value <-structure(expression(demo<-new.env()), srcfile = <

How can I avoid that? PS: my need is to programmatically create object into the server. e.g. demo would come from a user input and paste()d into the above string.

Reproducible example ### Open two rsession

# run in the 1st rsession
require(svSocket)
startSocketServer()

# run in the 2nd rsession
con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)
expr <- "demo<-new.env()"
evalServer(con, expr, expr)
Michele
  • 8,563
  • 6
  • 45
  • 72
  • Possible bug in the function. `evalServer(con, "demo <- new.env()" ) ` does actually create the new environment `"demo"` in my workspace (but the function still returns an error). – Simon O'Hanlon Nov 07 '13 at 16:58
  • @SimonO101 thanks for the edit. And yes! I have the same behaviour. `evalServer(con, parse(text=expr))` does create the environment, didn't check before... Well good for now. But still bad cause I can't implement a proper error handling. `class(try(evalServer(...)))` says `try-error`. so I would have to "manually" check with `exists` if it did the job. – Michele Nov 07 '13 at 18:54

1 Answers1

1

Here is workaround for what you want do.

First, start R with a socket server in a terminal window:

$ R
> require(svSocket)
> startSocketServer()
> 

Then, in a different R process, load svSocket, connect to the socket server and use evalServer():

$ R
> require(svSocket)
> options(prompt = "RClient> ")
RClient> con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)

Now, evalServer() works by serialising-deserializing R objects in order to send them through the socket. Not all R objects are serialisable… and environments are among those objects that cause problems.

It is possible to do what you want do, but you must take care that an environment object never get passed from the client to the server, or back. One way to do this, is by sending the instruction as a text string (making sure that it will not return the environment):

RClient> evalServer(con, expr, "demo <- new.env(); NULL")

Then, you must instruct the server to parse and evaluate that code on his side. From the client:

RClient> evalServer(con, eval(parse(text = expr)))

You can check that demo object is created in the server, and is of right class from within the client (here objects are serialisable, so, no problems):

RClient> evalServer(con, ls())
[1] "demo" "expr"
RClient> evalServer(con, class(demo))
[1] "environment"
RClient> 

And, of course, you also have to take care when you manipulate "demo" from the client. Don't forget at the end:

RClient> close(con)
  • Hi! And thanks for joining my discussion! You right I wasn't clear. Especially for a brand-new tag (I felt free to create it btw, I think you may want to change/improve it). Anyway, I actually did all the above but I forgot to ensure `NULL` is returned! Thanks. And be ready more question (hopefully less stupid) are coming :). – Michele Nov 08 '13 at 15:35