MATLABでファイルごとに複数の関数を定義し、そのファイルの外部からそれらにアクセスすることは可能ですか?


216

私がEEで学士号を取得するために勉強していたとき、MATLABでは、たとえそれが1行であったとしても、MATLABでは各関数を独自のファイルで定義する必要がありました。

現在、大学院の学位を取得しています。MATLABでプロジェクトを作成する必要があります。これは、MATLABの新しいバージョンの要件ですか?

ファイルに複数の関数を含めることができる場合、これに制限はありますか?たとえば、ファイル内のすべての関数にファイルの外部からアクセスできますか、それともファイルと同じ名前の関数のみにアクセスできますか?

注:私は、MATLABリリースR2007bを使用しています。

回答:


270

mファイルの最初の関数(メイン関数)は、mファイルが呼び出されると呼び出されます。main関数の名前がmファイルと同じである必要はありませんが、わかりやすくするためににする必要があります。関数とファイル名が異なる場合、ファイル名を使用してメイン関数を呼び出す必要があります。

ローカル関数(または古い用語では「サブ関数」)と呼ばれる、mファイル内の後続のすべての関数は、そのmファイル内のメイン関数と他のローカル関数によってのみ呼び出すことができます。他のmファイルの関数はそれらを呼び出すことができません。R2016b以降、ローカル関数をスクリプトに追加することもできますが、スコープの動作は同じです(つまり、スクリプト内からのみ呼び出すことができます)。

さらに、他の関数内で関数を宣言することもできます。これらはネストされた関数と呼ばネストされた関数内からのみ呼び出すことができます。また、入れ子になっている関数内の変数にアクセスすることもできます。これにより、操作が少し難しくなりますが、非常に役立ちます。

思考のためのより多くの食べ物...

SCFrenchおよびJonasからの回答で述べられているように、関数ハンドルを出力引数として渡す(R2013b以降、関数によって促進される)など、上記の通常の関数スコープ動作の周りにはいくつかの方法があります。ただし、関数やファイルを整理するためのはるかに優れたオプションが存在する可能性があるため、このようなトリックに頼る習慣を身に付けることはお勧めしません。localfunctions

たとえば、あなたが主な機能としましょうAM-ファイル内のA.mローカル関数と一緒に、DE、とF。今度は、あなたが他の二つの関連する機能を持っているとしようBCM-ファイルにB.mし、C.mあなたも呼び出すことができるようにしたいことを、それぞれDE、とF。いくつかのオプションがあります:

  • 入れてDE、およびFそれらを呼び出すために、他の機能をできるように、自分の別のM-ファイル内の各。欠点は、これらの機能の範囲が大きいだけに限定されないことであるABC、しかし逆に、これは非常に簡単であるということです。

  • 作成defineMyFunctionsして(ジョナス例のように)M-ファイルをDEおよびFローカル機能と、単にそれらに関数ハンドルを返す主な機能として。これは、あなたが保つことを可能にするDEF同じファイルで、それが呼び出すことができる任意の関数から、これらの機能の範囲について、何もしないdefineMyFunctions、それらを呼び出すことができます。また、関数ハンドルを引数として渡し、必要な場所に確実に配置できるようにする必要があります。

  • コピーDEおよびFB.mC.m地元の関数として。これはちょうどにその使用の範囲を制限しAB、とCしていますが、別の場所で同じコードの3つのコピーを持っているので、あなたのコード悪夢の更新やメンテナンスを行います。

  • プライベート関数を使用してください!あなたが持っている場合はABC同じディレクトリに、あなたが呼ばれるサブディレクトリを作成することができますprivateし、場所をDEと、Fそこでは、各個別のM-ファイルとして。これは、彼らが唯一のすぐ上のディレクトリ内の関数によって呼び出すことができるので(すなわち、その範囲を制限しAB、およびC)と同じ場所(まだ別のMファイル)でそれらを一緒に保持します。

    myDirectory/
        A.m
        B.m
        C.m
        private/
            D.m
            E.m
            F.m

これらすべてはあなたの質問の範囲をいくらか超えており、おそらく必要以上に詳細ですが、私はあなたのすべてのmファイルを整理することのより一般的な懸念に触れた方が良いかもしれないと思いました。;)


3
お気に入りの回答オプションは^、@ idigas
embert

1
@embert私は彼が質問のお気に入りのラインに沿って意味したと思います、それはお気に入りとは独立して賛成投票することができます。
OJFord 2015年

78

一般的に、あなたの質問に対する答えは「いいえ」です。ファイルごとに複数の外部から見える関数を定義することはできません。ただし、関数ハンドルをローカル関数に返すことができます。これを行う便利な方法は、構造体のフィールドにすることです。次に例を示します。

function funs = makefuns
  funs.fun1=@fun1;
  funs.fun2=@fun2;
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

そして、これはどのように使用できるかです:

>> myfuns = makefuns;
>> myfuns.fun1(5)    
ans =
     5
>> myfuns.fun2()     
ans =
     1

36

複数の個別にアクセス可能な関数を1つのファイルに含める唯一の方法は、オブジェクト指向プログラミングを使用して静的メソッドを定義することです。あなたはとしての機能にアクセスしたいmyClass.static1()myClass.static2()など

OOP機能はR2008a以降でのみ正式にサポートされているため、ドキュメント化されていない古いOOP構文を使用したくない場合は、@ gnoviceで説明されているように、答えはノーです

編集

