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.

jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • 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. – percusse Oct 28 '17 at 20:56
  • Why is that a limiting factor? – jmd_dk Oct 28 '17 at 20:57
  • Then you can't plug a function as an argument to another. You can do it for example with function handles using `functions()` function. – percusse Oct 28 '17 at 20:57
  • 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. – jmd_dk Oct 28 '17 at 21:00
  • 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)` – percusse Oct 28 '17 at 21:04
  • 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. – jmd_dk Oct 28 '17 at 21:09
  • 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? Thanks – pacta_sunt_servanda Oct 28 '17 at 21:14
  • @pacta_sunt_servanda 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. – jmd_dk Oct 28 '17 at 21:34
  • Have you already looked at the python engine pia to do this? http://www.mathworks.com/help/matlab/matlab-engine-for-python.html – Andy Campbell Nov 02 '17 at 14:57
  • @AndyCampbell No, but it looks promising as well, especially if you can call your own Matlab script from within Python. – jmd_dk Nov 02 '17 at 14:59

3 Answers3

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.
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
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)');
jmd_dk
  • 12,125
  • 9
  • 63
  • 94
  • Indeed `evalc` is one piece of the solution. And yes, it appears that one could hack something together along the lines of [toString](https://se.mathworks.com/matlabcentral/fileexchange/38566-string-representation-of-any-data-type), although this would require quite some work. – jmd_dk Oct 28 '17 at 21:56
  • @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). – pacta_sunt_servanda Oct 28 '17 at 22:00
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!

Andy Campbell
  • 2,177
  • 13
  • 15
  • **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. – jmd_dk Nov 02 '17 at 15:01