Module 动态需要与Racket中当前模块路径相关的模块(或如何在Racket中找到当前模块路径)

Module 动态需要与Racket中当前模块路径相关的模块(或如何在Racket中找到当前模块路径),module,racket,Module,Racket,如果我想在运行时选择性地需要一个模块,我可以使用[dynamic require”。如果我想需要一个已安装的软件包,这非常有用,例如: (dynamic-require 'racket/match 'match) #lang racket (require racket/runtime-path) (define-runtime-path eat "eat.rkt") (dynamic-require eat 'bite) 这将(前提是我安装了racket/match),需要racket/m

如果我想在运行时选择性地需要一个模块,我可以使用[
dynamic require
”。如果我想需要一个已安装的软件包,这非常有用,例如:

(dynamic-require 'racket/match 'match)
#lang racket
(require racket/runtime-path)
(define-runtime-path eat "eat.rkt")
(dynamic-require eat 'bite)
这将(前提是我安装了
racket/match
),需要
racket/match
,并评估该库中的
match
绑定

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

#lang racket ;; eat.rkt
(provide bite)
(define (bite) "Nom nom")
现在,假设我们想要制作一个
午餐.rkt
模块,该模块需要
eat.rkt
,并调用该函数。此外,假设我将它们放在同一个目录中:

#lang racket ;; lunch.rkt
(require "eat.rkt")
(bite) ; => Nom Nom
这很好,因为我使用了静态require,但是当我想执行
动态require时,它就不起作用了:

#lang racket ;; lunch2.rkt
(define bite (dynamic-require "eat.rkt" 'bite)
(bite) ; => Nom Nom
虽然这看起来很好,但事实证明,
dynamic require
所需的模块不是基于模块的路径而必需的,而是on。因此,如果我在定义了模块的目录中运行程序,这很好,但是如果我在另一个目录中,一切都会中断:

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

显然,如果我知道当前目录在哪里,我可以将其更改为该模块的目录。但是如果我不知道该模块的路径,有没有办法获取它?或者,更直接地说,是否可以相对于所需的模块路径来
动态需求
模块?

这是
动态需求的最简单方法相对于当前模块路径(即保存模块的路径)的模块将获取该模块路径并将其附加到相对模块

您可以使用and来执行此操作。(您可能还希望用于其他情况,但我们在这里不这样做。)组合这两个函数将为我们提供一个要定义的模块的
模块路径索引?
。(或者通常是
#%变量引用所来自的模块。)

因此,我们可以使用如下变量:

(define here (variable-reference->module-path-index (#%variable-reference)))
现在剩下的就是在这里用我们想要的模块的相对路径组成这个
路径。如果您愿意,我们正在寻找
构建路径的模块路径类比

事实证明,我们正在寻找的函数是:,它接受一个基本路径和一个相对路径,并将它们附加在一起。结果类似于:

(module-path-index-join "eat.rkt" here)
(是的,它与您从
构建路径
中所期望的相反,但是对于这个函数,基本路径排在第二位。)

生成的模块,
3.rkt
如下所示:

#lang racket
(define here (variable-reference->module-path-index (#%variable-reference)))
(define bite (dynamic-require (module-path-index-join "eat.rkt" here) 'bite))
现在,
3.rkt
将需要
eat.rkt
相对于其定义的位置,而不是基于当前目录

$ racket lunch3.rkt
"Nom Nom"
$ cd snacks/
$ racket ../lunch3.rkt
"Nom Nom"
感谢Matthew Flatt对此问题的帮助。

该表单定义了一个在运行时可用的路径,该路径独立于
当前目录。
。使用它来定义要动态要求的模块的路径,例如:

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

还有
define runtime module path index
,它(IIRC)也与
raco distribute
和朋友合作。可以确认,
define runtime module path index
的工作很有魅力。可能是在这个问题之后添加的?