tags:

views:

54

answers:

1

I have a set of code that, depending on how the program is initiated, will either be executed locally or sent to a remote machine for execution. The ideal way I imagine this could work would look something like the following:

line_of_code = 'do_something_or_other();';

if execute_remotely
    send_via_udp(line_of_code);
else
    eval(line_of_code);
end

The thing is, I know that the eval() function is ridiculously inefficient. On the other hand, if I write out line_of_code in each section of the if block, that opens the door for errors. Is there any other way that I can do this more efficiently than by simply using eval()?

+3  A: 

EDIT: After more consideration and some discussion in the comments, I have my doubts that function handles can be transmitted via UDP. I'm therefore updating my answer, instead suggesting the use of the function FUNC2STR to convert the function handle to a string for transmission, then using the function STR2FUNC to convert it back to a function handle again after transmission...

To get around using EVAL, you can use a function handle instead of storing the line of code to be executed in a string:

fcnToEvaluate = @do_something_or_other;  %# Get a handle to the function

if execute_remotely
  fcnString = func2str(fcnToEvaluate);   %# Construct a function name string
                                         %#   from the function handle
  send_via_udp(fcnString);               %# Pass the function name string
else
  fcnToEvaluate();                       %# Evaluate the function
end

The above assumes that the function do_something_or_other already exists. You can then do something like the following on the remote system:

fcnString = receive_via_udp();        %# Get the function name string
fcnToEvaluate = str2func(fcnString);  %# Construct a function handle from
                                      %#   the function name string
fcnToEvaluate();                      %# Evaluate the function

As long as the code (i.e. m-file) for the function do_something_or_other exists on both the local and remote systems, I think this should work. Note that you could also use FEVAL to evaluate the function name string instead of converting it to a function handle first.

If you need to create a function on the fly, you can initialize fcnToEvaluate as an anonymous function in your code:

fcnToEvaluate = @() disp('Hello World!');  %# Create an anonymous function

And the code to send, receive, and evaluate this should be the same as above.

If you have arguments to pass to your function as well, you can place the function handle and input arguments into a cell array. For example:

fcnToEvaluate = @(x,y) x+y;  %# An anonymous function to add 2 values
inArg1 = 2;                  %# First input argument
inArg2 = 5;                  %# Second input argument
cellArray = {fcnToEvaluate inArg1 inArg2};  %# Create a cell array

if execute_remotely
  cellArray{1} = func2str(cellArray{1});  %# Construct a function name string
                                          %#   from the function handle
  send_via_udp(cellArray);                %# Pass the cell array
else
  cellArray{1}(cellArray{2:end});  %# Evaluate the function with the inputs
end

In this case, the code for send_via_udp may have to break the cell array up and send each cell separately. When received, the function name string will again have to be converted back to a function handle using STR2FUNC.

gnovice
What about the function arguments? They're encoded in a string, remember. feval() takes the function and then each individual argument, not a string which can be parsed into arguments. How do I pass them?
eykanal
@eykanal: I added an example for how you could handle input arguments.
gnovice
@gnovice - Does the function handle actually transfer the contents of the function? I had always thought that function handles are references to functions, not functions themselves. But I wouldn't expect a reference to work on a remote machine. Is my understanding totally wrong? This is a great solution (if it works ;) ).
mtrw
@mtrw: I don't think function handles are pure "references" in the way that a pointer to a memory location is. If the code (i.e. m-file) for a function exists both locally and on the remote system, I don't think there will be any problems. I'm not totally sure about anonymous functions, but I know that variables specified in the body of the expression are captured and held constant throughout the lifetime of the function handle, suggesting that the handle somehow has this data associated with it. Unfortunately, without access to the function `send_via_udp`, I can't really test anything.
gnovice
@gnovice - Where's Loren when you really need her? Anyway, I hope it works, it's a very creative solution.
mtrw
@gnovice - actually, the `send_via_udp` function is just `fprintf(u,string)`, where `u` is an object created by the `udp` function (part of the instrument control toolbox). Anyway, thanks for the very creative solution.
eykanal

related questions