Trying to avoid eval()

  • Follow


I'm trying to avoid using eval() but am at a loss.  My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.

I have a class called "Wavefront" with a method called "ToMAT".  Let W be an instance of a Wavefront object.  I want the behavior of 

     >>W.ToMAT('filename.mat')

to save the variable W to filename.mat.  I want the variable name to be preserved so that

     >> load('filename.mat')

creates a variable called W.  The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff).  This is a member function in Wavefront.m.

     function [success, filename] = ToMAT(obj, filename)
     var_name = inputname(1);
     eval(sprintf('%s = obj;', var_name));
     save(filename, var_name);

Can somebody solve this problem without using eval?

Thanks,
Eric
0
Reply Eric 5/12/2010 5:51:04 PM

"Eric " <not@givingemail.com> wrote in message <hsepq8$1a7$1@fred.mathworks.com>...
> I'm trying to avoid using eval() but am at a loss.  My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.
> 
> I have a class called "Wavefront" with a method called "ToMAT".  Let W be an instance of a Wavefront object.  I want the behavior of 
> 
>      >>W.ToMAT('filename.mat')
> 
> to save the variable W to filename.mat.  I want the variable name to be preserved so that
> 
>      >> load('filename.mat')
> 
> creates a variable called W.  The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff).  This is a member function in Wavefront.m.
> 
>      function [success, filename] = ToMAT(obj, filename)
>      var_name = inputname(1);
>      eval(sprintf('%s = obj;', var_name));
>      save(filename, var_name);
> 
> Can somebody solve this problem without using eval?
> 
> Thanks,
> Eric

one of the many(!) other solutions

function tom(d,fnam)
     s.(inputname(1))=d;
     save(fnam,'s');
end

us
0
Reply us 5/12/2010 6:13:04 PM


Eric wrote:

> I have a class called "Wavefront" with a method called "ToMAT".  Let W 
> be an instance of a Wavefront object.  I want the behavior of
>     >>W.ToMAT('filename.mat')
> 
> to save the variable W to filename.mat.  I want the variable name to be 
> preserved so that
> 
>     >> load('filename.mat')
> 
> creates a variable called W.  The only way I have figured out how to do 
> this is with code that looks like the following (I've trimmed out some 
> error handling and other stuff).  This is a member function in Wavefront.m.
> 
>     function [success, filename] = ToMAT(obj, filename)
>     var_name = inputname(1);
>     eval(sprintf('%s = obj;', var_name));
>     save(filename, var_name);
> 
> Can somebody solve this problem without using eval?

function [success, filename] = ToMat(obj, filename);
   var_name = inputname(1);
   SaveStruct.(var_name) = obj;
   save(filename, '-STRUCT', SaveStruct);
0
Reply Walter 5/12/2010 6:15:16 PM

"Eric " <not@givingemail.com> wrote in message <hsepq8$1a7$1@fred.mathworks.com>...
> I'm trying to avoid using eval() but am at a loss.  My code works fine using eval(), but I'm curious to see if somebody can solve the same problem without it.
> 
> I have a class called "Wavefront" with a method called "ToMAT".  Let W be an instance of a Wavefront object.  I want the behavior of 
> 
>      >>W.ToMAT('filename.mat')
> 
> to save the variable W to filename.mat.  I want the variable name to be preserved so that
> 
>      >> load('filename.mat')
==============

Note: It is dangerous to create variables using load, and therefore questionable why you would want to do this.

The advisable practice is to do

S=load('filename');
myVariable=S.whatever; %whatever is the variable name as stored in the file


