动态重复一个模块相对于球拍中的当前模块路径(或如何在球拍中找到当前模块路径)

  • 本文关键字:模块 路径 动态 一个 相对于 module racket
  • 更新时间 :
  • 英文 :


如果我想在运行时选择一个模块,我可以使用[ dynamic-require'1。如果我想需要安装的软件包,例如:

(dynamic-require 'racket/match 'match)

这将(如果我安装了racket/match),需要racket/match并评估该库中的match

但是,当我想需要一个本地的非安装模块时,我会遇到麻烦。假设我有一些称为eat.rkt的模块,它提供了一个函数:bite

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

现在说,我们要制作一个需要eat.rktlunch.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

虽然这看起来不错,但事实证明,基于模块的路径而是current-directory所需的模块,而是在CC_11上。因此,如果我在目录中运行该程序,则可以定义模块,这很好,但是如果我在另一个目录中,一切都会破裂:

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

显然,如果我知道它在哪里,我可以将current-directory更改为该模块的目录。但是,如果我不知道这个模块的路径,有什么方法可以得到吗?或者,更直接地,相对于要求的模块路径,dynamic-require模块是否有可能?

define-runtime-path表单定义了一个路径,该路径将在运行时可用,并且独立于current-directory。使用它来定义要动态需要的模块的路径,例如:

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

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的模块路径类比。

事实证明,我们正在寻找的函数IS: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"

感谢Matthew Flatt帮助此答案。

最新更新