การเรนเดอร์th-TH

Types and values

Data types#

Faber มีระบบชนิดข้อมูลแบบสถิตที่ให้ชนิดข้อมูลมาก่อน ทุกการประกาศจะวางชนิดข้อมูลไว้ก่อนชื่อ: textus nomen ไม่ใช่ nomen: textus ระบบชนิดข้อมูลครอบคลุมชนิดพื้นฐานแบบสเกลาร์ คอลเลกชันแบบเจเนริก ตัวเลขที่กำหนดขนาด เทนเซอร์ และชนิดรีจิสเตอร์สำหรับงาน GPU

ชนิดข้อมูลพื้นฐาน#

ชนิดข้อมูลบทบาทตัวอย่างลิเทอรัล
ข้อความสตริง Unicode"Salve, munde"
asciiโทเค็นเครื่องแบบความยาวคงที่'solum:lege'
จำนวนจำนวนเต็มมีเครื่องหมาย (ค่าเริ่มต้นคือ i64)42
เศษจำนวนทศนิยม (ค่าเริ่มต้นคือ f64)3.14
ตรรกะค่าบูลีนจริง, เท็จ
เปล่าหน่วย / ไม่มีค่า
ว่างค่า Null / ไม่มีอยู่ว่าง
อินสแตนซ์ระยะเวลา / จุดเวลาทันที
jsonค่า JSON ระหว่างคอมไพล์{ "key": "value" }
ไบต์ลำดับไบต์ฐานสิบหก\|00ff\|

ชนิดตัวเลขที่กำหนดขนาด#

จำนวน และ เศษ มีความกว้างเริ่มต้น (i64 และ f64) และมีรูปแบบที่ระบุความกว้างได้อย่างชัดเจน:

คงที่ จำนวน<i32> narrow  7จำนวน<i32>

คงที่ จำนวน<u64> wide  255จำนวน<u64>

คงที่ f32 single  1.5 ∷ f32

สามารถใช้ชวเลขความกว้างในตำแหน่งชนิดข้อมูลได้: i8u64, f16, f32, f64 เทียบเท่ากับ numerus<W> / fractus<W>

ชนิดข้อมูลที่รับค่า Null ได้#

ค่าที่รับ Null ได้ใช้ไวยากรณ์ยูเนียน 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
    วน ช่วง 05 คงที่ i {
        บันทึก i
    }
    # inclusive range: 0, 1, 2, 3, 4, 5
    วน ช่วง 05 คงที่ 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"