2

継承した大規模なコードベースの一部として、次の関数があります。

function = save_function(fpath, a,b,c)
    save(fpath, 'a', 'b', 'c')
end

この関数は、1 つのスクリプトの最後で、別のスクリプトが実行される前に呼び出されます。このようにして、変数名が適切に保存されます (悪い設計です。私は知っています - 私はこのコードを書きませんでした)。

現在、コードベースに変更を加えており、より多くの変数を に格納する必要があることに気付きましたfpath。私は2つの選択肢に直面しています:

  1. save_functionより多くの入力を受け入れるように編集します。これにより、この関数も使用するコードベース内の他のコードが壊れます。
  2. save_function2(a, b, c, d, e, ...)変更するコードで呼び出すaを記述します。これも悪いデザインのようです。

私が理想的にやりたいことはsave_function、一度に任意の数の引数を取り、渡された変数名でそれらをすべて保存できるようにすることです。

グーグルで検索したところ、文字列を matlab コードとして評価するevalとが見つかりました。eval_inただし、これを使用するには次の 2 つの問題があります。

  1. 使用evalは恐ろしく遅く、非常に危険です
  2. to_string変数の型を事前に知っているとは限らないため、洗練された汎用関数を作成できません

可変数の変数に対抗するために、次のようにvararginandを使用することにしました。inputname

function = save_function(fpath, varargin)
    names = {}
    for i=1:size(varargin,1)
        names{i} = inputname(i+1);  % have to offset by 1 to account for fpath
    end
    save(fpath, names{:});
end

残念ながら、入力変数は に保持されてvararginいるため、スタック上に変数名として存在しないため、このsave行は失敗します。

これらの変数を変数名でスタック上に動的に作成するにはどうすればよいですか?

4

2 に答える 2

0

トリックはassignin、ワークスペース、変数名、およびいくつかのデータを取る を使用することです。次に、指定されたワークスペースで、値がデータである指定された名前の変数を作成します。

assignin(workspace, varname, value)

ワークスペース ID は、 または のいずれ'caller''base'です。前者は、呼び出された関数を呼び出した関数のワークスペースに変数を作成しますassignin。後者は...わかりません-変数を私が見ることができる場所に置いていないようです。

秘訣は、呼び出し元のワークスペースに変数を割り当てる小さな関数を作成し、この関数を 内から呼び出すことですassignin

function = save_function(fpath, varargin)
    names = {}
    for i=1:size(varargin,1)
        names{i} = inputname(i+1);  % have to offset by 1 to account for fpath
    end
    create_variables(names, varargin);
    save(fpath, names{:});
end

function = create_variables(names, vals)
    for i=1:size(names, 1)
        assignin('caller', names{i}, vals{i});
    end
end
于 2014-07-01T03:28:54.837 に答える