首页 文章

在Racket脚本中调用`racket`

提问于
浏览
6

General question:

我可以在正在运行的Racket脚本中调用当前的 racket 可执行文件吗?

基本上,在 (find-executable-path "racket") 没有返回我正在使用的Racket可执行文件的路径的情况下,我想要替换 (system "racket ...") .

Context:

我真正想要的是尝试编译一些表达式并断言它们会引发编译错误 . 这是用于单元测试 .

3 回答

  • 2

    我不相信你需要在这里走出可执行文件 . 试试这个:

    #lang racket
    
    (require syntax/modread)
    
    ;; define a namespace anchor to attach a namespace to:
    (define-namespace-anchor anchor)
    ;; define a namespace for expansion:
    (define target-namespace (namespace-anchor->namespace anchor))
    
    (define program-to-compile
      "#lang racket
    (+ 3 4)")
    
    ;; go ahead and expand
    (with-module-reading-parameterization
     (λ()
       (parameterize ([current-namespace target-namespace])
       (expand
        (read-syntax
         "bogus-filename"
         (open-input-string program-to-compile))))))
    

    当我说Racket在提供编译器以规范方式运行程序的能力方面非常干净时,我认为我是正确的 .

  • 4

    如果您的目标只是编译一些球拍表达式,那么只需使用compilecompile-syntax即可 . 示例文件将是:

    #lang racket
    (require rackunit)
    
    (define tests
      (list #'(+ 1 "3")
            #'(void void)
            #'(string-append 4)))
    
    (for/list ([t (in-list test)])
      (check-exn exn:fail?
         (lambda () (compile t))))
    

    exn:fail? 是您正在寻找的任何例外 .

    此外,如果您有一些常见的语法上下文,您想要运行测试,则可以使用 #``#,` . 所以你的代码最终会是这样的:

    #lang racket
    (require rackunit)
    
    (define tests
      (list #'(+ 1 "3")
            #'(void void)
            #'(string-append 4)))
    
    (for/list ([t (in-list test)])
      (check-exn exn:fail?
         (lambda () (compile #`(module anonymous racket
                                 #,t)))))
    

    最后,如果您的代码存储在您的计算机上,您可以使用John的解决方案,同时使用file->string将文件转换为字符串 .

  • 5

    对于小测试,您也可以使用 syntax/macro-testing 库中的convert-compile-time-error . 它将一个表达式导致编译时错误进入表达式,该表达式在计算时会引发运行时错误 . 表达式使用模块中出现的环境,包括本地绑定;你不必操作命名空间和 eval .

    (check-exn #rx"bad syntax"
                (lambda () (convert-compile-time-error (lambda))))
    

    还有 convert-syntax-error (在同一页面上) .

相关问题