sml

SML { ❄ }

中文 EN

Chapter 3: Fragment Inheritance

Chapter 3: Fragment Inheritance

In real projects, many configuration blocks look similar - for example, multiple services require region, timeout, dns. Repetitive writing is both verbose and prone to inconsistency. SML uses fragments to solve this problem.

One sentence: Fragment is “value reuse” - defining a set of fields once and expanding them everywhere by referencing.

3.1 Definition fragment: @name

Define a reusable field using @名字 { }:

@net {
    region: cn-north-1
    dns: internal.swebase.cn
    timeout: 30
}

Note that @net itself will not appear in the parsing results, it is just a “template”.

3.2 Quoted excerpt: &name

Expand the fragment using &Name:

network: &net

After parsing, network will obtain:

network {
    region: cn-north-1
    dns: internal.swebase.cn
    timeout: 30
}

3.3 References within Blocks

Fragments are commonly used to inject common fields into multiple services:

@base {
    region: cn-north-1
    timeout: 30
}

service auth { &base port: 7100 name: auth-svc }
service billing { &base port: 7200 name: billing-svc }

service auth is equivalent to:

service auth {
    region: cn-north-1
    timeout: 30
    port: 7100
    name: auth-svc
}

service billing also obtained the same region/timeout, but port/name were different from each other. Reuse+individuality, perfect.

3.4 Important Details: &name will not be unfolded when written naked within the block

This is the easiest pit for beginners to step into:

server {
    &base            #  这样写,&base 被当成"键名",不会展开字段
    port: 8080
}

The correct way to write it is to assign a fragment as a value to a key:

server {
    net: &base       #  net 这个键获得 base 的全部字段
    port: 8080
}

Alternatively, &base itself can be used as the source of the value (such as the writing style of service auth { &base ... } in 3.3, which “starts the block directly with &base and then with additional fields”, the parser will treat it as “expanding the fragment first and merging subsequent fields”). * * Remember: Fragments are “values” and should appear at the value position of 键: 值. **

3.5 Fragment vs Contract (Preview)

You may wonder, “Do fragments and contracts (Chapter 5) sound like each other?” Their positioning is completely different:

Fragment @base/&baseContract @contract/@is
EssenceValue Reuse** Shape Constraints**
What to doExpand a set of fieldsValidate the structure and add default values
ResultData copied and filledData checked and filled in

The two are orthogonal and can be used together (first unfold the fragment, then use contract verification).

3.6 Give it a try with your hands

Write configuration for a game server cluster, with three servers sharing region and max_players:

@common {
    region: ap-east-1
    max_players: 64
}

lobby { &common port: 25565 name: 大厅 }
pvp { &common port: 25566 name: 竞技场 }
survival { &common port: 25567 name: 生存 }

→ [Chapter 4: Include and namespaces](/en/book/ch04 include)

Hands on practice

After reading this chapter, directly modify SML in the editor below and click “Run” to immediately see the parsing results or validation errors - having output is necessary for efficient learning.

✍ 动手练习 定义 @base { region, timeout },再写两个 service 块(auth、billing)都 &base 并各自覆盖 port 与 name。
💡 提示:把 &base 误写成裸词(去掉 &)看看会发生什么。
✍ 自测考题:第 3 章自测:片段继承 得分 0 / 4
Q1. 定义可复用片段用哪个符号?
Q2. service auth { &base port: 7100 } 里,如果 @base 已定义 port: 7000,结果 port 是?
Q3. 判断:&base 必须放在块的第一行才能生效。
Q4. 片段继承主要解决什么问题?