> creates a variable called W.  The only way I have figured out how to do this is with code that looks like the following (I've trimmed out some error handling and other stuff).  This is a member function in Wavefront.m.
> 
>      function [success, filename] = ToMAT(obj, filename)
>      var_name = inputname(1);
>      eval(sprintf('%s = obj;', var_name));
>      save(filename, var_name);
> 
> Can somebody solve this problem without using eval?
==============

The following modification should do it.

    function [success, filename] = ToMAT(obj, filename)
     var_name = inputname(1);
     S.(var_name)=obj;
     save(filename, '-struct',S);
0
Reply Matt 5/12/2010 6:17:04 PM

us wrote:

> function tom(d,fnam)
>     s.(inputname(1))=d;
>     save(fnam,'s');
> end

That would create a .mat file in which the variable name was 's', rather 
than being the variable name of the object. Adding the -struct option 
does the needed conversion work.
0
Reply Walter 5/12/2010 6:25:16 PM

Walter Roberson <roberson@hushmail.com> wrote in message <goCGn.8258$Gx2.5836@newsfe20.iad>...
> us wrote:
> 
> > function tom(d,fnam)
> >     s.(inputname(1))=d;
> >     save(fnam,'s');
> > end
> 
> That would create a .mat file in which the variable name was 's', rather 
> than being the variable name of the object. Adding the -struct option 
> does the needed conversion work.

walter

now THAT is not (necessarily) advisable (in my view)...
the OP should learn to organize his/her data in a STRUCT...
otherwise, he/she ends up with all those zillions of variables in his/her workspace...
that's why i left this option off...

urs
0
Reply us 5/12/2010 6:45:22 PM

Thanks to everybody for their help.  I skipped over reading the -STRUCT sections of the help for save() since I wasn't trying to save a structure.  I'll try to be more careful in the future.

In response to Matt J's question about the utility:  It's possible I might use this method from several Wavefronts to save to the same MAT file.  I stripped this part out of the code that I posted to try to be brief.  Without changing the variable name to something meaningful, each time ToMAT(obj, filename) is called, a variable called "obj" would be appended to the MAT file, presumably overwriting the first one.

Thus
>>W1.ToMAT('c:\temp.mat')
>>W2.ToMAT('c:\temp.mat')

in my more-detailed function would allow both W1 and W2 to exist in the temp.mat file.  

I definitely agree that you have to be careful using the non-functional form of load().  I do this as rarely as possible and add comments indicating what variables are being created in the workspace to help make the code more readable.  I also generally only do this in script files where there's significant overhead associated with loading or processing data which I would hope to avoid in future runs.

Thanks again,
Eric
0
Reply Eric 5/12/2010 6:45:22 PM

"Eric " <not@givingemail.com> wrote in message 
news:hset02$oa1$1@fred.mathworks.com...
> Thanks to everybody for their help.  I skipped over reading the -STRUCT 
> sections of the help for save() since I wasn't trying to save a structure. 
> I'll try to be more careful in the future.
>
> In response to Matt J's question about the utility:  It's possible I might 
> use this method from several Wavefronts to save to the same MAT file.  I 
> stripped this part out of the code that I posted to try to be brief. 
> Without changing the variable name to something meaningful, each time 
> ToMAT(obj, filename) is called, a variable called "obj" would be appended 
> to the MAT file, presumably overwriting the first one.
>
> Thus
>>>W1.ToMAT('c:\temp.mat')
>>>W2.ToMAT('c:\temp.mat')
>
> in my more-detailed function would allow both W1 and W2 to exist in the 
> temp.mat file.
> I definitely agree that you have to be careful using the non-functional 
> form of load().  I do this as rarely as possible and add comments 
> indicating what variables are being created in the workspace to help make 
> the code more readable.  I also generally only do this in script files 
> where there's significant overhead associated with loading or processing 
> data which I would hope to avoid in future runs.
>
> Thanks again,
> Eric

So what would you expect this code to write to the MAT-file?


W = cell(1, 2);
W{1} = Wavefront(5); % Assume I used the correct constructor syntax here
W{2} = Wavefront(7);
W{1}.ToMAT('c:\temp.mat')
% or if you prefer
ToMAT(W{1}, 'c:\temp.mat')


W{1} is not a valid variable name and as such calling SAVE with W{1} as the 
string corresponding to the variable to save should (and does) error.  Okay, 
you could say, in that case I use something like GENVARNAME.

Now how about this?


ToMAT(Wavefront(5), 'c:\temp.mat')
% or even better
ToMAT(Wavefront, 'c:\temp.mat') % using the fact that this will call the 
0-input constructor


Would you attempt to save this to a variable named Wavefront in the 
MAT-file?  Then you'd run into problems when you LOAD it, as the variable 
would then shadow the constructor of the class.

-- 
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ 


0
Reply Steven 5/12/2010 7:20:25 PM

Steve brings up an interesting point.  My Wavefront class does have a "Name" member, so I switched the code to use that for the variable name in the MAT file.  I first use assert(isvarname(obj.Name),...) to check that the Name is a valid Matlab variable name.  If it's not, an error is reported and no saving is allowed.  

I believe this also addresses the ToMAT(Wavefront, 'c:\temp.mat') problem.  In this case the returned empty wavefront has a name that is an empty string.  This fails the isvarname() test as well.  Honestly I never use the empty constructor explicitly, though, as I'm always creating a Wavefront object from data in some form.

I'm not sure what "us" means when he says I should learn how to organize my data in a STRUCT.  My data is already organized in a single object.  There aren't thousands of variables in my workspace, just one.  I would claim that organizing my data in a user-defined class is preferable to using a STRUCT.  The object-oriented functionality of Matlab is quite powerful.  I'm guessing there's been some misunderstanding of what I'm doing.

Thanks to everybody once again.

-Eric
0
Reply Eric 5/12/2010 8:40:20 PM

When I try to use this solution I keep getting the following error message

"Error using save
The argument to -STRUCT must be the name of a scalar structure variable."

this is the code I use:
     var_name = catchmentName(1);
     S.(var_name) = rainfallRunoffCatchment; 
     save('WQmodelData.mat', '-struct',S);

The variable rainfallRunoffCatchment is a mxn double so I do not understand why this does not create a scalar structure, according to the help (http://www.mathworks.nl/help/matlab/ref/struct.html) :
     If value is not a cell array, then s is a scalar structure
This is my case but still I get this strange error saying that is not a scalar structure...
Any thoughts on what I am doing wrong?
0
Reply ingrid.keupers (2) 9/20/2012 2:21:07 PM


"Echidna " <ingrid.keupers@bwk.kuleuven.be> wrote in message 
news:k3f8oj$l02$1@newscl01ah.mathworks.com...
> When I try to use this solution I keep getting the following error message
>
> "Error using save
> The argument to -STRUCT must be the name of a scalar structure variable."
>
> this is the code I use:
>     var_name = catchmentName(1);
>     S.(var_name) = rainfallRunoffCatchment; save('WQmodelData.mat', 
> '-struct',S);
>
> The variable rainfallRunoffCatchment is a mxn double so I do not 
> understand why this does not create a scalar structure, according to the 
> help (http://www.mathworks.nl/help/matlab/ref/struct.html) :
>     If value is not a cell array, then s is a scalar structure
> This is my case but still I get this strange error saying that is not a 
> scalar structure...

No, read the error message more closely.

S is a scalar struct array, but S is not the NAME of a scalar struct array. 
The string 'S' IS the name of a scalar struct array. See the 4th example on 
the documentation page for SAVE for an example of how to save a structure to 
a MAT-file with each field being stored as a separate variable. Pay close 
attention to the last input in that SAVE call.

http://www.mathworks.com/help/matlab/ref/save.html

-- 
Steve Lord
slord@mathworks.com
To contact Technical Support use the Contact Us link on 
http://www.mathworks.com 

0
Reply slord (13276) 9/20/2012 3:14:53 PM

10 Replies
168 Views

(page loaded in 0.124 seconds)


Reply: