pyparsing實現(xiàn)letrec語法函數(shù)遞歸調(diào)用

前面使用let和proc,可以進行函數(shù)的定義,但是并不支持在函數(shù)內(nèi)部遞歸地調(diào)用改函數(shù),究其原因,是在函數(shù)調(diào)用時,即proc的body語句執(zhí)行的時候,它所引用的環(huán)境env,是在let語法中,擴展指向procedure的變量之前,所以在當時的env中,是沒有指向該函數(shù)的變量的。 本文使用letrec擴展語法,實現(xiàn)函數(shù)的遞歸調(diào)用。

代碼在https://github.com/wangdxh/eopl3-in-python ?letrec目錄下

letrec語法如下:

letrec 后跟著 函數(shù)的名稱,一對圓括號內(nèi)包含著函數(shù)的參數(shù)名稱,緊接著是 = 和 函數(shù)體,最后 in 和 要執(zhí)行的body語句。

pyparsing描述的語法

letrec解析的時候,函數(shù)的名稱,參數(shù),函數(shù)體,會直接解析出來,這里將函數(shù)的定義擴展進環(huán)境env,let+proc 擴展的時候通過procedure,將變量,body,“當時的環(huán)境”,通過閉包生成一個函數(shù),當這個函數(shù)體真正執(zhí)行的時候,所使用的env,生成函數(shù)時“當時的環(huán)境”+變量和其賦值的擴展。所以let聲明的指向函數(shù)的變量,并不在執(zhí)行的env中。

這里擴展進環(huán)境變量的時候,不用procedure生成一個閉包的函數(shù),而是把相應的函數(shù)名稱,參數(shù),和body擴展到環(huán)境中。

現(xiàn)在有2個向環(huán)境中擴展變量和其對應值的函數(shù)。

從環(huán)境中查找變量的時候,進行了調(diào)整,當發(fā)現(xiàn)查找的是letrec對應的函數(shù)名稱時,將其函數(shù)參數(shù),body,和正在查找的env(注意這個env很重要,這是最小包含著函數(shù)名稱的環(huán)境,相當于是letrec,將函數(shù)名稱擴展到環(huán)境中后的那個環(huán)境)放在一個list里面,原來的其他變量和單個對應值查找也進行了微調(diào),也放在list里,便于統(tǒng)一處理。

代碼中唯一用到查找變量的地方就是var_fun,這里針對變量的名稱,去查找對應的值,如果發(fā)現(xiàn)有3個元素的list,就是letrec定義的函數(shù),1個元素就是原來的處理。如果是letrec的信息,就使用proceduer函數(shù)生成一個閉包函數(shù),去執(zhí)行,和let一致,這里注意list內(nèi)的最后一個env,是最小的包含著letrec定義的函數(shù)名的環(huán)境。所以這個時候在函數(shù)調(diào)用的時候,在其環(huán)境中是包含著letrec定義的函數(shù)名的,借此來完成遞歸調(diào)用。

整個完成遞歸流程的處理點就是,生成procedure的時候,最后的env環(huán)境是包含著letrec定義的函數(shù)名的最小的環(huán)境集合。

下圖是一個測試一個數(shù)值是否為奇數(shù)的例子

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容