最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

LoveString基礎(chǔ)

2022-08-13 03:45 作者:Fuxfantx  | 我要投稿

注意:我不打算實(shí)際構(gòu)建這門語言!

設(shè)計(jì)目標(biāo)

完全基于Dictionary、僅有String類型的語言,無敵炫酷的玩具。


先來個(gè)Hello World吧!

func init:

????print: "Hello World!"


從了解符號開始

  1. 兩種引號,[]圍住的部分為Key,""圍住的部分為Value;=作為賦值符號使用。

  2. #LF圍住的部分將被視為注釋。

  3. %為“Value化”符號,用于轉(zhuǎn)義和格式字符串。

    print: "%"%"" ?#""

    print: "My name is %s, welcome to learn %s%s." % "John""Love""String"

    # My name is John, welcome to learn LoveString.

  4. ()圍住的部分稱為優(yōu)先行,用于提高運(yùn)算優(yōu)先級,以及跨行書寫同一語句;優(yōu)先行會嘗試捕獲一個(gè)Value。

  5. Space用于分隔關(guān)鍵字。因此,各個(gè)關(guān)鍵字之間必須存在空格(除非換行)。

  6. LF用于分隔語句(即:每行代表一個(gè)語句),Tab用于表明代碼的局部級別。

  7. 要求以:作方法關(guān)鍵字的后綴,唯一例外是func:(定義一個(gè)匿名函數(shù))

=為從右向左結(jié)合,其余關(guān)鍵字全部為從左向右結(jié)合。


LoveString的字典

入手字典,先從KeyValue開始??梢院唵蔚匕?code>Key理解為變量名,Value理解為變量值,但實(shí)際上更為簡單。

一般的字典攜帶一系列的鍵值對鍵鍵對,現(xiàn)在我們來定義一個(gè)一般的字典:

root[My First Dictionary] = {

? ??[1] = "Love"

????[2] = "String"

}

root關(guān)鍵字代表對根字典進(jìn)行操作,后面我們會對根字典作出詳細(xì)的說明。

由于空格分詞,{不要換行;由于字典結(jié)束是一個(gè)單獨(dú)的語句,}需要換行。


添加鍵,刪除鍵

不存在的Key對應(yīng)的Value是"",即空字符串。因此:

  • 添加一個(gè)鍵,只需訪問一個(gè)不存在的鍵,然后賦值;

  • 刪除一個(gè)鍵,只需將一個(gè)存在的鍵賦為空值。

示例如下:

func init:

????root[my_new_key_1] = "Love"

????root[my_new_key_2] = "String"

????root[to_be_erased] = "Foobar"

????root[to_be_erased] = ""

????print: [undefined_key] ?#輸出一個(gè)空行


方法

方法是代碼段的封裝,可以用于支持外部語言、實(shí)現(xiàn)代碼復(fù)用、標(biāo)記程序入口等?,F(xiàn)在我們來定義一個(gè)一般的方法:

func my_method: [var1]

????[var2] = "String"

????print: ([var1] + [var2])

然后執(zhí)行它:

func init:

????my_method: "Love"

# LoveString

從定義過程中可以看出,方法包含一個(gè)自定義關(guān)鍵字、一個(gè)內(nèi)部字典和一系列的語句。以func開頭的行,將檢測第一個(gè)空格后的關(guān)鍵字名,并對第二個(gè)空格后的鍵進(jìn)行“導(dǎo)出”。

執(zhí)行方法時(shí),內(nèi)部字典從空字典開始,先將傳入的鍵/值寫入內(nèi)部字典,然后執(zhí)行其后的一系列語句。最后,把內(nèi)部字典全部置空。

使用return關(guān)鍵字能終結(jié)方法的執(zhí)行,并“導(dǎo)出”一個(gè)局部變量,這點(diǎn)與其它語言是一致的。

特別地,使用return_self可以保證方法“逐級蠶食”后面的方法,理解這點(diǎn)需要一些匿名函數(shù)的知識。


鍵名是靜態(tài)的

遇到這樣一個(gè)代碼段怎么辦?

func my_add_root: [sth]

????root[sth] = [sth]

答:將傳入的[sth]鍵/值寫入根字典的名為sth的鍵。

我們強(qiáng)烈不建議用動態(tài)鍵名擴(kuò)充字典,但真的想這么做的話,可以使用add家族的方法:

func my_dynamic_add: [name][value]

????add_root: [name][value]

????add_to: root[dynamicadds][name][value]


func init:

????my_dynamic_add: "my_new_key_1""Love"

????my_dynamic_add: "my_new_key_2""String"

