前回に引き続き、FileMakerHacksのKevin Frankさんによる、新しいWhile関数についての記事の続編を紹介します。
New in FM 18: While, part 2
(元記事はこちら)
Kevin Frank
2019/6/1
今回は、FileMaker 18で新たに登場したWhile関数についてさらに詳しく見ていきます。繰り返しを避けるために、読者が先回のSetRecursionとWhileに関する記事を読んでいることを前提として進めます。基本的なものから高度なものまで、いくつかの新しい例を見て、今までLet関数で宣言していた変数をWhileで使用できる状況を調べ、WhileとCustomListを比較したベンチマーク結果をチェックします。
デモファイル
注釈付きの例: カウント数のリスト
While ( [ 初期変数 ] ; 条件 ; [ ロジック ] ; 結果 )
以下はとても簡単な例です。大したことはせず、数字のリストを表示するだけです。
この関数はもともと“ Loop”と名付けられることになっていました。終了条件が満たされるまで、関数が[ロジック]を繰り返し適用しながら、内部でループするので、それは中身にふさわしい良い名前でした。そう言いつつ、関数名が実際の今の名前に変更されてよかったと思っています。理由(a) スクリプトステップのLoopとの混同を避けるため、理由(b) 「条件が満たされる限り[ロジック]を適用し続ける。条件が満たされなくなったら、結果を表示する」という意味においては、Whileの方が正確な名前だから。
テキスト文字列の並びを逆にする
説明:
- Middle()を使用してテキスト文字列(a)を右から左へ走査して一度に1文字ずつ抽出し、新しい文字列を左から右へ組み立てる
- 変数bは文字列の長さを保持してスタートし、繰り返しごとに1ずつ減っていく
- b = 0になったら結果を表示する
変数のスコープ(有効範囲)
今までLetで宣言していた変数が、どのような場合にWhileに変換可能なのでしょうか? この関数の特殊な構造を念頭に…
While ( [ 初期変数 ] ; 条件 ; [ ロジック ] ; 結果 )
以下のことがわかりました。a) 今までLetによって宣言されていたすべての変数は目で見ることができた。しかし、b) [ロジック]セクションで変換されるすべての変数は[初期変数]セクションで宣言「されなければならない」。「されなければならない」を引用符でくくったのは一つ例外があるからで、それについては後ほど説明します。
以下の式は正しく機能します(変数“a”が[ロジック]セクションで変換されないからです)。
しかし”b”または”x”をLet宣言に移すと、正しく機能しません。
上で私が言及した例外はここです。標準のLet変数ではなく、$ローカル変数または$$グローバル変数を使用することができます。 そして$xは空からスタートするので、事前に宣言せずに[ロジック]セクションで変換することが可能です。
その他の興味深い点:
- このような状況の場合、[初期変数]セクションは空のままで問題ありません。
- 計算で$ローカル変数または$$グローバル変数をインスタンス化するときは、上記の2番目のLet宣言のように、最後に手動でクリーンアップする必要があります。
注: Whileの[初期変数]宣言を空のままにしてもかまいませんが、そこに””を入れると正しく動きません(空の結果が返されます)。
それでは、もう少し普通の($ローカル変数以外の)例を見てみましょう。
Whileの中のWhile
以下の例では、外側のWhileが縦方向のリストを作成し、内側のWhileが横方向のカンマ区切りのリストを作成します。
私は概してWhileの方がCustomListよりも扱いが簡単だと感じました。ただしこの例では、CustomListの方が実装の容易さの点で優れています。
オースチンに浸る
前回のジェーン・オースチンのテキスト(高慢と偏見の最初の章)に戻って…
今回は2つの例を示します。一つ目はアルファベット順に並べられた索引。各単語が章内で何回出現するかを示します。
説明: SortValuesとUniqueValuesを使用してアルファベット順の索引を生成します。これを行うためにWhileは必要ありません。Whileが役に立つのは、各単語の出現回数を数えて、その情報を追加する部分です。誤検出を避けるに、PatternCountではなくFilterValuesを使用します(たとえば、”a”が他の単語の一部としてではなく、独立した単語である場合にのみカウントしたい)。
二つ目は、あるオンラインフォーラムに投稿された現実のニーズから作成されたものです。各段落で最も長い単語を識別します…そしてこの課題の楽しい部分の1つは、複数の単語が同率一位になるかもしれないという点です。
前のWhile内のWhileの例でも見たように、ここには縦方向リストを生成する外側のWhileと、各段落を処理して最長の単語を抽出する内側のWhileがあります。
パスカルの三角形
2011年にパスカルの三角形を2回シリーズで取り上げました(Combination and Pascal’s Triangle, part 1とCombination and Pascal’s Triangle, part 2)。以下の議論は、読者がパスカルの三角形を知っているか、前述の連載のpart 1を読んでいることを想定しています。
注: これは独立した別のデモファイルになっており、メインの “Sandbox v2″のデモには含まれていません。
ここでもWhile関数を入れ子にしました。外側のWhileは縦方向の部分を生成し、内側のWhileは横方向の部分を生成します。
このような状況では、最初に「内側の問題」(または部品)をまず解決し、次に全体を考えるとうまくいくと思います。具体的には、ここでは行を組み立てるときに前の行から値のペアを合計するため、データビューアで作業を進め、テストケースとして4行目(“1 3 3 1”)を使用して5行目を作成しました。
FM 18ランタイムマージコード
今回の最後のデモは、私が2014年にPauseOnErrorで行ったプレゼンテーションからのものです。その時には私はカスタム関数を使いました。ここではその代わりにWhileを使用するようにアプローチを更新しました。この最低限のデモでは、強力なテクニックの最小限の実装を示します。
Templatesテーブルがあります…
…そしてAliasesテーブルのInputフィールドには偽のマージフィールドが含まれ、Outputフィールドには実行コードが含まれています。
ユーザがtemplateを選択すると…
…スクリプトトリガーで起動されたスクリプトステップがInputをOutputに翻訳します…
…その結果、以下のような文章が出力されます。
注: デバッグ用に、手紙文の生成時にCtrlキーを押すと、偽のマージフィールドの部分が赤で表示されます。
これで今回のデモは終わりです。
WhileとCustomListを比較した予備的なベンチマークの結果
すべてのテストは私の年季の入ったWindows 7のノートPCで行われました。予備的なテストの結果では、どちらの関数が速いかは実行するタスクの種類に依存するようです。
タスク1 — 大きなリストの作成を伴う場合、CustomListの方が速くなります。たとえば、n=70,000の場合、1からnまでのスペース区切りのリストを作るにはWhileとCustomListの両方で約4秒かかります。 しかしnを90,000まで増やすと、Whileでは9秒かかりますが、CustomListは5秒しかかかりませんでした。
タスク1: While
タスク1: CustomList
タスク2 — CustomListは常に改行区切りのリストを作成することを覚えておいてください。これは好きなように変換して構いませんが、リストを作成するためのオーバーヘッドが発生します。このテストでは1から300,000までのカウンターを繰り返して結果を表示します。これはWhileは2秒で完了するのに対し、CustomListは14秒かかります。
タスク2: While
タスク2: CustomList
タスク3 — 自分自身に.0001を100,000回追加します。Whileは1秒かかり、CustomListは5秒かかります。しかしもちろん、CustomListは計算を実行するだけではなく、100,000個の値を含むリストも生成します。
タスク3: While
タスク3: CustomList
まとめ
今回の記事を終わるにあたっては、私のCustomListについての記事の結論部分の修正版で締めくくるのが一番いいと考えました。今回と先回の記事の目標は、Whileを使って達成できることの幅と深さについていくらかの感覚を伝えることでした。このWhile関数がFileMakerのツールボックスに入れる価値がある強力で柔軟なツールであるという事実と比べたら、私がここで示した具体例は、まったく重要ではありません。Whileを使用して面白い問題を解決したという方は、ぜひこの記事にコメントを投稿し、どんな問題だったか、それをどのように解決したかを共有してください。