रेंडरिंगhi

Types and values

Data types#

Faber में एक स्थिर, प्रकार-प्रथम प्रकार-प्रणाली है। हर घोषणा में नाम से पहले प्रकार आता है: पाठ नाम, न कि नाम: पाठ। प्रकार-प्रणाली में स्केलर प्रिमिटिव, जेनरिक संग्रह, निर्धारित-आकार वाली संख्याएँ, टेंसर और GPU-संबंधी रजिस्टर प्रकार शामिल हैं।

प्रिमिटिव प्रकार#

प्रकारभूमिकाउदाहरण लिटरल
पाठUnicode स्ट्रिंग"Salve, munde"
asciiनिश्चित मशीन टोकन'solum:lege'
i32चिह्नित पूर्णांक42
f64फ्लोटिंग-पॉइंट3.14
तार्किकबूलियनसत्य, असत्य
रिक्तयूनिट / कोई मान नहीं—
शून्य_मानnull / अनुपस्थितशून्य_मान
क्षणअवधि / समय-क्षण—
jsonसंकलन-समय JSON मान{ "key": "value" }
बाइटहेक्स बाइट अनुक्रम\|00ff\|

निर्धारित-आकार वाले संख्यात्मक प्रकार#

प्रकार की स्थिति में चौड़ाई लिखें। ये संख्यात्मक प्रकार हैं — वही सूची जो Math in the ether में है:

परिवारचौड़ाई
चिह्नितi8 i16 i32 i64
अचिह्नितu8 u16 u32 u64
दशमलवd64
असीमित पूर्णांकinf
फ्लोटिंगf16 bf16 f32 f64
आरंभ {
    स्थिर i32 narrow ← 7 ∷ i32
    स्थिर u64 wide ← 255 ∷ u64
    स्थिर f32 single ← 1.5 ∷ f32
}

नंगी चौड़ाई-चिह्न ही प्रकार है।

Nullable प्रकार#

Nullable मान यूनियन सिंटैक्स T ∪ शून्य_मान का उपयोग करते हैं:

फलन find(पाठ key) → संख्या ∪ शून्य_मान {
    लौटाओ शून्यवत्
}

फलन maybe() → पाठ ∪ शून्य_मान {
    लौटाओ शून्यवत्
}

Faber में T? या Option<T> सिंटैक्स नहीं है। यूनियन स्पष्ट रूप से लिखना आवश्यक है।

प्रकार उपनाम#

प्रकार UserId = संख्या

जेनरिक#

फ़ंक्शन, प्रकार उपनाम, वर्ग और अनुबन्ध, <T> सिंटैक्स के साथ प्रकार पैरामीटर स्वीकार करते हैं:

फलन identitas<T>(T मान) → T {
    लौटाओ मान
}

फलन primum<T>(सूची<T> res) → T ∪ शून्य_मान {
    लौटाओ res.पहला()
}

कॉल-साइट पर स्पष्ट प्रकार आर्ग्युमेंट भी समर्थित हैं:

फलन identitas<T>(T मान) → T {
    लौटाओ मान
}

आरंभ {
    स्थिर संख्या value ← identitas<संख्या>(7)
}

संग्रह#

प्रकारभूमिकासंक्षिप्त रूप
सूची<T>क्रमबद्ध डायनेमिक संग्रहlf32, lu32
तालिका<K, V>कुंजी-मान मैप—
टेंसर<T, Figura>घना, निश्चित-आकार वाला बफ़रtf32[4], ti64[2,3]
विरल<T, Figura>विरल, निश्चित-आकार वाला बफ़रsf32[4], si64[2,3]
अंतरालरेंज प्रकार—
समुच्चय<T>अनियंत्रित सेट—
संकेतक<T>लेज़ी स्ट्रीम—
आरंभ {
    स्थिर सूची<संख्या> nums ← [1, 2, 3]
    स्थिर तालिका<पाठ, संख्या> scores ← { "alice": 10, "bob": 20 }
}

टेंसर प्रकार#

टेंसर<T, Figura> घना, निश्चित-आकार वाला कंटेनर है:

रूपअर्थ
टेंसर<T, Figura>मानक लेखन
टेंसर<T, []>रैंक-0 (स्केलर कंटेनर)
टेंसर<T, _>आकार-अनुमान रिक्ति
टेंसर<T, [N]>रैंक-1 वेक्टर
टेंसर<T, [N, M]>रैंक-2 मैट्रिक्स
आरंभ {
    स्थिर टेंसर<f32, []> scalar ← खाली
    स्थिर टेंसर<संख्या, [4]> row ← [1, 2, 3, 4] ↦ टेंसर<संख्या, [4]>
    स्थिर संख्या ∪ शून्य_मान first ← row[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)
}

प्रकारों पर borrow मार्कर#

Borrow मार्कर (से, में, स्वामित्व) पैरामीटर स्थितियों में प्रकारों पर दिखाई दे सकते हैं। वे बताते हैं कि कोई मान किस प्रकार पास किया जाता है:

# 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(own textus buffer) → textus {
    redde buffer
}

तुलना नीति#

ऑपरेटरपरिवारव्यवहार
≡, ≠, ≢सटीक समानतासमान प्रकार आवश्यक; शून्य_मान को अपवाद
≅, ≇प्रमोटेड सटीक समानतासंख्यात्मक चौड़ाइयाँ जुड़ती हैं, फिर सटीक तुलना
≈, ≉फ़ज़ी समानतासहनशीलता मिलान — isclose डिफ़ॉल्ट (rel_tol 1e-09); केवल संख्यात्मक संकारक
<, ≤, >, ≥क्रम निर्धारणसंख्यात्मक, instant, स्केलर टेक्स्ट
भीतररेंज समावेशनरेंज में संख्यात्मक मान
बीचसंग्रह सदस्यतासंग्रह में तत्व

Variables and binding#

Faber में तीन variable keywords और assignment के लिए एक विशेष glyph है। मुख्य अंतर स्थिर (केवल एक बार लिखने योग्य) और चर (स्वतंत्र रूप से फिर से assign करने योग्य) के बीच है, तथा ← (runtime flow) और = (संरचनात्मक field shape) के बीच है।

स्थिर — अपरिवर्तनीय binding#

स्थिर bindings केवल एक बार लिखी जा सकती हैं। इन्हें initializer के साथ या उसके बिना declare किया जा सकता है। यदि initializer के बिना declare किया गया हो, तो पढ़ने से पहले इन्हें ठीक एक बार assign करना आवश्यक है। दूसरी assignment अस्वीकार कर दी जाती है।

आरंभ {
    स्थिर संख्या count ← 0
    स्थिर पाठ name ← "Marcus"
    स्थिर _ inferred ← [1, 2, 3]
}

Deferred initialisation:

आरंभ {
    स्थिर संख्या factor
    यदि सत्य {
        factor ← 10
    }
    अन्यथा {
        factor ← 100
    }
    दिखाओ factor
}

चर — परिवर्तनशील binding#

चर bindings को स्वतंत्र रूप से फिर से assign किया जा सकता है:

आरंभ {
    चर संख्या count ← 0
    count ← count + 1
    count ← count * 2
}

बैठा — inferred immutable sugar#

बैठा, स्थिर _ का sugar है — inferred type वाली अपरिवर्तनीय binding:

आरंभ {
    स्थिर _ salve ← "Salve"
    स्थिर _ नाम ← "Marcus"
    स्थिर _ x ← 42

    # Deferred form
    स्थिर _ label
    label ← "deferred"
}

Runtime binding बनाम structural definition#

Faber उस = को दो अलग भूमिकाओं में बाँटता है, जिसे अधिकांश भाषाएँ एक ही रूप में समेट देती हैं:

Glyphभूमिकाउपयोग
←Runtime flowInitial binding, reassignment, mutation
=Structural shapeLiterals और metadata के भीतर field names
वर्ग 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
    स्थिर _ p ← Point { x = 10, y = 20 }
}

सेवन से field extraction#

सेवन किसी value से fields निकालकर local bindings में रखता है:

वर्ग Persona {
    स्थिर पाठ नाम
    स्थिर संख्या aetas
}

आरंभ {
    स्थिर _ p ← Persona { नाम = "Marcus", aetas = 30 }
    स्थिर पाठ नाम ← p.nomen
    स्थिर संख्या aetas ← p.aetas
    # prints "Marcus"
    दिखाओ नाम
}

परिवर्तनशील संख्यात्मक अपडेट#

परिवर्तनशील संख्या places को अपडेट करने के लिए binary + और - को runtime assignment ← के साथ उपयोग करें। दोनों operators दो operands लेते हैं; ये postfix statements नहीं हैं:

आरंभ {
    चर संख्या i ← 0
    # i becomes 1
    i ← i + 1
    # i becomes 0
    i ← i - 1
}

Collections#

Faber में कंपाइलर द्वारा स्वामित्व वाले कई कलेक्शन प्रकार हैं। इनके कैनोनिकल तरीके स्टैंडर्ड लाइब्रेरी में नहीं, बल्कि कंपाइलर में परिभाषित होते हैं।

Lista — क्रमबद्ध डायनेमिक कलेक्शन#

आरंभ {
    स्थिर सूची<संख्या> empty ← खाली
    स्थिर _ numbers ← [1, 2, 3, 4, 5]
    स्थिर _ names ← ["Marcus", "Julia", "Gaius"]
    स्थिर _ nested ← [[1, 2], [3, 4]]
}