????print: (root[my_new_key_1] + root[dynamicadds][my_new_key_2])


# LoveString

add_root方法取第一個(gè)參數(shù)的最終值作為鍵名,將第二個(gè)參數(shù)以引用形式存儲到根字典中。

add_to方法相較第一個(gè)方法在一開始多一個(gè)“目的地”。


默認(rèn)值參數(shù)

考慮LoveString“未定義即空”的特性,我們允許執(zhí)行方法時(shí)傳入任意項(xiàng)參數(shù),但需要注意賦值的目標(biāo)問題:

func 123: [1][2][3]

????root[1] = [1]

????root[2] = [2]

????root[3] = [3]


func init:

????123: "Love""String"

????print: (root[1] + root[2]) #LoveString

????print: (root[1] + root[3]) #Love

????123: "Love""""String"

????print: (root[1] + root[2]) #Love

????print: (root[1] + root[3]) #LoveString

????123: "Love""""""String" #在這里,"String"被忽略了

????print: (root[1] + root[2]) #Love

????print: (root[1] + root[3]) #Love

為此,我們提供一個(gè)小小的語法糖,方便定義函數(shù)的默認(rèn)值:

func 123: [1][2][3]

????default[1] = "Love "

????default[2] = "String "

????default[3] = "Forever"

????return ([1] + [2] + [3])

效果如下:

func init:

????print: (123:) ?#Love String Forever

????print: (123: "Love""String") ?#LoveString Forever

????print: (123: "Love""String""") ?#LoveString


傳入一個(gè)方法,還是一個(gè)值?

上一節(jié)中,您可能已經(jīng)注意到我們對于嵌套方法的處理方式了:總是用優(yōu)先行圍住先執(zhí)行并傳值的方法。

如果不這樣做會怎么樣?下面給出一個(gè)有趣的例子:

func sth_lambda: [1]

????print: "I am a Lambda!"

????print: [1]


func init:

????print: sth_lambda: "Not Ignored"


# ----------------?

# func sth_lambda: [1]?

# ????print: "I am a Lambda!"?

# ??? print: [1]?

# ----------------?

# Not Ignored

在此例子中:

我們向print:方法傳入了sth_lambda方法,于是print方法打印出了sth_lambda方法的定義,并返回了一個(gè)print:?匿名函數(shù)。

之后,新的print:匿名函數(shù)與字面量"Not Ignored"結(jié)合,于是打印出了一行"Not Ignored"語句。

怎么調(diào)用一個(gè)傳入的方法呢?這里也只需要使用優(yōu)先行:

func method_to_be_called:

????print: "Called"


func method_passer: [method]

????if ([method] isfunc) -> func:

????????([method]) #這樣書寫,傳入的方法就會被執(zhí)行

????????root[method] = [method]

????else -> return


func init:

????method_passer: method_to_be_called:

????(root[method])?

# Called

# Called

之后再展開講解程序的選擇與循環(huán)結(jié)構(gòu)。


傳入兩個(gè)方法,還是遵照傳遞性進(jìn)行運(yùn)算?

始終記住,分詞器依賴空格工作,方法的各個(gè)參數(shù)之間不用空格分割。

因此:

myfunc: func1:func2:?是向myfunc:傳入兩個(gè)方法;

myfunc: func1: func2:是向myfunc:傳入方法func1:,如果返回了方法,則向返回方法傳入func2:;否則func2:?將被無視。

print:在設(shè)計(jì)時(shí)同時(shí)支持return_self式的運(yùn)算符重載以及任意數(shù)量的可變參數(shù),因此print:后各個(gè)參數(shù)間寫空格與不寫空格等效。


值傳遞與引用傳遞(了解即可)

閱讀到這里就可以展開講解參數(shù)傳遞方式了。

LoveString對于“需要生成新值”的行為采取值傳遞,即傳遞字典的值;

對于其他行為,如賦值、函數(shù)傳參,則使用引用傳遞。

如何實(shí)現(xiàn)引用傳遞呢?這里將介紹我們的內(nèi)存模型。

程序初始狀態(tài)下存在一個(gè)root_map,存儲了Key的hash和字面量/字典的引用。賦值過程的流程如下:

  1. 判斷賦值動作是Key-Key型,Key-Value型,還是Key-Dict

  2. Key-Key型:對右側(cè)Key進(jìn)行hash處理,遍歷root_map來獲得該key對應(yīng)的引用;然后對左側(cè)key進(jìn)行hash處理,在root_map新增左側(cè)Key-hash的記錄;

  3. Key-Value型:開辟內(nèi)存寫入Value,然后在root_map新增一條記錄;

  4. Key-Dict型(將鍵與字典字面量綁定):為該字典字面量開辟submap,進(jìn)行Value寫入;root_map內(nèi)新增內(nèi)容為Key-Hash、submap引用的記錄。

