球拍中的功能,如module->language-info
,module->imports
和module->exports
希望他們的模塊被聲明,但不一定被訪問或實例化。訪問,實例化和聲明模塊有什麼區別?
現在,dynamic-require
似乎有幾個選擇如何需要模塊,包括訪問和實例化。
這讓我想知道,聲明模塊,訪問模塊和實例化模塊有什麼區別?
球拍中的功能,如module->language-info
,module->imports
和module->exports
希望他們的模塊被聲明,但不一定被訪問或實例化。訪問,實例化和聲明模塊有什麼區別?
現在,dynamic-require
似乎有幾個選擇如何需要模塊,包括訪問和實例化。
這讓我想知道,聲明模塊,訪問模塊和實例化模塊有什麼區別?
聲明一個模塊就是這個模塊在當前命名空間的某個地方。這可以通過一個需求來完成,或者直接在代碼中寫出模塊。
模塊訪問並實例化是比較麻煩一些理解,並且可以被描述爲這樣:
模塊來訪運行階段電平1(宏/編譯時間碼),並沒有運行相級別0(運行時間代碼)。
模塊實例化運行相位0級代碼,但不運行相位1級代碼。現在
,棘手位,運行相平0的代碼,你必須有以前運行所有的更高水平的分階段的代碼,如果它沒有被編譯。但是,如果此模塊已被訪問(並編譯),它將不會再次運行階段1的代碼。
這可以被看作具有以下模塊,稱爲test.rkt
:
#lang racket
(require (for-meta 2 racket/base))
(displayln "phase 0")
(begin-for-syntax
(displayln "phase 1")
(begin-for-syntax
(displayln "phase 2")))
該模塊具有運行在相位0,相位1碼和相位2(用於宏膨脹階段宏擴展)。在每個階段中,它會打印出一行來指示階段正在運行。使用這個模塊,我們可以看到模塊何時被實例化。
現在,讓我們創建以下文件,該文件實例test.rkt
:
#lang racket
(dynamic-require "test.rkt" #f)
如果我們DrRacket運行此,輸出將類似於:
phase 2
phase 1
phase 0
現在,我們看到phase 0
因爲模塊正在被實例化。但是,在這種情況下,我們還會看到phase 2
和phase 1
,因爲模塊的語法階段必須實例化以運行phase 0
代碼。
但是,如果你再運行它(假設你已經編譯的文件緩存打開),您將獲得:
phase 0
在這種情況下,你只能看到phase 0
因爲phase 1
和更高的代碼已經已擴大。我們也可以給0
動態要求類似的結果。現在
,如果不是在0
或#f
傳遞給dynamic-require
,我們在(void)
過去了,給我們以下文件:再次
#lang racket
(dynamic-require "test.rkt" (void))
然後輸出將是(假設你有編譯緩存打開),看起來像:
phase 1
這是因爲宏觀層面(階段1)代碼這裏正在運行,而不是運行時(相位0)代碼。但如果我們對test.rkt
的微小變化,並再次將其保存(無效緩存),我們將得到:
phase 2
phase 1
這是因爲球拍不得不擴大phase 2
代碼,以便能夠運行phase 1
碼。現在,編譯的模塊緩存已經更新,如果您再次運行它,它只會輸出:
phase 1
最後,沒有(據我所看到的,請更新這一點,如果我錯了) ,任何直接使用dynamic-require
的方式都可以保證運行高於階段1的代碼。