Matlab repr function
Asked Answered
S

3

6

In Matlab, one can evaluate an arbitrary string as code using the eval function. E.g.

s = '{1, 2, ''hello''}'  % char
c = eval(s)              % cell

Is there any way to do the inverse operation; getting the literal string representation of an arbitrary variable? That is, recover s from c? Something like

s = repr(c)

Such a repr function is built into Python, but I've not come across anything like it in Matlab, nor do I see a clear way of how to implement it myself.

The closest thing I know of is something like disp(c) which prints out a representation of c, but in a "readable" format as opposed to a literal code format.

Stevenstevena answered 28/10, 2017 at 20:39 Comment(10)
I don't think you can do it so in matlab in this manner, maybe in other ways. Because of the mantra functions are 1st class citizens you can do it in Python. This is not the case for matlab.Rushy
Why is that a limiting factor?Stevenstevena
Then you can't plug a function as an argument to another. You can do it for example with function handles using functions() function.Rushy
I do not want to use functions as arguments. I simply want repr(eval(s)) == s to be true for any eval'able string s representing a literal.Stevenstevena
Let me reword: suppose such function existed, call it matrepr. You wouldn't be able to pass an argument as matrepr(cos) or matrepr(inv). You can for example do func2str(@cos)Rushy
That's okay, as e.g. cos is not a literal. If I can get it to work for the example in the question, the solution is general enough.Stevenstevena
Can you provide an actual example you would solve with this added functionality? Also, any specific reason why you do not want to pass functions around? sprintf with a user defined function might give you what you are after or a generic function with lots of switches depending on the underlying type of your input, but I truly doubt you need it. Can you shed some light? ThanksBunk
@Bunk Say I have a nested cell array in Matlab which I want to bring into Python (by printing it to a file which is then read by Python). All that is needed syntactically is to change braces to brackets (1D Matlab cell arrays are equivalent to Python lists), but if the Matlab variable is the result of some computation, I do not have the literal code for the cell array, and so repr(c) would be very useful.Stevenstevena
Have you already looked at the python engine pia to do this? mathworks.com/help/matlab/matlab-engine-for-python.htmlObjectivity
@AndyCampbell No, but it looks promising as well, especially if you can call your own Matlab script from within Python.Stevenstevena
O
2

Depending on exactly why you want to do this, your use case may be resolved with matlab.io.saveVariablesToScript

Here is the doc for it.

Hope that helps!

Objectivity answered 2/11, 2017 at 14:46 Comment(1)
Very cool. Two complaints though: The resulting .m file builds up complex data structures rather than writing them out as one-line literals, and the results seems to have to be saved to a file, whereas I would prefer the result as a string. That aside, this is the best answer so far.Stevenstevena
F
7

The closest there is in Matlab is mat2str, which works for numeric, character or logical 2D arrays (including vectors). (It doesn't work for ND arrays, cell arrays, struct arrays, or tables).

Examples:

>> a = [1 2; 3 4]; ar = mat2str(a), isequal(eval(ar), a)
ar =
    '[1 2;3 4]'
ans =
  logical
   1

>> a = ['abc'; 'def']; ar = mat2str(a), isequal(eval(ar), a)
ar =
    '['abc';'def']'
ans =
  logical
   1

In this related question and answers you can see:

  • A function I wrote for obtaining a string representation of 2D cell arrays with arbitrarily nested cell, numeric, char or logical arrays.
  • How to do what you want in Octave for arbitrary data types.
Ferneferneau answered 29/10, 2017 at 3:5 Comment(0)
B
3

OK, I see your pain.

My advice would still be to provide a function of the sort of toString leveraging on fprintf, sprint, and friends, but I understand that it may be tedious if you do not know the type of the data and also requires several subcases.

For a quick fix you can use evalc with the disp function you mentioned.

Something like this should work:

function out = repr(x)
    out = evalc('disp(x)'); 
end

Or succinctly

repr = @(x) evalc('disp(x)');
Bunk answered 28/10, 2017 at 21:48 Comment(2)
Indeed evalc is one piece of the solution. And yes, it appears that one could hack something together along the lines of toString, although this would require quite some work.Stevenstevena
@jmd_dk, yup: I would advice for the 'toString' way. If you have time (and are willing to go that path) probably I would identify the underlying class of your data, then size and then create a string according to the size (e.g.). You could even use iscell, ischar etc. Another way would be to go the OOP way and wrapping your data around a class which defines your 'toString' method; e.g. you define a 'PrintableData' class and then through inheritance you implement 'PrintableCell', 'PrintableArray' etc. Just some thoughts (which possibly you have already considered).Bunk
O
2

Depending on exactly why you want to do this, your use case may be resolved with matlab.io.saveVariablesToScript

Here is the doc for it.

Hope that helps!

Objectivity answered 2/11, 2017 at 14:46 Comment(1)
Very cool. Two complaints though: The resulting .m file builds up complex data structures rather than writing them out as one-line literals, and the results seems to have to be saved to a file, whereas I would prefer the result as a string. That aside, this is the best answer so far.Stevenstevena

© 2022 - 2024 — McMap. All rights reserved.