每個(gè)Value和Submap均綁定一個(gè)引用計(jì)數(shù)。每個(gè)賦值動作均會導(dǎo)致對舊Value/Submap和新Value/Submap的引用計(jì)數(shù)變化與檢測。引用計(jì)數(shù)歸零時(shí),該Value/Submap會被釋放;Submap的釋放過程中,其內(nèi)各Value的引用計(jì)數(shù)均會減一。


循環(huán)引用問題(了解即可)

考慮如下的代碼段:

func init:

? ? root[A] = {

? ???? [sthB] = ""

????}

????root[B] = {

? ?????[sthA] = root[A]

????}

? ??root[A][sthB] = root[B]

這個(gè)代碼段將按以下順序工作:

  • root_map中新建A,然后構(gòu)建Submap(A),內(nèi)含的sthB指向空字符串。

  • root_map中新建B,然后構(gòu)建Submap(B),內(nèi)含的sthA對應(yīng)了Submap(A)的引用。

  • 修改Submap(A)中的sthB使包含對Submap(A)的引用。

這時(shí)兩個(gè)Submap彼此引用,導(dǎo)致引用計(jì)數(shù)無法歸零。為了解決這樣的循環(huán)引用問題,每個(gè)Map(root_map或Submap)會預(yù)先包含一個(gè)SubmapList供賦值時(shí)檢查。

循環(huán)引用的賦值時(shí)檢查僅在Debug模式工作。

檢查到循環(huán)引用時(shí),程序會形成一個(gè)斷點(diǎn)。請手動修復(fù)這樣的循環(huán)引用問題。


根字典

從了解符號開始一節(jié)中,提到了用func:?定義匿名函數(shù)的方法。現(xiàn)在我們可以對字典的定義作一點(diǎn)簡單的擴(kuò)充:

字典是一個(gè)記錄了一系列Key - Value引用的Map(root_map或Submap),Key是一個(gè)hash化的名稱,Value包含了對String字面量的引用、對Submap的引用、匿名函數(shù),三者之一。

到此,可以給出根字典的定義:

根字典是字典的超集。除了Key - Value關(guān)系表之外,根字典允許您使用func定義具名方法。因此,具名方法不能嵌套定義。此外,根字典自帶一個(gè)叫init:的虛方法,其在全局變量全部加載完成后自動執(zhí)行,作為程序入口而存在。

init:虛方法可以攜帶參數(shù)。

LoveString將每個(gè)程序文件視為一個(gè)根字典,沒有通過腳本新建根字典的方法。


運(yùn)算符

作為高級語言,總不能僅僅賦一堆值就完事了吧?

于是我們嘗試引入一些運(yùn)算符。在此提醒兩點(diǎn):

  • 運(yùn)算符是特殊的關(guān)鍵字,空格不能少!

  • 關(guān)鍵字出現(xiàn)結(jié)合失敗的情形時(shí),其后的關(guān)鍵字和元素都會被忽略。

上文介紹了%的兩種用法,在這里作出簡單的補(bǔ)充:

  • %% :形成一個(gè)百分號

  • %" : 形成一個(gè)引號

  • %n :換行

  • %t :Tab縮進(jìn)

  • %s :字符串替換符

  • 對%s作格式替換的例子:

    [sth] % "Value1"[Value2][Dict3](func4:)func5:func6:

    依次為:String字面量"Value1",[Value2]對應(yīng)的值,[Dict3]對應(yīng)Submap的文本輸出,方法func4:的值,func5:``func6:的定義。

接下來引入幾種布爾運(yùn)算符(優(yōu)先級上高下低左高右低):

  • ==?!=?:等值檢測

  • and?or?not:邏輯與/或/非

  • in:若前者為Key,后者對應(yīng)字典,且后者對應(yīng)的字典包含了該Key,則返回true。

    • 使用self訪問方法的內(nèi)部字典。

  • isstr``isdict?isfunc:類型判斷,分別對應(yīng)String/字典/函數(shù)

  • isroot:檢查根字典是否有對該字面量的引用

    • isroot_deep:檢查根字典及其子字典是否有對該字面量的引用(很慢)

對于布爾運(yùn)算符的返回值,作出如下約定:

  • 空字符串代表“非”,含內(nèi)容的字符串代表“是”(一般記錄為"true")

  • 關(guān)鍵字false代表“非“,true代表“是”

高級優(yōu)先行