फैलाओ के साथ स्प्रेड करें:

आरंभ {
    स्थिर सूची<संख्या> a ← [1, 2, 3]
    स्थिर सूची<संख्या> b ← [4, 5, 6]
    स्थिर _ combined ← [फैलाओ a, फैलाओ b]
    स्थिर _ headed ← [0, फैलाओ a, 99]
}

मुख्य तरीके: longitudo, accipe, appende, योग, primus, novissimus।

Tabula — कुंजी-मान मैप#

आरंभ {
    स्थिर तालिका<पाठ, संख्या> scores ← { "alice": 10, "bob": 20 }
}

Tensor — घना निश्चित-आकार बफ़र#

आरंभ {
    स्थिर टेंसर<f32, []> scalar ← खाली
    स्थिर टेंसर<संख्या, [4]> row ← [1, 2, 3, 4] ↦ टेंसर<संख्या, [4]>
    स्थिर संख्या ∪ शून्य_मान first ← row[0]
}

Tensor शुगर (संख्यात्मक कोड के लिए):

आरंभ {
    स्थिर tf32[] seed ← खाली
    स्थिर tf32[4] lanes ← seed.समतल_से_बनाओ([1.0, 2.0, 3.0, 4.0], [4])
}

मुख्य तरीके: forma, accipe, ponde, crea, structa, strue, साथ ही तत्व-स्तरीय अंकगणित, मैट्रिक्स गुणन (multiplicatio) और रिडक्शन (योग, 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()
}

घने और विरल रूपों के बीच रूपांतरण:

आरंभ {
    स्थिर tf32[2, 2] dense ← [[1.0, 0.0], [0.0, 2.0]] ↦ टेंसर<f32, [2, 2]>
    स्थिर sf32[2, 2] sparse ← dense ↦ विरल<f32, [2, 2]>
    स्थिर tf32[2, 2] roundtrip ← sparse ↦ टेंसर<f32, [2, 2]>
}

Cursors — लेज़ी स्ट्रीम#

संकेतक<T> एक लेज़ी स्ट्रीम प्रकार है। इसे कलेक्शन इटरेटर, पाना व्यू या जनरेटर फ़ंक्शन से बनाया जाता है। इसका उपभोग दोहराओ सेवन के माध्यम से किया जाता है:

