Types and values
Data types#
Faber có hệ thống kiểu tĩnh, ưu tiên kiểu. Mọi khai báo đều đặt kiểu trước tên: textus nomen, không phải nomen: textus. Hệ thống kiểu bao phủ các kiểu nguyên thủy vô hướng, tập hợp tổng quát, kiểu số có kích thước, tensor và các kiểu thanh ghi hướng đến GPU.
Các kiểu nguyên thủy#
| Kiểu | Vai trò | Literal ví dụ |
|---|---|---|
văn_bản | Chuỗi Unicode | "Salve, munde" |
ascii | Token máy có độ dài cố định | 'solum:lege' |
số | Số nguyên có dấu (mặc định i64) | 42 |
thập_phân | Số dấu phẩy động (mặc định f64) | 3.14 |
logic | Boolean | đúng, sai |
trống | Đơn vị / không có giá trị | — |
rỗng | Null / vắng mặt | rỗng |
thời_điểm | Khoảng thời gian / thời điểm | — |
json | Giá trị JSON tại thời điểm biên dịch | { "key": "value" } |
byte | Chuỗi byte dạng thập lục phân | \|00ff\| |
Các kiểu số có kích thước#
số và thập_phân có độ rộng mặc định (i64 và f64) cùng các dạng chỉ rõ
độ rộng:
hằng số<i32> narrow ← 7 ∷ số<i32>
hằng số<u64> wide ← 255 ∷ số<u64>
hằng f32 single ← 1.5 ∷ f32Có thể dùng cú pháp rút gọn độ rộng ở vị trí kiểu: i8 … u64, f16, f32,
f64 tương đương với numerus<W> / fractus<W>.
Các kiểu nullable#
Giá trị nullable sử dụng cú pháp hợp T ∪ nihil:
hàm find(văn_bản key) → số ∪ rỗng {
trả rỗng
}
hàm maybe() → văn_bản ∪ rỗng {
trả rỗng
}Faber không có cú pháp T? hoặc Option<T>. Hợp kiểu phải được viết tường minh.
Bí danh kiểu#
kiểu_tên UserId = sốGenerics#
Hàm, bí danh kiểu, kiểu và implendum chấp nhận tham số kiểu với cú pháp
<T>:
hàm identitas<T>(T valor) → T {
trả valor
}
hàm primum<T>(danh_sách<T> res) → T ∪ rỗng {
trả res.primus()
}Có thể chỉ rõ đối số kiểu tại vị trí gọi:
hàm identitas<T>(T valor) → T {
trả valor
}
hằng số value ← identitas<số>(7)Tập hợp#
| Kiểu | Vai trò | Cú pháp rút gọn |
|---|---|---|
lista<T> | Tập hợp động có thứ tự | lf32, lu32 |
tabula<K, V> | Bản đồ khóa-giá trị | — |
tensor<T, Figura> | Bộ đệm dày có hình dạng cố định | tf32[4], ti64[2,3] |
sparsa<T, Figura> | Bộ đệm thưa có hình dạng cố định | sf32[4], si64[2,3] |
intervallum | Kiểu khoảng | — |
copia<T> | Tập hợp không có thứ tự | — |
cursor<T> | Luồng lười | — |
hằng danh_sách<số> nums ← [1, 2, 3]
hằng bảng<văn_bản, số> scores ← { "alice": 10, "bob": 20 }Các kiểu tensor#
tensor<T, Figura> là bộ chứa dày có hình dạng cố định:
| Dạng | Ý nghĩa |
|---|---|
tensor<T, Figura> | Cách viết chuẩn |
tensor<T, []> | Rank 0 (bộ chứa vô hướng) |
tensor<T, _> | Vị trí để suy luận hình dạng |
tensor<T, [N]> | Vector rank 1 |
tensor<T, [N, M]> | Ma trận rank 2 |
hằng ten_xo<f32, []> scalar ← tập_rỗng
hằng ten_xo<số, [4]> vector ← [1, 2, 3, 4] ↦ ten_xo<số, [4]>
hằng số ∪ rỗng first ← vector[0]Các kiểu lõi GPU#
Các kiểu này được lane hệ thống nhận diện để xử lý GPU và thanh ghi. Các đích gói không hỗ trợ phần cứng sẽ từ chối chúng:
hàm half(f16 x) → f16 {
trả x
}
hàm add(ma_trận<f32, [2, 2]> a, ma_trận<f32, [2, 2]> b) → ma_trận<f32, [2, 2]> {
trả a.addita(b)
}
hàm swap(nguyên_tử<số<i32>> cell, số<i32> value) → số<i32> {
trả cell.exchange(value)
}Marker mượn trên kiểu#
Các marker mượn (ra, vào, từ) có thể xuất hiện trên kiểu ở vị trí tham số
để cho biết cách truyền một giá trị:
# 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
}Chính sách so sánh#
| Toán tử | Nhóm | Hành vi |
|---|---|---|
≡, ≠ | Bằng chính xác | Bắt buộc các kiểu giống hệt nhau; rỗng được bỏ qua |
≈, ≉ | Bằng theo giá trị số | Chỉ áp dụng cho lattice số |
<, ≤, >, ≥ | Thứ tự | Số, thời điểm, văn bản vô hướng |
intra | Chứa trong khoảng | Số nằm trong khoảng |
inter | Thành viên tập hợp | Phần tử nằm trong tập hợp |
Variables and binding#
Faber có ba từ khóa biến và một ký hiệu gán riêng. Điểm khác biệt chính nằm giữa hằng (chỉ ghi một lần) và biến (có thể gán lại tự do), cũng như giữa ← (luồng thực thi) và = (hình dạng trường mang tính cấu trúc).
fixum — liên kết bất biến#
Các liên kết hằng chỉ được ghi một lần. Có thể khai báo chúng có hoặc không có trình khởi tạo; nếu khai báo mà không có trình khởi tạo, chúng phải được gán đúng một lần trước khi đọc. Lần gán thứ hai sẽ bị từ chối.
hằng số count ← 0
hằng văn_bản name ← "Marcus"
hằng danh_sách<số> inferred ← [1, 2, 3]Khởi tạo trì hoãn:
bắt_đầu {
hằng số factor
nếu đúng {
factor ← 10
}
khác {
factor ← 100
}
ghi_chú factor
}varia — liên kết khả biến#
Các liên kết biến có thể được gán lại tự do:
bắt_đầu {
biến số count ← 0
count ← count + 1
count ← count * 2
}sit — cú pháp rút gọn cho liên kết bất biến suy luận kiểu#
sit là cú pháp rút gọn của fixum _ — một liên kết bất biến với kiểu được suy luận:
bắt_đầu {
hằng văn_bản salve ← "Salve"
hằng văn_bản nomen ← "Marcus"
hằng số x ← 42
# Deferred form
hằng văn_bản label
label ← "deferred"
}Liên kết thời gian chạy và định nghĩa cấu trúc#
Faber tách biệt hai vai trò mà hầu hết các ngôn ngữ gộp chung vào =:
| Ký hiệu | Vai trò | Dùng cho |
|---|---|---|
← | Luồng thời gian chạy | Liên kết ban đầu, gán lại, biến đổi |
= | Hình dạng cấu trúc | Tên trường bên trong literal và siêu dữ liệu |
kiểu Point {
số x
số y
}
bắt_đầu {
# Runtime: ← attaches a value to a name at execution time
biến số count ← 0
biến văn_bản label ← "ready"
count ← count + 1
# Structural: = defines field values inside a type literal
hằng Point p ← Point {x = 10, y = 20}
}Trích xuất trường bằng ex#
từ trích xuất các trường từ một giá trị vào các liên kết cục bộ:
kiểu Persona {
văn_bản nomen
số aetas
}
bắt_đầu {
hằng Persona p ← Persona {nomen = "Marcus", aetas = 30}
hằng văn_bản nomen ← p.nomen
hằng số aetas ← p.aetas
# prints "Marcus"
ghi_chú nomen
}Tăng và giảm hậu tố#
⊕ và ⊖ là các câu lệnh tăng/giảm hậu tố dành cho các vị trí số khả biến. Chúng chỉ được dùng như câu lệnh — không có giá trị biểu thức và không có dạng tiền tố:
bắt_đầu {
biến số i ← 0
# i becomes 1
i ⊕
# i becomes 0
i ⊖
}Collections#
Faber có một số kiểu tập hợp do trình biên dịch sở hữu. Các phương thức chuẩn của chúng nằm trong trình biên dịch, không nằm trong thư viện chuẩn.
Lista — tập hợp động có thứ tự#
hằng danh_sách<số> empty ← tập_rỗng
hằng danh_sách<số> numbers ← [1, 2, 3, 4, 5]
hằng danh_sách<văn_bản> names ← ["Marcus", "Julia", "Gaius"]
hằng danh_sách<danh_sách<số>> nested ← [[1, 2], [3, 4]]Trải phần tử bằng sparge:
hằng danh_sách<số> a ← [1, 2, 3]
hằng danh_sách<số> b ← [4, 5, 6]
hằng danh_sách<số> combined ← [rải a, rải b]
hằng danh_sách<số> headed ← [0, rải a, 99]Các phương thức chính: longitudo, accipe, appende, summa, primus, novissimus.
Tabula — ánh xạ khóa–giá trị#
hằng bảng<văn_bản, số> scores ← { "alice": 10, "bob": 20 }Tensor — bộ đệm dày có hình dạng cố định#
hằng ten_xo<f32, []> scalar ← tập_rỗng
hằng ten_xo<số, [4]> vector ← [1, 2, 3, 4] ↦ ten_xo<số, [4]>
hằng số ∪ rỗng first ← vector[0]Cú pháp rút gọn cho Tensor (mã thiên về số):
hằng ten_xo<f32, []> seed ← tập_rỗng
hằng ten_xo<f32, [4]> lanes ← seed.strue([1.0, 2.0, 3.0, 4.0], [4])Các phương thức chính: forma, accipe, ponde, crea, structa, strue, cùng với phép tính theo từng phần tử, phép nhân ma trận (multiplicatio) và các phép rút gọn (summa, productum).
Sparsa — bộ đệm thưa có hình dạng cố định#
hằng thưa<f32, [2, 3]> sparse ← tập_rỗng
bắt_đầu {
sparse.ponde([0, 1], 4.0)
sparse.ponde([1, 2], 9.0)
# accipe returns the stored value, here 4.0
ghi_chú sparse.accipe([0, 1])
# count of stored entries
ghi_chú sparse.nonnihil()
}Chuyển đổi giữa dạng dày và dạng thưa:
hằng ten_xo<f32, [2, 2]> dense ← [[1.0, 0.0], [0.0, 2.0]] ↦ ten_xo<f32, [2, 2]>
hằng thưa<f32, [2, 2]> sparse ← dense ↦ thưa<f32, [2, 2]>
hằng ten_xo<f32, [2, 2]> roundtrip ← sparse ↦ ten_xo<f32, [2, 2]>Cursors — luồng lười#
cursor<T> là một kiểu luồng lười. Nó được tạo từ các bộ lặp của tập hợp, các view tuus hoặc các hàm sinh. Luồng được tiêu thụ bằng itera ex:
hằng danh_sách<số> items ← [1, 2, 3]
bắt_đầu {
lặp từ items hằng item {
ghi_chú item
}
}Intervallum — các khoảng#
bắt_đầu {
# exclusive range: 0, 1, 2, 3, 4
lặp khoảng 0‥5 hằng i {
ghi_chú i
}
# inclusive range: 0, 1, 2, 3, 4, 5
lặp khoảng 0…5 hằng i {
ghi_chú i
}
}‥ là điểm cuối khoảng loại trừ; … là điểm cuối khoảng bao gồm.
String and template literals#
Faber sử dụng ngữ nghĩa của các dấu phân cách — mỗi dạng dấu nháy biểu thị một dạng mã nguồn khác nhau. Chúng không phải là các từ đồng nghĩa có thể thay thế cho nhau.
Dạng literal#
| Dạng | Kiểu | Vai trò | ||
|---|---|---|---|---|
'…' | ascii | Token cố định dành cho máy; không có §; không có (…) | ||
"…" | văn_bản | Chuỗi Unicode một dòng ngắn; (…) được nội suy | ||
«…» | văn_bản | Unicode dạng khối/nhiều dòng; (…) được nội suy | ||
… | forma | Template được thu giữ; (…) được thu giữ | ||
{ … } | json | Tài liệu JSON tại thời điểm biên dịch | ||
| ` | … | ` | byte | Dãy byte hex tại thời điểm biên dịch |
[ … ] | lista<T> | Literal danh sách Faber |
Áp dụng template chuỗi#
Faber định dạng văn bản bằng phép áp dụng template chuỗi: một literal
"…" hoặc «…» có các vị trí trống §, theo sau là các đối số trong
ngoặc đơn:
hàm greet(văn_bản nomen) → văn_bản {
trả "Salve, §!"(nomen)
}
hằng số pagina ← 3
hằng số totum ← 10
hằng văn_bản code ← "200"
hằng văn_bản label ← "OK"
hằng văn_bản msg ← "Page § of §"(pagina, totum)
hằng văn_bản block ← "status: § (§)"(code, label)Các quy tắc chính:
§(U+00A7) là vị trí trống của template- Vị trí trống theo thứ tự:
§0,§1, … để chỉ rõ thứ tự - Dấu
!ở cuối chọn cách định dạng hiển thị:"Salve, §!"(nomen) - Hậu tố
(args)là phép áp dụng template, không phải lời gọi hàm
Chuỗi dạng khối#
Các khối nhiều dòng sử dụng dấu ngoặc kép kiểu guillemet «…»:
hằng văn_bản sql ← «
select id, email
from accounts
»Template được thu giữ (forma)#
Template dùng dấu backtick thu giữ văn bản và tham số mà không thực hiện việc kết xuất. Phù hợp cho payload SQL/URL có liên kết tham số:
hằng số user_id ← 42
hằng forma query ← `select * from users where id = §`(user_id)JSON nội tuyến#
{ … } trần là JSON nội tuyến: một tài liệu json tại thời điểm biên dịch,
không phải là đối tượng Faber ẩn danh. Các khóa là chuỗi được đặt trong dấu
nháy và phân tách bằng ::
hằng json empty ← {}
hằng json user ← { "name": "Marcus", "age": 30, "active": true }
hằng json nested ← { "meta": { "version": 1 }, "tags": ["alpha", "beta"] }Để tạo một kiểu có kiểu, hãy sử dụng tên kiểu và dạng trường với =:
kiểu Point {
số x
số y
}
hằng Point p ← Point {x = 10, y = 20}Nullability and optionality#
Faber phân biệt sự vắng mặt trong một giá trị với việc cung cấp tùy chọn tại vị trí khai báo.
Giá trị nullable — T ∪ nihil#
Dùng T ∪ nihil khi giá trị có thể vắng mặt:
hàm find(văn_bản key) → số ∪ rỗng {
trả rỗng
}
hàm divide(số a, số b) → số ∪ rỗng {
nếu b ≡ 0 do_đó trả rỗng
trả a / b
}Vị trí khai báo tùy chọn — sponte#
Đặt sponte sau tên khi tham số hoặc trường có thể được lược bỏ bởi bên gọi hoặc hàm khởi tạo:
hàm connect(văn_bản host, số port tự_nguyện) → trống {
}
kiểu User {
văn_bản email tự_nguyện
}Các dấu mượn có thể kết hợp với tham số tùy chọn:
hàm process(ra số depth tự_nguyện) → trống {
}Khẳng định non-null — !#
Dùng !., ![, !( để khẳng định rằng một giá trị nullable không phải là rỗng:
kiểu Box {
số ∪ rỗng val
}
hằng Box ∪ rỗng maybe_name ← Box {val = 7}
hằng số ∪ rỗng name ← maybe_name!.valKhẳng định non-null trên rỗng sẽ hủy thực thi tại thời điểm chạy.
Kết hợp nullish — vel#
hằng văn_bản ∪ rỗng provided ← rỗng
hằng văn_bản name ← provided hoặc_nếu_rỗng "default"ignotum#
ignotum là kiểu unknown cấp cao nhất dành cho các lối thoát tạm thời và tri thức chưa hoàn chỉnh. Đây không phải là cơ chế biểu diễn tính nullable.
Conversion and construction#
Hai toán tử chuyển đổi quan trọng, một toán tử dùng khi chạy chương trình và một toán tử dùng tại thời điểm biên dịch:
# runtime conversion
hằng số parsed ← "42" ↦ số
# static ascription
hằng số value ← 7
hằng văn_bản text ← value ∷ văn_bảnChuyển đổi khi chạy chương trình — ↦#
Dùng ↦ để chuyển đổi khi chạy chương trình, đặc biệt là khi phân tích cú pháp hoặc ép kiểu có thể thất bại. Cung cấp xử lý phục hồi nội tuyến bằng ⇥:
hằng văn_bản input ← "9"
hằng số n ← "42" ↦ số
hằng số safe ← input ↦ số ⇥ 0Vật chất hóa theo kiểu:
hằng văn_bản path ← "/etc/hosts"
hằng vectơ<f32, 4> lanes ← [1.0, 2.0, 3.0, 4.0] ↦ vectơ<f32, 4>
hằng văn_bản body ← gọi 'solum:lege' (path) ↦ văn_bảnGán kiểu tĩnh — ∷#
Dùng ∷ để gán kiểu tĩnh một cách tường minh. Toán tử này đặt ở hậu tố và được điều khiển bởi kiểu đích:
hằng số value ← 7
hằng số<i32> x ← 7 ∷ số<i32>
hằng văn_bản text ← value ∷ văn_bảnKết hợp giá trị null — vel#
Dùng vel để kết hợp giá trị null khi một giá trị là rỗng:
hằng văn_bản ∪ rỗng provided_name ← rỗng
hằng văn_bản name ← provided_name hoặc_nếu_rỗng "default"