高級優(yōu)先行是特殊的優(yōu)先行,是LoveString擴(kuò)展模塊的有力語法支撐。官方計(jì)劃維護(hù)以下幾種高級優(yōu)先行:

group()是字典結(jié)構(gòu)的語法糖:

root[current_color] = group("1.0""1.0""1.0""1.0")


# 相當(dāng)于

root[current_color] = {

? ??[1] = "1.0"

? ??[2] = "1.0"

????[3] = "1.0"

????[4] = "1.0"

}

此外,group()為方法提供了可變參數(shù)支持:

func grouped_function: group()

????for [i] in self -> func:

????????print: [i]

????return "That's all, thanks."


func init:

????print: (grouped_function: "LoveString""Mutable Amount of Arguments")


# LoveString

# Mutable Amount of Arguments

# That's all, thanks.

math()?會將傳入的Value全部轉(zhuǎn)成數(shù)字(失敗時(shí)則轉(zhuǎn)成0),并提供了一系列符合數(shù)學(xué)書寫習(xí)慣的表達(dá)式:

root[math_instance] = math( 3^2 + 6%5 + root(4)by(2) + exp(ln2) )


func init:

????print: root[math_instance]


# 14

注意:該高級優(yōu)先行使用了不同的分詞器,以盡可能符合正常數(shù)學(xué)表達(dá)式的書寫習(xí)慣。

duo()允許傳入兩個(gè)Value和一個(gè)高級運(yùn)算符(“先計(jì)算再賦值”運(yùn)算符,以及大小比較類運(yùn)算符),Value會被轉(zhuǎn)換為數(shù)字:

root[my_set] = duo( root[my_advanced_pass] = "5.0" )

root[my_set] = duo( root[my_set] += "1")

root[compare] = duo( root[my_set] > "5" )


func init:

????print: root[my_set]root[compare]


# 6.0

# true

在循環(huán)結(jié)構(gòu)中還會再介紹幾種高級優(yōu)先行。


匿名函數(shù)與“導(dǎo)向“算符

現(xiàn)在,我們掌握了了基于自定義關(guān)鍵字的方法。教程的一開始我們也透露了用func:關(guān)鍵字定義的匿名函數(shù),怎么把這兩種元素統(tǒng)一起來呢?

現(xiàn)在我們可以使用“導(dǎo)向”算符->?幫助我們完成此操作。“導(dǎo)向”算符用于向匿名函數(shù)傳參,并將具名方法等連接到匿名函數(shù)或優(yōu)先行:

root[myfunc] = func: [a][b][c]

????if ([d] in self) -> (print: [d])

????print: [a][b][c]

