関数内のシングルクウ​ォート連続3個とカン​マの意味について

cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']
上記のプログラム解釈についてご教示頂きたいです。
当該プログラムはMファイルとして実行しているプログラムの一部になります。
load関数についてのヘルプを見ると、第1引数から第3引数まではそれぞれ仕様にて定義されていましたが、第4引数以降は仕様としては存在しないと理解しました。
ですが当初自身の上記プログラムの理解としては、第1引数と第3引数、第4引数と第6引数にシングルクウォートを引数として指定しているでしたが、実際にMATLAB上でデバックすると変数cmdには「'load('BeforeName','strjoin(rot90(CheckList,3),','),');'」が格納されていました。
ですので上記プログラムの挙動としては、第1引数はBeforeNameが指定され第2引数はstrjoin(rot90(CheckList,3),',')が指定されていると考えました。
ただそうだとすると、ヘルプページに記載のload関数の仕様と実際の挙動の辻褄が合いません。
もしかすると、シングルクウォートが連続3個記載されている箇所とカンマの解釈次第で当該不整合が解消されるのではと想像しております。
ですので、関数内でシングルクウォートとカンマを使用する際の挙動についてご教示頂きたいです。
またそれが記載されているヘルプページがありましたら、そのページも併せてご教示頂けますと幸いです。
因みに現在の自身の理解では、関数内のカンマは第n引数と第n+1引数(nは1以上の自然数)を区切る以外の機能は持ち合わせていないと思っているのですが、その点につきましても認識に齟齬がありましたら併せてご教示頂けますと幸いです。
もし自身の予想が全くの検討違いだった際は、上記プログラムの正しい解釈方法をヘルプページの解説と併せてご教示頂けますと幸いです。
お手数をお掛けしてしまい大変恐縮ですが、何卒宜しくお願い致します。

Answers (1)

Atsushi Ueno
Atsushi Ueno on 13 Mar 2023
Edited: Atsushi Ueno on 13 Mar 2023

0 votes

> 第1引数から第3引数までは仕様にて定義されていましたが、第4引数以降は仕様としては存在しないと理解しました
一見、load(filename,'-mat',variables)の様に第3引数まではそれぞれ仕様にて定義されている様に見えますが、variablesは可変個数の引数として定義されているのでこの限りではありません。例えば load 関数を下記の様に使っても問題無く動作します。
load('accidents.mat','datasources','hwycols','hwydata','hwyheaders','hwyidx','hwyrows','statelabel','ushwydata','uslabel')
> 第1引数はBeforeNameが指定され第2引数はstrjoin(rot90(CheckList,3),',')が指定されていると考えました。ただそうだとすると、ヘルプページに記載のload関数の仕様と実際の挙動の辻褄が合いません。
第2引数は可変個数なので、第3引数、第4引数…と続く事が想定されます。具体的には下記の様に文字ベクトルのセル配列が入力される事が想定され、strjoin関数により「 ',' 」で区切られた可変個数の変数になります。一重引用符のエスケープシーケンスが解釈され、変数cmdに文字ベクトルとして格納されます。
BeforeName = 'sample.mat';
CheckList = {'check1','check2','check3'}; % テスト用
cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']
cmd = 'load('sample.mat','check1','check2','check3');'
> もしかすると、シングルクウォートが連続3個記載されている箇所とカンマの解釈次第で当該不整合が解消されるのではと想像しております。
そんな事はないのですが、分かり難いので二重引用符(ダブルクウォート)に変える事が推奨されます。但しこの場合、文字ベクトルはstring型に変わってしまいますので、文字ベクトルのセル配列もstring配列に変更する事になります。詳細な説明は下記リンク先に譲ります。文字と文字列 - MATLAB & Simulink - MathWorks 日本
cmd = ['load("',BeforeName,'","',strjoin(rot90(CheckList,3),'","'),'");']
cmd = 'load("sample.mat","check1","check2","check3");'
>関数内でシングルクウォートとカンマを使用する際の挙動についてご教示頂きたいです。またそれが記載されているヘルプページがありましたら、そのページも併せてご教示頂けますと幸いです。
この点は現在の使い方が正しいので問題無いかと思います。エスケープシーケンスがややこしいだけです。
>関数内のカンマは第n引数と第n+1引数(nは1以上の自然数)を区切る以外の機能は持ち合わせていない
この点も仰る通りで、間違いないと思います。

