はじめに
先日、以下の記事を発表しました。
新しいテクノロジーに触れる時はいつでも楽しいものです。
まだまだ勉強中ですが、公式ドキュメントの学習過程の記録として、以下の記事をまとめてみました。
本稿情報のソースとして、下記ドキュメントを参照ください。
構文
Fenl は式で構成されます。すべての Fenl 式は値のストリームを記述します。
また、式を合成して新しい式を形成することができます。
単項演算と二項演算
算術演算は、ほとんどのプログラミング言語と同様に表現できます。
1 + 2 / (3 * 4)
論理演算では標準的な比較記号とともに、and
および or
というキーワードを組み合わせることができます 。
true and (5 >= 2) or !false
ドット構文
以下のようなJSONスタイルで複数の値を構成することができます。
{ a: 10, b: true }
複数の値を構成するデータ型では、ドット構文を使用して個々の値を参照できます。
{ a: 10, b: true }.a
上記の結果は、10
になります。
条件分
すべての Fenl 式は値を生成します(Fenlは、命令型ではなく宣言型であることを思い出してください)。
if
やwhen
のような条件文は、式の値を決定するために使用されます。
たとえば、次の式の結果は、5
という値です。
5 | if(true)
そして、次の式の値はnull
になります。
5 | if(false)
Let バインディング
Let バインディングは、式に(ローカル)名を割り当てる特別な操作です。
これは、特定の式を複数回参照する必要がある場合や、複雑な式をより小さな部分に分割する場合に有益です。
バインディングには 2 つのコンポーネントがあります。名前と式のバインディングの後に、バインドされた名前を参照できる本体式が続きます。
let the_answer = 42
in the_answer * 2
let
の部分を繰り返すことによって、複数の(入れ子の)バインディングを導入することができます。バインディングは以前のバインディングを参照することができます。
let the_answer = 42
let not_the_answer = the_answer * 2
in the_answer != not_the_answer
let
式で定義した値は、in
式で利用されます。
パイプ構文
Fenl では、パイプ演算子|
を使用して関数呼び出しを連鎖させることができます。パイプ演算子の基本的な構造としては、左側の式の結果を、右側の式内の$input
にバインドします。
42 | mul(2, $input)
上記の省略表現として、下記のような表現が可能です。パイプ式の 右項内で使用される関数では、$input
を使用する引数の記載を省略することができます。
42 | mul(2)
パイプ演算子は、以下のように、複数の操作を順番に適用する場合に便利です。
the_answer
| add(10)
| div(2)
| gt(0)
パイプ操作LHS | RHS
は、 let $input = LHS in RHS
と同等と言うことも言えます。
(RHS = right-hand side, LHS = left-hand side)
関数呼び出し
関数は括弧を付けて呼び出されます。関数パラメータには名前が付けられます。
substring(s = "input", start = 0, end = 2)
パラメーターには、デフォルト値を持つものがあります。デフォルト値を持つパラメータは関数呼び出しの記載から省略できます。
substring("input")
名前付きパラメータの値をデフォルト値で指定する場合は、パラメータ名を含める必要があります。
substring("input", 0) # 無効なシンタックス
substring("input", start = 0) # 有効なシンタックス
関数の設計
Fenlでは、多くの関数が「data
」パラメータと「config
」パラメータを持つ設計となっています。
たとえば、substring
関数では、開始オフセットから終了オフセット (「config
」パラメータ) までの文字範囲指定により、文字列 (「data
」パラメータ) を変換します。
substring(zipcode, start=0, end=6)
Fenl の関数は、「data
」パラメータを最後の必須パラメータまたは位置パラメータとして配置しようとします。「data
」パラメーターを最後に配置すると、パイプ構文を使用するときにそれらを簡単に省略できます。
この設計の結果として、コード記述においては、「config
」パラメーター指定が強調されます。
名前解決
Fenl の名前解決はコンテキストに依存します。コンテキストは通常、ユーザーが定義したテーブル名(ref:tableservice[tables]
) およびビュー名( ref:viewservice[views]
)のセットが存在しているところから始まります。
式で使う名前が、これらの名前と重複しないことが必要です。
let
および|
演算子を使用して名前をコンテキストに追加できます。これらの方法でバインドされた名前は、関連付けられた部分式 (たとえば、 let
のin
句や の RHS 式)でのみ表示されます。
名前は複数回バインドされる場合があります。名前が 2 回バインドされている場合、2 番目のバインディングは2 番目のバインディング後のin
部分式内でのみ利用できます。
let current_favorite = "pizza"
let first_favorite = current_favorite
let current_favorite = "hot dogs"
in { current_favorite, first_favorite }
一旦、名前Aによってバインドされた名前Bは、その後名前Aが新たにバインドされても、影響を受けません。
この例では、名前current_favorite
は、別の名前first_favorite
の宣言時に、その値としてバインドされ 、その後、名前current_favorite
は 別の値にバインドされます。しかし、first_favorite
の値は、current_favorite
の再バインドの影響を受けません。
{ "current_favorite": "hot dogs", "first_favorite": "pizza"}