????if (not [c] in self) -> (print: "%n--String Lover)


func my_func: [d] -> root[myfunc]


func init:

????print: (root[myfunc] -> "Love""String""Forever")

????print:

????print: (my_func: "I""love""string""forever.")

# Love?

# String?

# Forever?

# --Srting Lover?


#?

# I?

# love?

# string?

# forever.

通過“導(dǎo)向”連接具名方法和匿名函數(shù)時(shí),具名方法的參數(shù)、匿名函數(shù)的參數(shù)都是內(nèi)部字典的Key。這允許你將匿名函數(shù)導(dǎo)向具名方法時(shí),要求具名方法傳入更多的參數(shù)。

從示例中還可以挖掘到我們設(shè)計(jì)的語法糖:具名方法“多出來”的參數(shù)可以流入導(dǎo)向的匿名函數(shù)內(nèi)。

注意:

  • 沒有匿名函數(shù)“導(dǎo)向”匿名函數(shù)的語法,“導(dǎo)向”的左側(cè)若是匿名函數(shù),則向匿名函數(shù)傳參。

  • 如果不導(dǎo)向具名方法的話,不裝入優(yōu)先行的匿名函數(shù)不會執(zhí)行。

  • LoveString禁止了具名方法執(zhí)行時(shí)導(dǎo)向參數(shù),以保證具名方法的統(tǒng)一性和分詞器設(shè)計(jì)的簡潔性。

結(jié)構(gòu)式

本節(jié)中,介紹程序設(shè)計(jì)中非常關(guān)鍵的選擇結(jié)構(gòu)及循環(huán)結(jié)構(gòu)。

先從結(jié)構(gòu)式開始:結(jié)構(gòu)式是形如condition -> callable的語句,callable允許無參關(guān)鍵字、具名方法、匿名函數(shù)及優(yōu)先行;為了降低語法復(fù)雜度,結(jié)構(gòu)式自身不能向callable傳入自定義參數(shù)。但是,我們可以給出一個(gè)“結(jié)構(gòu)式傳參”的示例:

root[arg_to_structureline] = func: [a][b][c]

????foo: [a][b]

????bar: [c]


func init:

????if (true) -> (root[arg_to_structureline] -> root[a]root[b]root[c])

選擇結(jié)構(gòu)的結(jié)構(gòu)式是if () -> callable。

強(qiáng)制要求用優(yōu)先行(包含高級優(yōu)先行)表示條件,以確保能捕獲到返回值。

我們深知匿名函數(shù)是一種相當(dāng)晦澀的設(shè)計(jì),因此大多數(shù)情況只需使用如下的寫法:

# 單行

func init:

????root[input] = receive_and_pause:

????if (root[input] == "hp+1") -> duo(root[hp] += 1)

????else -> return

????return_self


# 多行

func init: [sth]

????if ([sth] == "") -> func:

????????[sth] = "String"

????????[lover] = "Lover"

????????print: ([sth] + " " + [lover])


# 該多行示例的輸出結(jié)果(執(zhí)行時(shí)不傳參):String Lover

注意:結(jié)構(gòu)式不自帶字典,但匿名函數(shù)自帶字典!

來到while循環(huán),我們提供了while_true () -> callablebefore () -> callable兩種結(jié)構(gòu)式,見名知義。

for家族則更加常用一些,我們提供了以下幾種遍歷模式:

# 字典遍歷模式

for [i] in root -> func1:

for "sth" in root -> func2:

deepfor [i] in root -> func3:

deepfor "sth" in root -> func4:


# 高級優(yōu)先行模式

for "Values" in range("0""100") -> print:

for "Values" in ftb("0""100""10") -> print:

可以看出for家族的通式:for A in B -> callable。

其中,A如果是Key的話,會自動向“導(dǎo)向”的callable傳入一個(gè)Key;如果是Value的話,則傳入一個(gè)鍵名字面量。

字典遍歷模式中,B一般是指向字典的元素,以rootself居多,也可以是自定義字典。

????如果B部分是空字典的話,該循環(huán)被跳過。

????如果B部分是一個(gè)Value的話,for循環(huán)將會執(zhí)行一次,此時(shí)傳入的都是該Value。

對于高級優(yōu)先行模式,range()優(yōu)先行要求內(nèi)含兩個(gè)數(shù)字,左閉右開,效果如該例:

func init:

????for "Values" in range(0,2) -> print:?


# 0

# 1

ftb()是"from-to-by"的縮寫,ftb([A][B][C])表示從[A]開始(左閉),到[B]結(jié)束(右開),每次步進(jìn)[C]個(gè)單位,效果如該例:

func init:

????for "Values" in ftb("0""50""10) -> print:


# 0

# 10?

# 20?

# 30?

# 40?

deepfor比較少用,但可以把傳入的字典所包含的子字典一并遍歷。高級表達(dá)式模式中,fordeepfor完全等價(jià)。


在LoveString中運(yùn)用OOP思想

  • 通過多層次的字典設(shè)計(jì),可以實(shí)現(xiàn)面向?qū)ο蟮姆庋b性。

  • 通過編寫“模板”,可以形成實(shí)例,也可以完成繼承。例如:

    root[Templates][Character] = {

  • ? ??[HP] = "100"

  • ? ? [MP] = "75"

  • }

  • root[Templates][Wizard] = (

  • ? ? root[Templates][Character] + {

  • ? ? ? ??[MP] = "200"

  • ? ? ? ??[Skill] = "Magic"

  • ? ? }

  • )

    對于字典,+是合并運(yùn)算符,深拷貝右側(cè)字典,然后對左側(cè)字典順次賦值改鍵。

  • “成員變量私有化“

    子字典中加入[lock] = "true",[lock] = "before_addup"這樣的鍵值對,則只能通過向上一級的匿名函數(shù)傳參來訪問該子字典。

    僅在Debug模式起作用。

Congratulations!


LoveString基礎(chǔ)的評論 (共 條)

分享到微博請遵守國家法律
沅陵县| 万宁市| 津南区| 巴南区| 工布江达县| 金门县| 冕宁县| 衡南县| 普格县| 夏津县| 兰考县| 新化县| 延川县| 宁津县| 民权县| 湖南省| 内乡县| 玛纳斯县| 中江县| 隆德县| 宜昌市| 孟津县| 石阡县| 浦江县| 富阳市| 东乌珠穆沁旗| 麻阳| 益阳市| 肥西县| 任丘市| 永顺县| 上虞市| 清徐县| 顺昌县| 汽车| 樟树市| 大化| 青铜峡市| 锡林浩特市| 洮南市| 谷城县|