1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

matlabで無名関数に代入の必要な複数行を実行させる方法

Posted at

参考:http://woodrush.hatenablog.com/entry/2014/08/25/034413
逆参考: https://jp.mathworks.com/matlabcentral/answers/499533-matlab-r2019a-substr?s_tid=mwa_osa_a
(「逆参考」のページに、ほとんど同じ内容を投稿しています。)

ここでは、substr関数を実装することを考えていきます。

substr = (@(s_or_c, i, n)feval(@(c, i, n) c(i:(i+n-1)),feval(@(s_or_c) char(s_or_c),s_or_c),i,n));
これをコマンドラインにコピペすれば、substrを書き換えたりclear substrしたりしない限り、substrが利用可能になります。
substr("hello world", 2, 6)
と打てば「'ello w'」が返ります。

解説

入力cが文字ベクトル(1重引用符で括られたもの)のとき、
「無名関数」というのを利用して定義すればいいです。
substr = @(c,i,n) c(i:(i+n-1));
とすることで、substrが実現します。

無名関数
@(x, ..) 関数や演算子など(x, ..);
は、

anonymous.m
function rtn = anonymous(x, ..)
    rtn = 関数や演算子など(x, ..)
end

のようなanonymous.mが「あるとみなして」anonymous(x, ...)を返してくれという命令です。

つまり、先ほどのコードでは、

function rtn = anonymous(c, i, n)
    rtn = c(i:(i+n-1));
end

がある
とみなして、
substr = anonymous(c,i,n);
をやったのと同じです。

例えばsubstr('hello world', 2, 6)'ello w'を返却します。

しかし、ここにはまだ問題が残っています。
substr("hello world", 2, 6)
機能しないのです。
2重引用符で括られたものは「文字列」であり、文字ベクトルとは別物だからです。

文字列は、char(文字列)のようにすることで文字ベクトルに変換できます。
(蛇足: ちなみにchar(文字ベクトル)は、そっくりそのまま文字ベクトルを返します)
したがって、
substr(char("hello world"), 2, 6)
ならOKです。

ただ、これではダサいですよね。
substr("hello world", 2, 6)
でもちゃんと動くようにしましょう。

substr = @(str,i,n) char(str)(i:(i+n-1));
ならいいでしょうか?

いいえ。
matlabでは、括弧が隣り合うと、エラーになります
したがって、
substr = @(str,i,n) (c = char(str); c(i:(i+n-1)));
でいけそうです。
しかしこれもダメです。無名関数は文を1つしか持たせられないからです。

何とかして無名関数で書きたい場合、
feval関数」というのを何度も用いることで書けます。

fevalは、次のような関数です。
feval(@f, x)  f(x) を返却する」
feval(@g, x, y)g(x, y)を返却する」
・・・

例1:
feval(@cos, 3.14)は、cos(3.14)つまり-1を返却します。

例2:
feval(@mod, 10,3)は、mod(10,3)つまり1 を返却します。

また、
feval関数の第1引数には無名関数も持ってこれます。

例3:
feval(@(c,i,n) c(i:(i+n-1)), 'hello_world', 2, 6)
は、substr('hello world', 2, 6)つまり'ello w'を返します。

ややこしいですが、

'無名関数'内でfevalを利用し、
           そのfeval内で'無名関数'を利用し、
                    その'無名関数'内でfevalを利用し
                                 そのfeval内で'無名関数'を利用し、
                                          その'無名関数'内でfevalを利用し
                                                       そのfeval内で...

のようなことを繰り返すと、複数の文を無名関数で実行できます。
(理由は、「複数の文」全体を、一つの文としてみることが可能になるからです)

いきなり例を示すと混乱するので(もし皆さんが混乱しないとしても、説明している僕のほうが混乱します笑)、

どんな無名関数をつかうか、先に決めましょう。

関数その1: (s_or_c)c
引数:
s_or_c: 文字列かもしれないし文字ベクトルかもしれないもの。
戻り値:
c: 確実に文字ベクトル
内容(分かりやすい表現):
c = char(s_or_c);
内容(無名関数の書き方で)
@(s_or_c) char(s_or_c);

関数その2: (c, i, n)answer
引数:
c
i
n
戻り値:
answer: 得たい部分文字列
内容(分かりやすい表現):
answer = c(i:(i+n-1));
内容(無名関数の書き方で)
@(c, i, n) c(i:(i+n-1));

では、これを書いてみましょう。


substr = ...
(...
    @(s_or_c, i, n) ...
        feval ...                                                            %◆ 
...     %関数その2を無名で定義し、利用します。                               %◆
        (...                                                                 %◆
            @(c, i, n) c(i:(i+n-1)), ...                                     %◆
...         %関数その2を定義                                                 %◆
...                                                                          %◆
            feval ...                             %★                        %◆
...         %関数その1を無名で定義し、利用します。%★                        %◆
            (...                                  %★                        %◆
                @(s_or_c) char(s_or_c), ...       %★                        %◆
...             %関数その1を定義                  %★                        %◆
...                                               %★                        %◆
                s_or_c ...                        %★                        %◆
...             %関数その1を利用                  %★                        %◆
            ), ...                                %★                        %◆
...         %★全体がcとして評価される(=あたかもcであるかのように振る舞う)  %◆          
            i, n ... %(★=c)と繋げて読むと、c,i,nとなっている。              %◆
...         %関数その2を利用                                                 %◆
        )...                                                                 %◆
...     %◆全体がanswerとして評価される
);

こんな感じです。

それでは、失礼いたします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?