外部からアクセスできるファイル内の複数の関数を定義するもう1つの方法は、複数の関数ハンドルを返す関数を作成することです。つまり、定義関数をとして呼び出し[fun1,fun2,fun3]=defineMyFunctions、その後out1=fun1(inputs)などを使用できます。


私はこの目的でoopを使用しません。特に静的メソッドの場合、かなりのオーバーヘッドが追加されます。(stackoverflow.com/questions/1693429/...
ダニエル

1
@Daniel:オーバーヘッドが顕著になるのは、大量の関数呼び出しを実行し、メソッドでの計算がほぼ瞬時に行われる場合のみです。多くの場合、両方の条件は設計が悪いことを示しています-ベクトル化がなく、意味のない関数です。したがって、私はあまり心配していません。
ジョナス

23

私はSCFrenchの答えが本当に好きです。assignin関数を使用して関数をワークスペースに直接インポートするように簡単に変更できることを指摘しておきます。(これをこのように行うと、Pythonの「xからyをインポートする」方法の多くを思い出します)

function message = makefuns
  assignin('base','fun1',@fun1);
  assignin('base','fun2',@fun2);
  message='Done importing functions to workspace';
end

function y=fun1(x)
  y=x;
end

function z=fun2
  z=1;
end

そして、このように使用されます:

>> makefuns
ans =
Done importing functions to workspace

>> fun1(123)
ans =
   123

>> fun2()
ans =
     1

assignin('caller',...)より正しいでしょう。これらの関数を別の関数内から使用したい場合があります。
クリスLuengo

10

SCFrenchの回答と同じように、より多くのC#スタイルのスピンを使用します。

複数の静的メソッドを含むクラスを作成します(多くの場合、そうします)。例えば:

classdef Statistics

    methods(Static)
        function val = MyMean(data)
            val = mean(data);
        end

        function val = MyStd(data)
            val = std(data);
        end
    end

end

メソッドは静的なので、クラスをインスタンス化する必要はありません。次のように関数を呼び出します。

data = 1:10;

mean = Statistics.MyMean(data);
std = Statistics.MyStd(data);     

4

Octaveで1つの.mファイルに複数の関数を定義してから、そのファイルの関数を利用する必要がある.mファイル内からコマンドを使用します。

source("mycode.m");

これがMatlabで利用できるかどうかはわかりません。

octave:8> help source
'source' is a built-in function

 -- Built-in Function:  source (FILE)
     Parse and execute the contents of FILE.  This is equivalent to
     executing commands from a script file, but without requiring the
     file to be named `FILE.m'.

3

次のようなメイン関数と一緒に、1つのメインファイルに関数をグループ化することもできます。

function [varargout] = main( subfun, varargin )
[varargout{1:nargout}] = feval( subfun, varargin{:} ); 

% paste your subfunctions below ....
function str=subfun1
str='hello'

次に、subfun1を呼び出すと、次のようになります。str = main( 'subfun1')


0

R2017b以降、これは公式には不可能です。関連文書のように述べています:

プログラムファイルには、複数の関数を含めることができます。ファイルに関数定義のみが含まれている場合、最初の関数はメイン関数であり、MATLABがファイル名に関連付ける関数です。メイン関数またはスクリプトコードに続く関数は、ローカル関数と呼ばれます。ローカル関数はファイル内でのみ使用できます。

ただし、他の回答で提案された回避策は、同様のことを達成できます。


これは、Gnoviceが彼の回答の冒頭で述べたことと正確には同じではありませんか?
Adiel 2017年

@Adielおそらく、その回答から数年が経過したため、誰かが変わったのではないかと思うかもしれません。
Dev-iL 2017年

何か変わったのにまだ分からない…?:)
Adiel 2017年

いいえ。この特定のトピックに対処するために追加されたいくつかのドキュメント以外に。
Dev-iL 2017年

私がこの回答を書いた理由は、いくつかのリリース前にスクリプトの最後に追加できる関数が導入されたためです。そのため、この点に関して何か変更されたのではないかと思われるかもしれません(回答:いいえ)。
Dev-iL 2017年

-1

私は、SCFRenchとオクターブのRu Hashaを試してみました。

そして最後にそれは動作します: しかし、私はいくつかの変更を行いました

function message = makefuns
    assignin('base','fun1', @fun1);   % Ru Hasha
    assignin('base', 'fun2', @fun2);  % Ru Hasha
    message.fun1=@fun1;               % SCFrench
    message.fun2=@fun2;               % SCFrench
end

function y=fun1(x)
    y=x;
end

function z=fun2
    z=1;
end

他の「m」ファイルで呼び出すことができます:

printf("%d\n", makefuns.fun1(123));
printf("%d\n", makefuns.fun2());

更新:

ので、私は答えを追加しましたどちらも 72も20が働いていた私のためにオクターブで。私が書いたものは完全に機能します(そして、先週の金曜日に後でポストを書いたときにテストしました)。


2
これが、コピー元の2つの既存の回答とどのように異なるかを説明できる場合は、反対票を削除します。以前にコメントしないでごめんなさい。両方の方法を1つの関数に組み合わせたため、何か冗長なことをしているのを除いて、これがどのように違うのかはわかりません。また、あなたが参照している回答への適切なリンクを挿入してください。「+ 72」と「+20」はかなり不可解です。投票数を参照していることを認識するのにしばらく時間がかかりました。わかりにくい。
Cris Luengo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.