2015-07-14 1 views
1

Любые переменные и их значения, первоначально сохраненные в дескрипторе функции, когда они были созданы, теряются, если вы преобразуете дескриптор функции в строку и обратно с помощью функций func2str и str2func.Matlab: преобразовать дескриптор функции в параметры сохранения строки

Есть ли способ преодолеть это?

Как

y = 1; 
fun = @(x) x + y 
fun_str = func2str(fun); 

clear y 

fun = eval(fun_str); 
result = fun(12); % This doesn't work 

Бетон У меня есть метод измерения, создавая какие-то данные, которые затем получает оборудованные (с помощью fminsearch) против некоторых пользовательских функций для процедуры выравнивания. Теперь я хотел бы сохранить все данные для будущего анализа.

Поскольку данные обычно выживают дольше, чем код, я хотел бы сделать его независимым от любого исходного файла. Вот почему я также конвертирую дескриптор функции в строку. В строке разрешено вызывать только matlab builtin.

Теперь, что я могу сделать, конечно, также хранить y в этом примере. Но мне было интересно, есть ли более элегантное решение для этого, где мне не нужно это делать.

+2

Это не совсем так. Он хранится с анонимной функцией, а затем теряется при преобразовании в строку. Вы можете очистить y и по-прежнему вызывать анонимную функцию. – Kim

+0

@ Ким, вы правы. Удаление ... – excaza

ответ

1

Проблема связана с тем, что Matlab сохраняет значение y в рабочем пространстве, локальном для анонимной функции, сохраняя при этом символ функции y. Затем, как вы указали, функция func2str преобразует определение без замены символа на его значение. Поскольку ваш пример указывает, что вы хотите, чтобы функциональный дескриптор работал даже после очистки переменной y (оба значения и символа) из текущего рабочего пространства, я бы предложил два пути вперед.

Первый заключается в создании функции ручки с str2func используя значение y вместо того, чтобы позволить анонимные функции держать его:

fun = str2func(['@(x) x + ',num2str(y)]); 

Другой написать вариант func2str, что делает замену значения после преобразование функции в строку. Функция functions может использоваться для получения рабочей области анонимной функции, а некоторые регулярные выражения могут использоваться для замены символов литералами. Вот минимальный рабочий пример:

function str = func2strrep(fun) 

    % Grab workspace information 
    info  = functions(fun); 
    workspace = info.workspace{1}; 
    symbols = fieldnames(workspace); 

    % Initialize string 
    str = func2str(fun); 

    % Replace workspace variables with numeric literals 
    if not(isempty(symbols)) 

     seps = '[\s\+\-\*\/\\\^\:\=\>\<]'; 
     expr = @(s) ['(',seps,'{1})',s,'(',seps,'{1})']; 

     for k = 1:numel(symbols) 

      symbol = symbols{k}; 
      value = num2str(workspace.(symbol)); 

      % Check end of string 
      str = regexprep(str,['(',seps,'{1})',symbol,'$'],['$1',value]); 

      % Check bulk 
      stro = regexprep(str,expr(symbol),['$1',value,'$2']); 
      % 
      % Put in loop for repeated replacement since 
      % 'all' is not working as I thought it would. 
      while not(strcmp(stro,str)) 
       str = stro; 
       stro = regexprep(str,expr(symbol),['$1',value,'$2']); 
      end 

     end 
    end 
end 

Я не настолько талантлив с регулярными выражениями, поэтому метод замены может потребоваться некоторые настройки (особенно с regexprep не заменит то, что я думал, будет все матчи за повторен символы). Однако это первый идти производит

>> y = 1; 
>> z = 2; 
>> yy = 3; 
>> f = @(x) x + y + y + z + yy; 
>> func2strrep(f) 
ans = 
@(x)x+1+1+2+3 

Оба подхода опираются на num2str и, следовательно, хороши только для скалярных значений. Для векторных значений для работы метода необходим вариант num2str, который создает допустимый литерал массива в строковой форме.

Второй подход также работает только для простого хранения переменных, как в примере. Вложенные ручки и затворы и подобные им потребуют более сложный алгоритм определения значения символа и, возможно, замены.

+0

Благодарим вас за ответ. Я действительно старался избегать 'strrep' и' regex', так как я хотел бы дать пользователю возможность дать определенную пользователем функцию (конечно, не связываясь с файлом (встроенные матрицы Matlab в порядке)). Поэтому я не могу быть уверен в внутренней структуре, и я боюсь, что я заменил бы слишком много, но, возможно, с очень умным регулярным выражением, это можно было бы сделать. Я подожду еще немного, если кто-то другой придумает другое решение. Еще раз спасибо за то, что нашли время. –

+0

Не могли бы вы объяснить, что вариант использования немного больше, и, возможно, предоставить дополнительный пример в вашем вопросе? Я думаю, что ответ на ваш вопрос сильно зависит от того, что именно вы пытаетесь сделать. – TroyHaskin

+0

Добавлена ​​дополнительная информация –