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

2.6 KiB

Examples

This chapter combines Decodal's main constructs in complete examples.

Basic configuration schema

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;

Array schema

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

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

An abstract array requires an element constraint. In this example, port in the first element materializes to 8080.

Associative arrays and range refinement

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

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

api and worker are arbitrary keys, and each value is refined to a range narrower than Service. In the result of as, api.enabled remains abstract. Its default of true is selected only when the complete result is materialized.

Functions and constraints

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

Evaluation result:

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 evaluates arms in order, so place narrower conditions before broader ones.

Deep patch

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

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

Patched is equivalent to:

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

Cyclic imports

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

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

func.dcdl imports main.dcdl, but it references only main.schema. The cyclic import is valid as long as main.schema does not depend on main.result.