name が John または Robert の場合は、male 変数と found 変数の両方を true に設定します。
CFScript では、次のタイプのステートメントを使用できます。
- 代入ステートメントおよび関数
- 条件処理ステートメント
- ループステートメント
代入ステートメントおよび関数の使用
CFScript の代入ステートメントは、cfset タグに相当します。このステートメントの形式は次のとおりです。
lval = expression;
eval は、任意の ColdFusion 変数の参照です。次に例を示します。
x = "positive"; y = x; a[3]=5; structure.member=10; ArrayCopy=myArray;
CFScript では、ColdFusion 関数(UDF を含む)を直接呼び出せます。例えば、次の行は有効な CFScript ステートメントです。
StructInsert(employee,"lastname",FORM.lastname);
条件処理ステートメントの使用
CFScript では、次の条件処理ステートメントが使用できます。
- if および else ステートメント。これは、cfif、cfelseif、cfelse タグに相当します。
- switch、case、default ステートメント。これは、cfswitch、cfcase、cfdefaultcase タグに相当します。
if および else ステートメントの使用
if および else ステートメントのシンタックスは次のとおりです。
if(expr) statement [else statement]
最も簡単な if ステートメントの例を示します。
if(value EQ 2700) message = "You've reached the maximum";
簡単な if-else ステートメントの例を示します。
if(score GT 1) result = "positive"; else result = "negative";
CFScript には elseif ステートメントはありません。cfelseif タグに相当する処理をおこなうには、次の例のように、else ステートメントの直後に if ステートメントを記述します。
if(score GT 1) result = "positive"; else if(score EQ 0) result = "zero"; else result = "negative";
条件処理を記述する部分では、一般的な条件処理ステートメントと同じように、中括弧を使用して複数のステートメントを囲むことができます。
if(score GT 1) { result = "positive"; message = "The result was positive."; } else { result = "negative"; message = "The result was negative."; }
多くの場合、括弧を適切に使用することで、コードの読みやすさを向上させることができます(処理上は不要な括弧であっても)。
switch および case ステートメントの使用
switch ステートメントと、その従属ステートメントである case および default ステートメントのシンタックスを次に示します。
switch (expression) { case constant: [case constant:]... statement(s) break; [case constant: [case constant:]... statement(s) break;]... [default: statement(s)] }
switch ステートメントを使用するときは、次のルールおよび推奨事項に従ってください。
- 1 つの switch ステートメント内に、ブール値定数と数値定数を混在させることはできません。
- constant は定数である必要があります。変数、関数、または他の式は指定できません。
- 複数の case constant: ステートメントを、1 つまたは複数のステートメントの前に並べることができます。この場合は、それらの case のいずれかが true になれば、その後のステートメントが実行されます。これによって、1 つのコードブロックを複数の条件に対応させることができます。
- 同じ定数値を複数の case で指定することはできません。
- case ステートメントブロックのコロンの後のステートメントは、中括弧で囲む必要はありません。switch 式に等しい定数値が見つかると、break ステートメントに達するまで、以降のすべてのステートメントが実行されます。
- case ステートメントの末尾にある break ステートメントは、switch ステートメントを終了させるために使用します。break ステートメントを省略しても、エラーにはなりません。このステートメントが存在しない場合は、次の case ステートメントに記述されているステートメントもすべて実行されます。これは、次の case 条件が false であってもおこなわれます。このような動作を意図しておこなうことは少なく、ほとんどの場合は break の記述忘れです。
- 1 つの switch ステートメントブロックで使用できる default ステートメントは、1 つのみです。式の値に等しい case ステートメント定数がない場合は、default ブロックに記述されているステートメントが実行されます。
- default ステートメントは常に必要なわけではありませんが、case ステートメントを使用するときはその最後に default ステートメントを記述するのがよいプログラミングスタイルといえます。case ステートメントの最後に default ステートメントを記述する場合は、default ブロックコードの最後に break ステートメントを置く必要があります。
- default ステートメントは必須ではありませんが、式が取り得る値を case 定数ですべて列挙していない場合は、このステートメントを使用します。
次の switch ステートメントでは、name 変数の値に基づいて処理をおこないます。
-
-
name が Mary の場合は、male 変数を false に、found 変数を true に設定します。
-
その他の場合は、found 変数を false に設定します。
switch(name) { case "John": case "Robert": male=True; found=True; break; case "Mary": male=False; found=True; break; default: found=False; } //end switch
動的 switch-case
以前のバージョンの ColdFusion では、switch-case の処理は静的でした。case ステートメントの値はソースコードにハードコーディングされている必要がありました。
ColdFusion(2021 リリース)では、switch および case ステートメントの値は動的です。スクリプトシンタックスとタグシンタックスの両方がサポートされています。
次の例は、動的 switch-case の使用方法を示しています。
タグシンタックス
<cfswitch expression="#(() => 1)()#" > <cfcase value="5">I like kiwi!</cfcase> <cfcase value="#(5 GT 1)#">I like Orange!</cfcase> <cfdefaultcase>Fruit, what fruit?</cfdefaultcase> </cfswitch>
出力
I like Orange!
算術演算子
<cfscript> s=-1 switch((()=> 1)()) { case 3/4: writeoutput("22") break; case s+ 2: writeoutput("21") break; } </cfscript>
出力
21
変数参照
<cfscript> s=123 switch((()=> 123)()) { case s: writeoutput("21") break; } </cfscript>
出力
21
default ステートメント
<cfscript> s = 125; switch((()=> 125)()) { case 20 : default : writeoutput("6") break; case s : writeoutput("21") break; } switch((()=> 125)()) { case s : case 125 : writeoutput("21") break; default : writeoutput("6") break; } switch((()=> 125)()) { default : writeoutput("6") break; case 125 : writeoutput("21") break; } </cfscript>
出力
212121
UDF
<cfscript> public string function f() { return "yes" } switch((()=> "yes")()) { case round(3.14159): writeoutput("22") break; case f(): writeoutput("23") break; default: writedump("via UDF") } </cfscript>
出力
23
単項演算子
<cfscript> s = 123 switch((()=> 125)()) { case -(-s) + 2: writeoutput("22") break; } </cfscript>
出力
22
三項演算子
<cfscript> switch((()=> "hi")()) { case (5 GT 1)? "h" & "i" : "hello" : writeoutput("21") break; } </cfscript>
出力
21
文字列演算子
<cfscript> switch((()=> "hi")()) { case "h" & "i" : writeoutput("21") break; } </cfscript>
出力
21
論理演算子
<cfscript> public string function f() { return "yes" } switch((()=> true)()) { case f() && false: writeoutput("23") break; case !f(): writeoutput("22") break; case !(6 - 3 * 2): writeoutput("22") break; } </cfscript>
出力
22
IIFE
<cfswitch expression="#(() => 1)()#" > <cfcase value="#(()=> 1)()#" >I like kiwi!</cfcase> </cfswitch>
出力
I like kiwi!
配列参照
<cfscript> b = [2, 21, 211] switch((()=> 1)()) { case 1 + Round(3.14159)/Round(3.14159): writeoutput("22") break; case b[1] - 1: writeoutput("21") break; } </cfscript>
出力
21
構造体参照
<cfscript> b = { e = 2, f = 21, g = 211} switch((()=> 21)()) { case b.e: writeoutput("2"); break; case b.f: writeoutput("21") ; break; } </cfscript>
出力
21
ループステートメントの使用
CFScript には、CFML タグよりも豊富なループ構文が用意されています。一般的なプログラミング言語やスクリプト言語と同じように、効果的なループ構文を作成できます。CFScript では、次のループ構文を使用できます。
- For
- While
- Do-while
- For-in
また、ループ処理を制御する continue および break ステートメントも使用できます。
for ループの使用
for ループの形式を次に示します。
for (initial-expression; test-expression; final-expression) statement
initial-expression および final-expression は、次のいずれかです。
- 1 つの代入式(x=5 や loop=loop+1 など)
- 任意の ColdFusion 式(SetVariable("a",a+1) など)
- 空
test-expression は次のいずれかです。
次のような任意の ColdFusion 式
A LT 5 index LE x status EQ "not found" AND index LT end
- 空
test expression は、ループを繰り返す前に再評価されます。ループ内のコードによって test expression の任意の部分を変更すると、ループの繰り返し回数に影響を及ぼす可能性があります。
statement は、セミコロンで終了する単一のステートメントか、中括弧で囲まれているステートメントブロックです。
ColdFusion では、for ループは次のように処理されます。
-
initial-expression が評価されます。
-
test-expression が評価されます。
-
test-expression が False の場合は、ループが終了し、statement の次のコードから処理が続行されます。test-expression が true の場合は、次のように処理されます。
a. statement(またはステートメントブロック)が実行されます。
b. final-expression が評価されます。
c. 手順 2 に戻ります。
ループ構文の代表的な使い方は、ループを繰り返すたびにインデックス変数を増加させていく方法です(それ以外の使い方もできます)。
次のループサンプルでは、10 要素からなる配列の各要素に、そのインデックス番号を設定します。
for(index=1; index LTE 10; index = index + 1) a[index]=index;
より複雑な次の例では、2 つの方法を使用しています。
- 中括弧を使用して複数のステートメントをグループ化し、1 つのブロックにしています。
- 空条件ステートメントを使用しています。ループの制御ロジックは、すべてステートメントブロックの中に含まれています。
<cfscript> strings=ArrayNew(1); ArraySet(strings, 1, 10, "lock"); strings[5]="key"; indx=0; for( ; ; ) { indx=indx+1; if(Find("key",strings[indx],1)) { WriteOutput("Found key at " & indx & ".<br>"); break; } else if (indx IS ArrayLen(strings)) { WriteOutput("Exited at " & indx & ".<br>"); break; } } </cfscript>
この例では、ループを作成するときの重要な注意事項が示されています。それは、ループを確実に終了させる必要があるということです。この例で else if ステートメントを記述し忘れると、配列に「key」が含まれていなかった場合、(システムエラーが発生して停止しない限り)ColdFusion が無限ループに陥ります。無限ループを終了させるには、サーバーを停止する必要があります。
また、この例では、インデックスの処理に関する 2 つの注意事項も示されています。1 つは、この形式のループではインデックスを初期化する必要があることです。もう 1 つは、どこでインデックスが増加するかを考慮して処理をおこなう必要があることです。この場合は、ループの開始時にインデックスが増加するので、最初のループで 1 になるように、インデックスの初期値を 0 にします。
while ループの使用
while ループの形式を次に示します。
while (expression) statement
while ステートメントは、次のように処理されます。
- expression が評価されます。
- expression が true の場合は、以下が実行されます。
- statement(セミコロンで終了する単一のステートメントか、中括弧で囲まれているステートメントブロック)が実行されます。
手順 1 に戻ります。
expression が false の場合は、後続のステートメントから処理が続行されます。次の例では、while ループを使用して、10 要素からなる配列に 5 の倍数を設定しています。
a = ArrayNew(1); loop = 1; while (loop LE 10) { a[loop] = loop * 5; loop = loop + 1; }
他のループと同様に、while の expression がいつかは必ず false になるようにし、インデックスの処理に注意する必要があります。
do-while ループの使用
do-while ループは while ループに似ていますが、ループのステートメントブロックが実行された後にループ条件がテストされる点が異なります。do-while ループの形式を次に示します。
do statement while (expression);
do while ステートメントは、次のように処理されます。
-
statement(セミコロンで終了する単一のステートメントか、中括弧で囲まれているステートメントブロック)が実行されます。
-
expression が評価されます。
-
expression が true の場合は、手順 1 に戻ります。
expression が false の場合は、後続のステートメントに処理が移ります。
次の例では、while ループの例と同様に、10 要素からなる配列に 5 の倍数を設定します。
a = ArrayNew(1); loop = 1; do { a[loop] = loop * 5; loop = loop + 1; } while (loop LE 10);
配列値を代入した後にループインデックスをインクリメントしているので、loop 変数を 1 に初期化し、この値が 10 以下であることを確認しています。
次の例は、前の 2 つの例と同じ結果になりますが、インデックスをインクリメントしてから配列値を代入しているので、インデックスを 0 に初期化し、終了条件としてインデックスの値が 10 未満であることを確認しています。
a = ArrayNew(1); loop = 0; do { loop = loop + 1; a[loop] = loop * 5; } while (loop LT 10);
クエリ結果をループ処理する例を次に示します。
<cfquery ... name="myQuery"> ... sql goes here... </cfquery> <cfscript> if (myQuery.RecordCount gt 0) { currRow=1; do { theValue=myQuery.myField[CurrRow]; currRow=currRow+1; } while (currRow LTE myQuery.RecordCount); } </cfscript>
for-in ループの使用
for-in ループは、ColdFusion 構造体内の各要素をループします。このループの形式を次に示します。
for (variable in structure) statement
variable は任意の ColdFusion 識別子で、ColdFusion が構造体内をループする際に、構造体のキー名が格納されます。structure は、既存の ColdFusion 構造体の名前である必要があります。statement は、セミコロンで終了する単一のステートメントか、中括弧で囲まれているステートメントブロックです。
次の例では、3 つの要素を持つ構造体を作成します。その後、構造体をループして、各キーの名前と値を表示します。この例に含まれている中括弧は必須ではありませんが、長い WriteOutput 関数の内容を識別しやすくするために使用しています。一般的に、ループなどの構造化された制御フローでは、中括弧を使用すると読みやすくなります。
myStruct=StructNew(); myStruct.productName="kumquat"; mystruct.quality="fine"; myStruct.quantity=25; for (keyName in myStruct) { WriteOutput("myStruct." & Keyname & " has the value: " & myStruct[keyName] &"<br>"); }
cfloop タグとは異なり、CFSCript の for-in ループには、クエリおよびリストをループ処理する機能は組み込まれていません。
continue および break ステートメントの使用
continue および break ステートメントを使用すると、ループ内の処理を制御できます。
- continue ステートメントは、次のループ繰り返しの先頭までスキップするように指示します。
- break ステートメントは、現在のループまたは case ステートメントを終了します。
continue の使用
continue ステートメントは、現在のループ繰り返しを終了し、ループ内の以降のコードをすべてスキップして、次のループ繰り返しの先頭にジャンプします。例えば、次のコードは 1 つの配列をループし、空の文字列以外の値を表示します。
for ( loop=1; loop LE 10; loop = loop+1) { if(a[loop] EQ "") continue; WriteOutput(loop); }
このコードスニペットをテストするには、10 以上の要素からなり、いくつかの要素に空以外の文字列が含まれている、a という配列を最初に作成する必要があります。
continue ステートメントは、配列や構造体をループするときに、空の文字列などの特定の値を持つ配列要素または構造体メンバーの処理をスキップするのに便利です。
break の使用
break ステートメントは、現在のループまたは case ステートメントを終了します。処理は、次の CFScript ステートメントから続行されます。case のステートメント処理ブロックは、break ステートメントを使用して終了します。また、次の例のように、無限ループを防止するために特定のテストケースで break ステートメントを実行することもできます。このスクリプトは、配列をループし、key という値を含んでいる配列インデックスを出力します。配列の末尾でループを必ず終了させるために、条件テストと break ステートメントを使用しています。
strings=ArrayNew(1); ArraySet(strings, 1, 10, "lock"); strings[5]="key"; strings[9]="key"; indx=0; for( ; ; ) { indx=indx+1; if(Find("key",strings[indx],1)) { WriteOutput("Found a key at " & indx & ".<br>"); } else if (indx IS ArrayLen(strings)) { WriteOutput("Array ends at index " & indx & ".<br>"); break; } }
for-in 構文(配列の場合)
CFScript で for-in 構文を使用して、配列に対するループを実行できます。
h7.例
public String foo(array a) { for(var item in a) { writedump(item); } }
for-in 構文(クエリの場合)
配列や構造体に対するループ処理と同様に、for-in 構文を使用すると、CFScript のクエリオブジェクトをループ処理できます。
例
この例では、クエリの結果セットは変数 arts に格納されており、for-in ループを使用して結果セットをループ処理しています。for-in 構文で使用されている変数 row は、クエリ列をキーとして含む構造体です。arts.currentrow を使用して現在の行を参照できます。
<cfquery name="arts" datasource="cfartgallery"> select * from art </cfquery> <cfscript> cols = listToArray(listsort(arts.columnlist, "textnocase")); for(row in arts) { for(col in cols) writeoutput(arts.currentrow & " ..." & col & ": " & row[col] & "<br>"); writeoutput("<hr>"); } </cfscript>
recordcount や currentrow などのクエリ結果変数にアクセスするには、クエリ名を前に付ける必要があります(例を参照)。
for ループ内の var 宣言
この機能は、ColdFusion 9 アップデート 1 をインストールしてある場合にのみ適用されます。
for-in 構文で var インラインを使用して、構造体と配列の両方の変数をローカルスコープにバインドできます。
例
public String foo(struct s) { for(var item in s) { writedump(item & ": " & s[item]); } writedump(local); }
配列の例については、for-in 構文(配列の場合)を参照してください。
for-in 構文における Java 配列のサポート
for-in 構文で、ネイティブな ColdFusion 配列に加えて、Java 配列がサポートされるようになりました。次に例を示します。
<cfscript> a = CreateObject("java","java.util.Arrays").AsList(ToString("CF,10,Zeus").split(",")); for (var1 in a) { WriteOutput(var1); } </cfscript>
break や continue を使用しているループでのラベルのサポート
どのようなプログラミングパラダイムでも、開発者はループを処理するコードを作成する必要があります。ループは、繰り返しの多いタスクをおこなう必要がある場合に便利です。ほとんどの開発者は、複数のループ、ループ内のループなどのコードを記述します。複雑なシナリオでは、内側のループの反復処理中に外側のループから抜け出す必要があるような状況があります。
ループのシンタックス
// For Loop: <OuterLabel> : for(){ <InnerLabel> : for(){ break OuterLabel; continue OuterLabel; } }
*// While Loop: <OuterLabel> : while(){ <InnerLabel> : while(){ break OuterLabel; continue OuterLabel; } }
ラベルは、ループ内で break または continue を実行すべきトレースマークとして使用できる対応ポイントです。<label> は、そのラベルが定義されている対応ループからブレークアウト/続行するために、対応する break および continue ステートメントで使用されます。通常は、break; ステートメントまたは continue; ステートメントを書くだけで、対応するステートメントが実行された場所から最も近いループから抜け出すまたは続行することができます。
break と continue のシンタックス
break <label>; // ラベルは for/while ループの開始より前に定義されています
continue <label>; // ラベルは for/while ループの開始より前に定義されています
例 1
<cfscript> xyz : for(i=110;i<115;i++){ abc : for(j=10;j<20;j++) { writeDump(i); if(j%3 == 0) continue xyz; writeDump(j); } writeDump("<br>"); } </cfscript>
出力
110 10 110 11 110 111 10 111 11 111 112 10 112 11 112 113 10 113 11 113 114 10 114 11 114
例 2
<cfscript> // breaking out using a label x = 0; WhileLabel: while (x < 10){ writeOutput("x is #x#<br>"); switch (x){ case 1: break; case 3: break WhileLabel; } x++; writeOutput("end of of loop<br>"); } writeOutput("After loop, x is #x#<br>"); </cfscript>
出力
x is 0
end of of loop
x is 1
end of of loop
x is 2
end of of loop
x is 3
After loop, x is 3
例 3
<cfloop index="i" from="1" to="10" label="xyz"> <cfoutput>#i#</cfoutput> <br> <cfif i Ge 5> <cfcontinue xyz> </cfif> <cfoutput>#i#->#i#</cfoutput> <br> </cfloop>
出力
1
1->1
2
2->2
3
3->3
4
4->4
5
6
7
8
9
10