आरंभ {
    स्थिर _ 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 दस्तावेज़
`…`बाइटसंकलन-समय हेक्स बाइट्स
[ … ]सूची<T>Faber सूची लिटरल

स्ट्रिंग-टेम्पलेट अनुप्रयोग#

Faber स्ट्रिंग-टेम्पलेट अनुप्रयोग से पाठ को फ़ॉर्मैट करता है: पहले "…" या «…» लिटरल में § रिक्त-स्थान होते हैं, फिर कोष्ठक में तर्क दिए जाते हैं:

फलन greet(पाठ नाम) → पाठ {
    लौटाओ "Salve, §!"(नाम)
}

आरंभ {
    स्थिर संख्या pagina ← 3
    स्थिर संख्या totum ← 10
    स्थिर पाठ code ← "200"
    स्थिर पाठ label ← "OK"
    स्थिर _ msg ← "Page § of §"(pagina, totum)
    स्थिर _ block ← "status: § (§)"(code, label)
}

मुख्य नियम:

  • § (U+00A7) टेम्पलेट रिक्त-स्थान है
  • स्थितीय रिक्त-स्थान: स्पष्ट क्रम के लिए §0, §1, … का उपयोग करें
  • अंतिम ! प्रदर्शन फ़ॉर्मैटिंग चुनता है: "Salve, §!"(नाम)
  • (args) प्रत्यय टेम्पलेट अनुप्रयोग है, फ़ंक्शन कॉल नहीं

ब्लॉक स्ट्रिंग#

बहुपंक्ति ब्लॉक गिलेमे «…» का उपयोग करते हैं:

आरंभ {
    स्थिर _ sql ← «
        select id, email
        from accounts
    »
}

कैप्चर किए गए टेम्पलेट (forma)#

बैकटिक टेम्पलेट पाठ और पैरामीटर को रेंडर किए बिना कैप्चर करते हैं। बाउंड SQL/URL पेलोड के लिए ये सुरक्षित हैं:

आरंभ {
    स्थिर संख्या user_id ← 42
    स्थिर _ query ← `select * from users where id = §`(user_id)
}

इनलाइन JSON#

सादा { … } इनलाइन JSON है: यह संकलन-समय का json दस्तावेज़ है, अनाम Faber ऑब्जेक्ट नहीं। कुंजियाँ उद्धृत स्ट्रिंग होती हैं और : से अलग की जाती हैं:

आरंभ {
    स्थिर _ empty ← {}
    स्थिर _ user ← { "name": "Marcus", "age": 30, "active": true }
    स्थिर _ nested ← { "meta": { "version": 1 }, "tags": ["alpha", "beta"] }
}

टाइप किए गए वर्ग निर्माण के लिए, प्रकार का नाम और = फ़ील्ड संरचना का उपयोग करें:

वर्ग Point {
    स्थिर संख्या x
    स्थिर संख्या y
}

आरंभ {
    स्थिर _ p ← Point { x = 10, y = 20 }
}

Nullability and optionality#

Faber किसी मान में अनुपस्थिति और घोषणा स्थल पर वैकल्पिक प्रावधान के बीच भेद करता है।

नलनीय मान — T ∪ शून्य_मान#

जब मान अनुपस्थित हो सकता है, तब T ∪ शून्य_मान का उपयोग करें:

फलन find(पाठ key) → संख्या ∪ शून्य_मान {
    लौटाओ शून्यवत्
}

फलन divide(संख्या a, संख्या b) → संख्या ∪ शून्य_मान {
    यदि b ≡ 0 अतः लौटाओ शून्यवत्
    लौटाओ a / b
}

वैकल्पिक घोषणा स्लॉट — स्वेच्छा#

जब कोई पैरामीटर या फ़ील्ड कॉलर या कंस्ट्रक्टर द्वारा छोड़ा जा सकता हो, तब नाम के बाद स्वेच्छा का उपयोग करें:

फलन connect(पाठ host, संख्या port स्वेच्छा) → रिक्त {
}

वर्ग User {
    स्थिर पाठ email स्वेच्छा
}

उधार-चिह्न वैकल्पिक पैरामीटरों के साथ संयोजित किए जा सकते हैं:

फलन process(से संख्या depth स्वेच्छा) → रिक्त {
}

नल-रहित अभिकथन — !#

किसी नलनीय मान के शून्य_मान न होने का अभिकथन करने के लिए !., ![, !( का उपयोग करें:

वर्ग Box {
    स्थिर संख्या ∪ शून्य_मान val
}

आरंभ {
    स्थिर Box ∪ शून्य_मान maybe_name ← Box { val = 7 }
    स्थिर _ name ← maybe_name!.val
}

शून्य_मान पर नल-रहित अभिकथन रनटाइम पर प्रोग्राम को रोक देता है।

नलिश सहसंयोजन — vel#

आरंभ {
    स्थिर पाठ ∪ शून्य_मान provided ← शून्यवत्
    स्थिर _ name ← provided डिफ़ॉल्ट "default"
}

अज्ञात#

अज्ञात एस्केप हैच और अधूरी जानकारी के लिए शीर्ष-स्तरीय अज्ञात प्रकार है। यह नलनीयता की कोई व्यवस्था नहीं है।

Conversion and construction#

रनटाइम और कंपाइल-टाइम के लिए दो महत्वपूर्ण रूपांतरण ऑपरेटर:

# runtime बदलें
आरंभ {
    स्थिर _ parsed ← "42" ↦ संख्या ⊥ 0
    # static ascription
    स्थिर संख्या value ← 7
    स्थिर _ text ← value ∷ पाठ
}

रनटाइम रूपांतरण — ↦#

रनटाइम रूपांतरण के लिए ↦ का उपयोग करें, विशेष रूप से ऐसी पार्सिंग या कोअर्शन के लिए जो विफल हो सकती है। ⊥ के साथ इनलाइन रिकवरी दें:

आरंभ {
    स्थिर पाठ input ← "9"
    स्थिर _ n ← "42" ↦ संख्या ⊥ 0
    स्थिर _ safe ← input ↦ संख्या ⊥ 0
}

टाइप-निर्देशित मटेरियलाइज़ेशन:

आरंभ {
    स्थिर पाठ path ← "/etc/hosts"
    स्थिर _ lanes ← [1.0, 2.0, 3.0, 4.0] ↦ सदिश<f32, 4>
    स्थिर _ body ← सेवा 'solum:lege' (path) ↦ पाठ
}

स्थिर प्रकार-निर्देशन — ∷#

स्पष्ट स्थिर प्रकार-निर्देशन के लिए ∷ का उपयोग करें। यह पोस्टफ़िक्स होता है और लक्ष्य-प्रकार द्वारा निर्देशित होता है:

आरंभ {
    स्थिर संख्या value ← 7
    स्थिर _ x ← 7 ∷ i32
    स्थिर _ text ← value ∷ पाठ
}

नलिश कोअलेसिंग — vel#

जब कोई मान शून्य_मान हो, तब नलिश कोअलेसिंग के लिए डिफ़ॉल्ट का उपयोग करें:

आरंभ {
    स्थिर पाठ ∪ शून्य_मान provided_name ← शून्यवत्
    स्थिर _ name ← provided_name डिफ़ॉल्ट "default"
}