Files
Decodal/doc/manual/source/jp/language/examples.md
T

2.8 KiB

この章では、Decodal の主要な記法を組み合わせた例を示す。

基本的な設定スキーマ

Host = String;

Port = Int & >= 1 & <= 65535;
NarrowedPort = Port & > 443;

MyConfig = {
    host = Host;
    port = NarrowedPort default 8080;
    feature_hoge = {
        enable = Bool default true;
        fuga = Int default 10;
    };
};

NewConfig = MyConfig & {
    host = "127.0.0.1";
    port = 8000;
};

disabled_config = NewConfig & {
    feature_hoge.enable = false;
};

enabled_config = NewConfig;

配列スキーマ

Services = [...{
    name = String;
    port = Int default 8080;
}];

[
    { name = "api"; },
    { name = "worker"; port = 9000; },
] as Services

抽象配列には要素制約が必須である。 この例では、1 番目の要素の port8080 に materialize される。

連想配列と範囲絞り込み

Service = {
    port = Int;
    enabled = Bool default true;
};

services = {
    api = { port = 8080; };
    worker = { port = 8081; enabled = false; };
} as {...Service};

apiworker は任意の key であり、それぞれの value は Service より狭い範囲へ絞り込まれる。 as の結果では api.enabled は abstract のまま残り、最終的に結果全体を materialize した時点で default の true が使われる。

関数と制約

let
    Port = Int & >= 1 & <= 65535;
    add_offset = (base: Port, offset: Int) => base + offset;
in
    add_offset(8000, 80)

評価結果:

8080

match

(
    input_a: {
        hoge = Int & >= 0;
    },
    input_b: {
        fuga = 20;
    }
) =>
let
    inputs = {
        a = input_a;
        b = input_b;
    };
in
{
    foo = match inputs.a.hoge {
        >= 20: {
            value = 200;
        };
        >= 10: {
            value = 100;
        };
        _: {
            value = 300;
        };
    };
}

match は上から順に評価されるため、広い条件より狭い条件を先に書く。

deep patch

Base = {
    feature_hoge = {
        enable = Bool default true;
        fuga = Int default 10;
    };
};

Patched = Base // {
    feature_hoge.enable = false;
};

Patched は以下に相当する。

{
    feature_hoge = {
        enable = false;
        fuga = Int default 10;
    };
}

循環 import

# main.dcdl
{
    schema = {
        hoge = String;
    };

    result = (import "./func.dcdl")(schema);
}
# func.dcdl
(input: (import "./main.dcdl").schema) =>
{
    # ...
}

func.dcdlmain.dcdl を import しているが、参照しているのは main.schema である。 main.schemamain.result に依存していなければ、この循環 import は成立する。