SML/NJ中如何基于导入者相对路径引入其他文件?
别担心,这个问题是SML入门时超常见的小坎,我来给你两个靠谱的解决办法,尤其是第一个,是SML/NJ官方推荐的标准做法,完全能避开你说的路径坑~
方法一:用Compilation Manager(CM)管理依赖(强烈推荐)
CM是SML/NJ专门用来处理多文件代码的工具,它会自动识别文件之间的相对位置,不管你从哪个目录运行脚本,都能准确找到依赖文件,根本不用纠结路径问题。
具体步骤:
整理你的代码文件
先把f1.sml里要共享的函数封装成一个结构(相当于其他语言里的模块),这样能明确哪些函数可以被外部调用:(* f1.sml *) structure F1 = struct fun add x y = x + y fun multiply x y = x * y -- 把你要在f2里用的所有函数都放在这个结构里 end然后在
f2.sml里直接引用这个结构就行,完全不用写use命令:(* f2.sml *) -- 直接用F1结构里的函数 val sum = F1.add 3 5 fun double num = F1.multiply num 2创建CM配置文件
在f1.sml和f2.sml所在的目录下,新建一个名为myproject.cm的文件,内容如下:Group is $/basis.cm f1.sml f2.sml end$/basis.cm是用来引用SML的标准库,必须加上;- 然后按依赖顺序列出你的文件(f1要放在f2前面,因为f2依赖f1)。
加载整个项目
不管你在哪个目录打开SML/NJ,只要运行下面的命令加载CM配置文件就行(写配置文件的相对路径,如果是当前目录就直接写文件名):CM.make "path/to/myproject.cm";这样CM会自动编译所有依赖文件,你就能正常使用f1里的函数了,完全不用管路径问题~
方法二:临时调整use的路径(不推荐长期用)
如果暂时不想用CM,也可以用一个小技巧让use找到正确的f1路径,但这个方法比较hack,局限性大,适合临时测试:
(* f2.sml *) -- 获取当前f2.sml文件的路径 val f2FilePath = case SMLofNJ.getArgs () of [path] => path | _ => raise Fail "无法获取f2.sml的路径" -- 构造f1.sml的相对路径 val f1FilePath = OS.Path.joinDirFile {dir = OS.Path.dir f2FilePath, file = "f1.sml"} -- 加载f1.sml val _ = use f1FilePath; -- 现在可以用f1里的函数了 val sum = add 3 5
注意这个方法需要你运行f2.sml的时候把它的路径作为参数传入,比如在终端里执行:
sml f2.sml
但如果是从其他脚本导入f2,这个方法可能还是会出问题,所以还是更推荐用CM。
为啥use会有路径问题?
其实use命令的路径是相对于SML/NJ进程的当前工作目录,而不是f2.sml所在的目录。所以当你从其他地方导入f2时,工作目录变了,自然就找不到f1了。而CM是根据文件之间的相对位置来解析依赖的,所以完全不会有这个问题~
内容的提问来源于stack exchange,提问作者leolovesai

