2017-03-06 59 views
1

如果我想在運行時選擇性地需要模塊,我可以使用[dynamic-require'1。如果我想要求已安裝包這個偉大的工程,例如:dynamic-require模塊相對於Racket中的當前模塊路徑(或如何在Racket中找到當前模塊路徑)

(dynamic-require 'racket/match 'match) 

這將(提供我已經racket/match安裝),需要racket/match和評估的match該庫結合。

但是,當我想要一個本地的,未安裝的模塊時,我遇到了麻煩。比方說,我有一些模塊調用eat.rkt,它提供了一個功能:bite

#lang racket ;; eat.rkt 
(provide bite) 
(define (bite) "Nom nom") 

現在讓我們說,我們希望做一個lunch.rkt模塊需要eat.rkt,並調用函數。此外,讓我們假設我把它們放在同一個目錄下:

#lang racket ;; lunch.rkt 
(require "eat.rkt") 
(bite) ; => Nom Nom 

這是很好的,因爲我使用的靜態要求,但這種分崩離析的時候我想做一個dynamic-require

#lang racket ;; lunch2.rkt 
(define bite (dynamic-require "eat.rkt" 'bite) 
(bite) ; => Nom Nom 

雖然這似乎沒問題,事實證明dynamic-require所需的模塊不是基於模塊的路徑而是在current-directory上。所以,如果我在模塊定義的目錄運行程序,這很好,但如果我在別的目錄是,一切都打破:

$ racket lunch2.rkt 
"Nom Nom" 
$ cd snacks/ 
$ racket ../lunch2.rkt 
; default-load-handler: cannot open module file 

顯然,如果我我可能只是改變current-directory該模塊的目錄知道它在哪裏。但是如果我不知道這個模塊的路徑,有什麼辦法可以得到它嗎?或者更直接地說,是否有可能dynamic-require模塊相對於需求的模塊路徑?

回答

2

define-runtime-path表格定義了一條路徑,該路徑在運行時可用並且獨立於current-directory。使用它的路徑定義要動態地要求模塊,例如:

#lang racket 
(require racket/runtime-path) 
(define-runtime-path eat "eat.rkt") 
(dynamic-require eat 'bite) 
1

dynamic-require模塊相對於當前模塊路徑(也就是模塊保存路徑)的最簡單方法是獲取該模塊路徑並將其附加到相關模塊。

你可以用#%variable-referencevariable-reference->module-path-index來做到這一點。 (您也可以在其他情況下使用variable-reference->resolved-module-path,但我們不會在這裏完成。)編寫這兩個函數使我們能夠定義模塊module-path-index?。 (或者在一般情況下,模塊的#%variable-reference是從哪裏來的。)

因此,我們可以像一個變量:

(define here (variable-reference->module-path-index (#%variable-reference))) 

現在所有剩下的是撰寫與所涉及的相對路徑此here路徑我們想要的模塊。如果您願意,我們正在尋找build-path的模塊路徑類比。

事實證明,我們正在尋找的功能是:module-path-index-join,這需要一個基本路徑和一個相對路徑,並將它們附加在一起。其結果將類似於:

(module-path-index-join "eat.rkt" here) 

(是的,這是倒退的,你會從build-path期待什麼,但基本路徑來第二次實現此功能。)

產生的模塊,lunch3.rkt樣子:

#lang racket 
(define here (variable-reference->module-path-index (#%variable-reference))) 
(define bite (dynamic-require (module-path-index-join "eat.rkt" here) 'bite)) 

現在lunch3.rkt需要eat.rkt相對於它的定義在哪裏,不是基於current-directory

$ racket lunch3.rkt 
"Nom Nom" 
$ cd snacks/ 
$ racket ../lunch3.rkt 
"Nom Nom" 

謝謝馬修·弗拉特幫助解答這個問題。

+0

還有'定義的運行時模塊路徑 - index',其中(IIRC)也與'拉科distribute'合作和朋友。 –