13 Comments

しん
しん on 13 Mar 2023
ご回答頂き有難う御座います。
当該プログラムの挙動に関しては、エスケープシーケンスにより「'''」→「'」となると理解しました。
ただヘルプページにて下記記載を発見しました。
上記解説によると「''」==「'」と記載されていたので、この解釈によると「'''」→「''」になるのではと考えました。
実際のプログラムの挙動からすると「'''」→「'」になっているのですが、公式のヘルプページの解説と齟齬が生じている様に思いました。
もし私が見ているページが間違っていましたら、正しい説明が記載されている公式ヘルプページをご教示頂きたいです。
重ね重ねのお願いで大変恐縮ですが、何卒宜しくお願い致します。
仰る通りで、「'''」→「'」ではなく「''」==「'」となります。
一重引用符が3つ並ぶ場合は、文字ベクトルを括る一重引用符と重なる場合です。
test = 'load('''; % 一重引用符が3つ並ぶ場合:最初の2つは文字ベクトルの一文字としての一重引用符、次の1つは文字ベクトルを括る一重引用符
disp(test)
load('
しん
しん on 13 Mar 2023
ご回答頂き有難う御座います。
一重引用符の箇所は理解出来ました。有難う御座います。
続いてカンマに関して疑問点が御座います。
cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']
上記load関数の引数に関してですが、厳密に考えますとBeforeNameの直前にはカンマが記述されてますので、第1引数は実質「''」、第2引数は「BeforeName」、第3引数は実質「''」、第4引数は実質「''」、第5引数は実質「strjoin(rot90(CheckList,3),'','')」、第6引数は実質「''」であると考えています。(※実質とはエスケープシーケンスを考慮するとという意味)
そしてそれぞれの引数が文字ベクトルとして扱われcmd変数に代入されると更に一重引用符が1つ外れて、第1引数は「'」、第2引数は「BeforeName」、第3引数は「'」、第4引数は「'」、第5引数は「strjoin(rot90(CheckList,3),',')」、第6引数は「'」となると考えています。
下記質問は上記を前提にさせて頂きますが、ここまでは認識間違っていないでしょうか?
実際デバックすると繰り返しになり恐縮ですが、第1引数がBeforeName、第2引数がstrjoin(rot90(CheckList,3),''',''')となっており、この挙動自体が良く理解出来ません。
自分なりに考えましたが、当該挙動は下記の通り2つ考えられると思っています。
①一重引用符のみが関数の引数として指定された場合は引数として扱われない。
②一重引用符のみが関数の引数として指定された場合はカンマが機能しない。
上記2つ以外の仕様もあるかも分かりませんが、それ以外の仕様としては「一重引用符」の箇所が「二重引用符」でも同様等と考えています。
ただ一番最初の質問にて下記の通り回答を頂いてますので、もしかすると②は仕様としてはないのではとも思っています。
>関数内のカンマは第n引数と第n+1引数(nは1以上の自然数)を区切る以外の機能は持ち合わせていない
この点も仰る通りで、間違いないと思います。
再三のご質問で大変恐縮ですが、ご回答頂けますと幸いです。
何卒宜しくお願い致します。
Atsushi Ueno
Atsushi Ueno on 13 Mar 2023
Edited: Atsushi Ueno on 13 Mar 2023
>下記質問は上記を前提にさせて頂きますが、ここまでは認識間違っていないでしょうか?
⇒間違ってはいないと思います。言葉では@しんさんの解釈を正確に伺い知る事は難しいです。
一点大事な点として伝えたいのは「cmdに命令(文字ベクトル)として納められた load 関数が eval 関数で実行されるまでは、その中身は評価されない」という事です。従って、load 関数における引数の解釈は、エスケープシーケンスを取り除いてから検討しても良いのではないかと思います。
実際にdisp関数を使って動かしてみます。回答の内容をバラしただけで同じ事をしています。デバッガを使わずにデバッグしているといっても過言ではありません。(この場所ではデバッガが使えない)
これならどうでしょうか?
first = 'load('''; disp(first) % disp()を使えば、実際の文字ベクトルだけが表示される
load('
second = 'sample.mat'; disp(second)
sample.mat
third = ''','''; disp(third)
','
CheckList = {'check1','check2','check3'}; % テスト用
fourth = strjoin(rot90(CheckList,3),''','''); disp(fourth)
check1','check2','check3
fifth = ''');'; disp(fifth)
');
cmd = [first, second, third, fourth, fifth]; disp(cmd)
load('sample.mat','check1','check2','check3');
Atsushi Ueno
Atsushi Ueno on 13 Mar 2023
> 実際デバックすると繰り返しになり恐縮ですが、第1引数がBeforeName、第2引数がstrjoin(rot90(CheckList,3),''',''')となっており、この挙動自体が良く理解出来ません
私の書いた例だと最終的に第1引数が「sample.mat」、第2引数が「check1','check2','check3」となりました。(誤解を避ける為「」を使いました)。全て解釈された後の文字ベクトルは「load('sample.mat','check1','check2','check3');」で、これが実行したい命令文(の例)です。
>自分なりに考えましたが、当該挙動は下記の通り2つ考えられると思っています。
①一重引用符のみが関数の引数として指定された場合は引数として扱われない
⇒その様な事があるとすれば「’’」即ち空文字が渡されるケースが考えられます。一重引用符が単独で引数として渡される事はあり得ない(何らかのエラーが出る)と思います。
②一重引用符のみが関数の引数として指定された場合はカンマが機能しない。
⇒その様な事はありません。
>上記2つ以外の仕様もあるかも分かりませんが、それ以外の仕様としては「一重引用符」の箇所が「二重引用符」でも同様等と考えています。
⇒仰る通りです。
>ただ一番最初の質問にて下記の通り回答を頂いてますので、もしかすると②は仕様としてはないのではとも思っています。(関数内のカンマは第n引数と第n+1引数(nは1以上の自然数)を区切る以外の機能は持ち合わせていない⇒この点も仰る通りで、間違いないと思います)
⇒そうですね。関数の括弧内に書くカンマは引数を区切る機能なので、②の様な事はありません。
しん
しん on 13 Mar 2023
Edited: しん on 13 Mar 2023
ご回答有難う御座います。
ただプログラムの挙動は自体は理解しておりまして、上記ご回答も踏まえ簡潔に質問させて頂きます。
ヘルプページのload関数の説明にて「load(filename,variables)」と記載されていますが、
cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']というプログラムは上記のパターンとMATLABは理解するで間違っていませんでしょうか?(他にも幾つか引数のパターンがある為確認させてください。)
恐らく「load(filename,variables)」と認識すると思ってますので、それを前提として再度確認させて下さい。
first = 'load('''; disp(first) ←第1引数はfilenameの為NG
→第1引数はload関数の仕様からfilenameしか指定できないと理解していますが合ってますでしょうか?
また一番最初の回答を下記に引用させていただきます。
>第2引数は可変個数なので、第3引数、第4引数…と続く事が想定されます。
上記ご回答から第3引数以降の引数はご回答頂いた通り、仕様上問題無く動作すると理解しております。
が第2引数に関してはvariablesの所filenameを指定していまっているので動作しない。
second = 'sample.mat'; disp(second) ←第2引数はvariablesの為NG
third = ''','''; disp(third) ←第3引数以降はvariablesの為OK
fourth = strjoin(rot90(CheckList,3),''','''); disp(fourth) ←第3引数以降はvariablesの為OK
fifth = ''');'; disp(fifth) ←第3引数以降はvariablesの為OK
プログラムの挙動自体はご教示頂いた通りで、自身も理解しておりその点に関しては異論は無いのですが、公式のヘルプページの記載が良く分からず確認しております。(実際のプログラムの挙動と相違がある為)
恐れ入りますがその点に関して、以前のやり取りも含めご回答頂けますと幸いです。
> ヘルプページのload関数の説明にて「load(filename,variables)」と記載されていますが、cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']というプログラムは上記のパターンとMATLABは理解するで間違っていませんでしょうか?
⇒はいその認識で間違っていません。load(filename,variables) に対し、
BeforeName = 'sample.mat';
CheckList = {'check1','check2','check3'}; % テスト用
cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']
cmd = 'load('sample.mat','check1','check2','check3');'
filename ← 第1引数はBeforeName (='sample.mat') が対応します
variables ← 第2引数(以降)はstrjoin(rot90(CheckList,3),''',''') (='check1','check2','check3') が対応します
first = 'load('''; disp(first) ←第1引数はfilenameの為NG
→第1引数はload関数の仕様からfilenameしか指定できないと理解していますが合ってますでしょうか?
⇒違います「load('」は load 関数本体を記述する為に書いた文字で、第1引数ではありません。
>第2引数は可変個数なので、第3引数、第4引数…と続く事が想定されます。
上記ご回答から第3引数以降の引数はご回答頂いた通り、仕様上問題無く動作すると理解しております。
が第2引数に関してはvariablesの所filenameを指定していまっているので動作しない。
second = 'sample.mat'; disp(second) ←第2引数はvariablesの為NG
third = ''','''; disp(third) ←第3引数以降はvariablesの為OK
fourth = strjoin(rot90(CheckList,3),''','''); disp(fourth) ←第3引数以降はvariablesの為OK
fifth = ''');'; disp(fifth) ←第3引数以降はvariablesの為OK
⇒これも違います。load関数は、エスケープやstrjoin関数の解釈が終わった後の文字列を解釈するのです。
>プログラムの挙動自体はご教示頂いた通りで、自身も理解しておりその点に関しては異論は無いのですが、公式のヘルプページの記載が良く分からず確認しております。(実際のプログラムの挙動と相違がある為)恐れ入りますがその点に関して、以前のやり取りも含めご回答頂けますと幸いです。
下記は文字ベクトルを連結する為の構文であり、これ自身が文字ベクトルの中身を実行する訳ではありません。それを行うには eval 等のMATLAB式を評価する関数を実行する必要があります。下記に例を示します。
cmd = ['fprintf(''','today is hot.','\n','今日は暑いです。',''');']
cmd = 'fprintf('today is hot.\n今日は暑いです。');'
eval(cmd); % 文字ベクトルcmdをコマンドとして実行する
today is hot. 今日は暑いです。
しん
しん on 14 Mar 2023
Edited: しん on 14 Mar 2023
first = 'load('''; disp(first) ←第1引数はfilenameの為NG
→第1引数はload関数の仕様からfilenameしか指定できないと理解していますが合ってますでしょうか?
⇒違います「load('」は load 関数本体を記述する為に書いた文字で、第1引数ではありません。
上記は例としてセミコロンになっていますが、私がそもそも質問していたプログラムではカンマになっています。
上記の場合はそれで正しいのは分かりますが、そもそも下記の場合はカンマで引数を区切って指定していると思っていますが、下記の場合でも第1引数はBeforeNameになるのでしょうか?
カンマで区切られているので、下記の場合ですと引数は6個あると思っていますが、認識間違っていますでしょうか?(デバックするとそうならないので認識が違うのは自覚しておりますが、公式ヘルプページの記載から理解出来る説明をお願いします。)
cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');']
再三の質問で恐縮ですがご回答お願いします。
first = 'load('''; disp(first) ←第1引数はfilenameの為NG
→第1引数はload関数の仕様からfilenameしか指定できないと理解していますが合ってますでしょうか?
⇒違います「load('」は load 関数本体を記述する為に書いた文字で、第1引数ではありません。
⇒この流れの問答は私の勘違いがありました。まず他の意図で書かれたコメントをそのままコピペしてしまった事。そして、「load('」は load 関数本体を記述する為に書いた文字で第1引数ではないのに、私が変数名をfirstとした事で誤解を与えてしまったという事ですね。私は単に文字列を連結する際の変数名を1,2,3,4,5番目と表したかっただけです。下記の様に変数名を変更すれば、@しんさんの解釈に沿う表現になりますでしょうか?
func = 'load('''; disp(func) % disp()を使えば、実際の文字ベクトルだけが表示される
load('
first = 'sample.mat'; disp(first)
sample.mat
dlmtr = ''','''; disp(dlmtr)
','
CheckList = {'check1','check2','check3'}; % テスト用
second = strjoin(rot90(CheckList,3),''','''); disp(second)
check1','check2','check3
dlmtr2 = ''');'; disp(dlmtr2)
');
cmd = [func, first, dlmtr, second, dlmtr2]; disp(cmd)
load('sample.mat','check1','check2','check3');
Atsushi Ueno
Atsushi Ueno on 14 Mar 2023
Edited: Atsushi Ueno on 14 Mar 2023
>上記は例としてセミコロンになっていますが、私がそもそも質問していたプログラムではカンマになっています。
⇒それは無理もない話で、私が各要素を複数行に分けて書き下したので、出力を抑制する為にセミコロンで区切らざるを得なくなっています。
>上記の場合はそれで正しいのは分かりますが、そもそも下記の場合はカンマで引数を区切って指定していると思っていますが、下記の場合でも第1引数はBeforeNameになるのでしょうか?
⇒はい。load関数にとっての第1引数はBeforeName(当該変数の内容)です。
>カンマで区切られているので、下記の場合ですと引数は6個あると思っていますが、認識間違っていますでしょうか?(デバックするとそうならないので認識が違うのは自覚しておりますが、公式ヘルプページの記載から理解出来る説明をお願いします。)
⇒cmd = ['load(''',BeforeName,''',''',strjoin(rot90(CheckList,3),''','''),''');'] の図解です。これでどうでしょう。
なんかどうもデバッグに関する見解で認識違いが生じている様ですね。
しん
しん on 16 Mar 2023
ご回答有難う御座います。
とても分かり易くある程度理解出来ました。
細部に関して念の為確認させてください。
緑色から水色へ変換(関数が展開(実行される?)?)際の挙動ですが、「'load(''',」についてご教示下さい。
load関数の先頭にある一重引用符が消えるのは変数cmdに代入されることと関係ありますでしょうか?
またload関数の後方にある一重引用符が3個から1個に変化する箇所と、カンマが消えてしまう挙動が未だに良く理解できずにおります。
上記2点に関してご教示頂けますと幸いです。
何卒宜しくお願い致します。
Atsushi Ueno
Atsushi Ueno on 16 Mar 2023
Edited: Atsushi Ueno on 16 Mar 2023
>load関数の先頭にある一重引用符が消えるのは変数cmdに代入されることと関係ありますでしょうか?
いいえ関係ありません。私が無意識に一重引用符を書いたり書かなかったりしていました。理解を妨げる様な描き方になってしまい申し訳ありません。下記に統一して書く様に修正した図を添付します。
  • 水色の枠外に書いた一重引用符が文字ベクトルである事を示す為に括った一重引用符です
  • 水色の枠内に描いた一重引用符は、緑色の枠内と違ってエスケープシーケンスが除かれています。本来MATLABでこのような表現方法はできません。(それが無意識に消した理由です)
  • 図の右側に文字ベクトルの連結を例として併記しました
これで下記3種類の一重引用符が混在している事が明確になったかと思います。
  • エスケープシーケンスとしての一重引用符
  • 文字そのものとしての一重引用符
  • 文字ベクトルである事を示す一重引用符
Atsushi Ueno
Atsushi Ueno on 16 Mar 2023
文字ベクトルの連結については下記リンク先のドキュメントに記載されています。
角括弧を用いる文字ベクトルの連結方法は 代替機能 として取り挙げられていました。MATLABのデータ型に慣れた人はこの代替機能を使う事が多いと思いますが、新しいstring型とも共通の扱い方が可能な strcat 関数や append 関数を使った方が、万人にとって分かり易いかもしれません。

Sign in to comment.

Products

Release

R2018b

Asked:

on 13 Mar 2023

Commented:

on 16 Mar 2023

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!