Types and values
Data types#
Faber 採用靜態、型別優先的型別系統。每個宣告都將型別置於名稱之前:textus nomen,而非 nomen: textus。型別系統涵蓋純量原始型別、泛型集合、定寬數值、張量,以及面向 GPU 的暫存器型別。
原始型別#
| 型別 | 作用 | 字面值範例 |
|---|---|---|
文字 | Unicode 字串 | "Salve, munde" |
ascii | 固定機器權杖 | 'solum:lege' |
整數 | 有號整數(預設為 i64) | 42 |
小數 | 浮點數(預設為 f64) | 3.14 |
布林 | 布林值 | 真、假 |
空值 | 單位/無值 | — |
空 | 空值/不存在 | 空 |
執行個體 | 持續時間/時間瞬間 | — |
JSON | 編譯期 JSON 值 | { "key": "value" } |
位元組 | 十六進位位元組序列 | \|00ff\| |
定寬數值型別#
整數 和 小數 具有預設定寬(i64 和 f64),也支援明確指定定寬的形式:
定值 整數<i32> narrow ← 7 ∷ 整數<i32>
定值 整數<u64> wide ← 255 ∷ 整數<u64>
定值 f32 single ← 1.5 ∷ f32在型別位置可使用定寬簡寫:i8 … u64、f16、f32、f64 分別等同於 numerus<W>/fractus<W>。
可空型別#
可空值使用聯集語法 T ∪ nihil:
函式 find(文字 key) → 整數 ∪ 空 {
傳回 空
}
函式 maybe() → 文字 ∪ 空 {
傳回 空
}Faber 不提供 T? 或 Option<T> 語法。聯集必須明確寫出。
型別別名#
型別 UserId = 整數泛型#
函式、型別別名、類型 和 implendum 使用 <T> 語法接受型別參數:
函式 identitas<T>(T valor) → T {
傳回 valor
}
函式 primum<T>(列表<T> res) → T ∪ 空 {
傳回 res.primus()
}支援在呼叫位置明確指定型別引數:
函式 identitas<T>(T valor) → T {
傳回 valor
}
定值 整數 value ← identitas<整數>(7)集合#
| 型別 | 作用 | 簡寫 |
|---|---|---|
lista<T> | 有序動態集合 | lf32、lu32 |
tabula<K, V> | 鍵值對映 | — |
tensor<T, Figura> | 密集固定形狀緩衝區 | tf32[4]、ti64[2,3] |
sparsa<T, Figura> | 稀疏固定形狀緩衝區 | sf32[4]、si64[2,3] |
intervallum | 範圍型別 | — |
copia<T> | 無序集合 | — |
cursor<T> | 惰性串流 | — |
定值 列表<整數> nums ← [1, 2, 3]
定值 表格<文字, 整數> scores ← { "alice": 10, "bob": 20 }張量型別#
tensor<T, Figura> 是密集固定形狀容器:
| 形式 | 意義 |
|---|---|
tensor<T, Figura> | 標準拼寫 |
tensor<T, []> | 秩 0(純量容器) |
tensor<T, _> | 形狀推論缺口 |
tensor<T, [N]> | 秩 1 向量 |
tensor<T, [N, M]> | 秩 2 矩陣 |
定值 張量<f32, []> scalar ← 空集
定值 張量<整數, [4]> vector ← [1, 2, 3, 4] ↦ 張量<整數, [4]>
定值 整數 ∪ 空 first ← vector[0]GPU 核心型別#
系統層會辨識這些型別,以支援 GPU 與暫存器工作。 不具備硬體支援的套件目標會拒絕這些型別:
函式 half(f16 x) → f16 {
傳回 x
}
函式 add(矩陣<f32, [2, 2]> a, 矩陣<f32, [2, 2]> b) → 矩陣<f32, [2, 2]> {
傳回 a.addita(b)
}
函式 swap(原子<整數<i32>> cell, 整數<i32> value) → 整數<i32> {
傳回 cell.exchange(value)
}型別上的借用標記#
借用標記(從、傳入、取自)可出現在參數位置的型別上,用來指出值的傳遞方式:
# shared borrow — caller retains ownership
functio imprime(de textus label) → vacuum { }
# mutable borrow — caller lends mutable access
functio duplica(in numerus value) → vacuum { }
# move — caller gives up ownership
functio consume(ex textus buffer) → textus {
redde buffer
}比較規則#
| 運算子 | 類別 | 行為 |
|---|---|---|
≡、≠ | 精確相等 | 必須使用相同型別;空 可略過此要求 |
≈、≉ | 數值相等 | 僅限數值格 |
<、≤、>、≥ | 排序 | 數值、瞬間、純量文字 |
intra | 範圍包含 | 數值位於範圍內 |
inter | 集合成員資格 | 元素位於集合內 |
Variables and binding#
Faber 有三個變數關鍵字,以及專用的指派字元。關鍵差異在於 定值(只能寫入一次)與 變值(可自由重新指派),以及 ←(執行期流程)與 =(結構欄位形狀)之間的區別。
fixum — 不可變繫結#
定值 繫結只能寫入一次。宣告時可以提供初始值,也可以不提供;若未提供初始值,則必須在讀取前恰好指派一次。第二次指派會被拒絕。
定值 整數 count ← 0
定值 文字 name ← "Marcus"
定值 列表<整數> inferred ← [1, 2, 3]延遲初始化:
入口 {
定值 整數 factor
若 真 {
factor ← 10
}
否則 {
factor ← 100
}
註記 factor
}varia — 可變繫結#
變值 繫結可以自由重新指派:
入口 {
變值 整數 count ← 0
count ← count + 1
count ← count * 2
}sit — 推導的不可變語法糖#
sit 是 fixum _ 的語法糖——具有推導型別的不可變繫結:
入口 {
定值 文字 salve ← "Salve"
定值 文字 nomen ← "Marcus"
定值 整數 x ← 42
# Deferred form
定值 文字 label
label ← "deferred"
}執行期繫結與結構定義#
Faber 將多數語言合併在 = 中的概念分開:
| 字元 | 作用 | 用於 |
|---|---|---|
← | 執行期流程 | 初始繫結、重新指派、變更 |
= | 結構形狀 | 常值與中繼資料中的欄位名稱 |
類型 Point {
整數 x
整數 y
}
入口 {
# Runtime: ← attaches a value to a name at execution time
變值 整數 count ← 0
變值 文字 label ← "ready"
count ← count + 1
# Structural: = defines field values inside a type literal
定值 Point p ← Point {x = 10, y = 20}
}ex 欄位擷取#
取自 將值中的欄位擷取至區域繫結:
類型 Persona {
文字 nomen
整數 aetas
}
入口 {
定值 Persona p ← Persona {nomen = "Marcus", aetas = 30}
定值 文字 nomen ← p.nomen
定值 整數 aetas ← p.aetas
# prints "Marcus"
註記 nomen
}後置遞增與遞減#
⊕ 與 ⊖ 是可變 整數 儲存處的後置遞增/遞減陳述式。它們只能作為陳述式使用——沒有運算式值,也沒有前置形式:
入口 {
變值 整數 i ← 0
# i becomes 1
i ⊕
# i becomes 0
i ⊖
}Collections#
Faber 有數種由編譯器擁有的集合型別。它們的標準方法定義於編譯器中,而非標準函式庫。
Lista — 有序動態集合#
定值 列表<整數> empty ← 空集
定值 列表<整數> numbers ← [1, 2, 3, 4, 5]
定值 列表<文字> names ← ["Marcus", "Julia", "Gaius"]
定值 列表<列表<整數>> nested ← [[1, 2], [3, 4]]使用 sparge 展開:
定值 列表<整數> a ← [1, 2, 3]
定值 列表<整數> b ← [4, 5, 6]
定值 列表<整數> combined ← [展開 a, 展開 b]
定值 列表<整數> headed ← [0, 展開 a, 99]主要方法:longitudo、accipe、appende、summa、primus、novissimus。
Tabula — 鍵值對映射#
定值 表格<文字, 整數> scores ← { "alice": 10, "bob": 20 }Tensor — 密集固定形狀緩衝區#
定值 張量<f32, []> scalar ← 空集
定值 張量<整數, [4]> vector ← [1, 2, 3, 4] ↦ 張量<整數, [4]>
定值 整數 ∪ 空 first ← vector[0]Tensor 語法糖(數值運算密集的程式碼):
定值 張量<f32, []> seed ← 空集
定值 張量<f32, [4]> lanes ← seed.strue([1.0, 2.0, 3.0, 4.0], [4])主要方法:forma、accipe、ponde、crea、structa、strue,以及逐元素算術、矩陣乘法(multiplicatio)和歸約(summa、productum)。
Sparsa — 稀疏固定形狀緩衝區#
定值 稀疏<f32, [2, 3]> sparse ← 空集
入口 {
sparse.ponde([0, 1], 4.0)
sparse.ponde([1, 2], 9.0)
# accipe returns the stored value, here 4.0
註記 sparse.accipe([0, 1])
# count of stored entries
註記 sparse.nonnihil()
}在密集與稀疏格式之間轉換:
定值 張量<f32, [2, 2]> dense ← [[1.0, 0.0], [0.0, 2.0]] ↦ 張量<f32, [2, 2]>
定值 稀疏<f32, [2, 2]> sparse ← dense ↦ 稀疏<f32, [2, 2]>
定值 張量<f32, [2, 2]> roundtrip ← sparse ↦ 張量<f32, [2, 2]>Cursors — 延遲串流#
cursor<T> 是延遲串流型別。它可以由集合迭代器、tuus 檢視或產生器函式建立。使用 itera ex 消費:
定值 列表<整數> items ← [1, 2, 3]
入口 {
遍歷 取自 items 定值 item {
註記 item
}
}Intervallum — 範圍#
入口 {
# exclusive range: 0, 1, 2, 3, 4
遍歷 範圍 0‥5 定值 i {
註記 i
}
# inclusive range: 0, 1, 2, 3, 4, 5
遍歷 範圍 0…5 定值 i {
註記 i
}
}‥ 表示不包含終點的範圍;… 表示包含終點的範圍。
String and template literals#
Faber 使用分隔符語義——每種引號形式都代表不同的原始碼形狀。它們不是可互換的同義詞。
字面形式#
| 形式 | 類型 | 作用 | ||
|---|---|---|---|---|
'…' | ascii | 固定機器標記;不含 §;不含 (…) | ||
"…" | 文字 | 短 Unicode 行字串;可解析 (…) | ||
«…» | 文字 | 區塊/多行 Unicode;可解析 (…) | ||
… | forma | 擷取的範本;可擷取 (…) | ||
{ … } | JSON | 編譯期 JSON 文件 | ||
| ` | … | ` | 位元組 | 編譯期十六進位位元組 |
[ … ] | lista<T> | Faber 清單字面值 |
字串範本套用#
Faber 使用字串範本套用來格式化文字:先寫入含有 § 佔位符的 "…" 或 «…» 字面值,再接上括號引數:
函式 greet(文字 nomen) → 文字 {
傳回 "Salve, §!"(nomen)
}
定值 整數 pagina ← 3
定值 整數 totum ← 10
定值 文字 code ← "200"
定值 文字 label ← "OK"
定值 文字 msg ← "Page § of §"(pagina, totum)
定值 文字 block ← "status: § (§)"(code, label)主要規則:
§(U+00A7)是範本佔位符- 位置佔位符:
§0、§1、…,用於明確指定順序 - 尾端的
!選取顯示格式:"Salve, §!"(nomen) (args)尾碼是範本套用,不是函式呼叫
區塊字串#
多行區塊使用書名號 «…»:
定值 文字 sql ← «
select id, email
from accounts
»擷取的範本(forma)#
反引號範本會擷取文字與參數,但不進行解析。 適合用於繫結的 SQL/URL 承載內容:
定值 整數 user_id ← 42
定值 forma query ← `select * from users where id = §`(user_id)內嵌 JSON#
裸露的 { … } 是內嵌 JSON:它是編譯期的 JSON 文件,不是匿名的 Faber 物件。鍵是以引號括起、並以 : 分隔的字串:
定值 JSON empty ← {}
定值 JSON user ← { "name": "Marcus", "age": 30, "active": true }
定值 JSON nested ← { "meta": { "version": 1 }, "tags": ["alpha", "beta"] }若要建構具型別的 類型,請使用型別名稱與 = 欄位形狀:
類型 Point {
整數 x
整數 y
}
定值 Point p ← Point {x = 10, y = 20}Nullability and optionality#
Faber 區分值中的缺失與宣告位置上的可選提供。
可為空值 — T ∪ nihil#
當值可能缺失時,使用 T ∪ nihil:
函式 find(文字 key) → 整數 ∪ 空 {
傳回 空
}
函式 divide(整數 a, 整數 b) → 整數 ∪ 空 {
若 b ≡ 0 則 傳回 空
傳回 a / b
}可選宣告槽位 — sponte#
當參數或欄位可由呼叫者或建構函式省略時,在名稱後使用 sponte:
函式 connect(文字 host, 整數 port 可選) → 空值 {
}
類型 User {
文字 email 可選
}借用標記可以與可選參數結合:
函式 process(從 整數 depth 可選) → 空值 {
}非空值斷言 — !#
使用 !.、![、!( 來斷言可為空值不是 空:
類型 Box {
整數 ∪ 空 val
}
定值 Box ∪ 空 maybe_name ← Box {val = 7}
定值 整數 ∪ 空 name ← maybe_name!.val對 空 進行非空值斷言會在執行階段中止。
空值合併 — vel#
定值 文字 ∪ 空 provided ← 空
定值 文字 name ← provided 或取 "default"ignotum#
ignotum 是頂層未知型別,用於逃生閘道與不完整的知識。它不是可為空值的機制。
Conversion and construction#
兩個重要的轉換運算子,一個用於執行期,另一個用於編譯期:
# runtime conversion
定值 整數 parsed ← "42" ↦ 整數
# static ascription
定值 整數 value ← 7
定值 文字 text ← value ∷ 文字執行期轉換 — ↦#
使用 ↦ 進行執行期轉換,尤其適用於可能失敗的剖析或強制轉型。使用 ⇥ 提供行內復原:
定值 文字 input ← "9"
定值 整數 n ← "42" ↦ 整數
定值 整數 safe ← input ↦ 整數 ⇥ 0由型別導向的具現化:
定值 文字 path ← "/etc/hosts"
定值 向量<f32, 4> lanes ← [1.0, 2.0, 3.0, 4.0] ↦ 向量<f32, 4>
定值 文字 body ← 端點 'solum:lege' (path) ↦ 文字靜態歸屬 — ∷#
使用 ∷ 明確標註靜態型別。它是後綴運算子,並由目標型別決定:
定值 整數 value ← 7
定值 整數<i32> x ← 7 ∷ 整數<i32>
定值 文字 text ← value ∷ 文字空值合併 — vel#
當值為 空 時,使用 vel 進行空值合併:
定值 文字 ∪ 空 provided_name ← 空
定值 文字 name ← provided_name 或取 "default"