一般问题:
我能否在运行中的Racket脚本中调用当前的racket
可执行文件?
基本上,如果(find-executable-path "racket")
没有返回我当前使用的Racket可执行文件的路径,我想要一个替代(system "racket ...")
。
背景:
我真正想做的是尝试编译一些表达式,并断言它们会引发编译错误。这是为了单元测试。
一般问题:
我能否在运行中的Racket脚本中调用当前的racket
可执行文件?
基本上,如果(find-executable-path "racket")
没有返回我当前使用的Racket可执行文件的路径,我想要一个替代(system "racket ...")
。
背景:
我真正想做的是尝试编译一些表达式,并断言它们会引发编译错误。这是为了单元测试。
我认为您不需要在此处执行外部操作。尝试这样做:
#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在提供编译器以有条理的方式运行程序方面非常纯净时,我的观点是正确的。
compile
或者compile-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
将文件转换为字符串。
syntax/macro-testing
库的convert-compile-time-error
。它将导致编译时错误的表达式转换为在评估时引发运行时错误的表达式。该表达式使用模块中出现的环境,包括局部绑定;您不必调整名称空间和eval
。(check-exn #rx"bad syntax"
(lambda () (convert-compile-time-error (lambda))))
同一页还有convert-syntax-error
。
dr
是什么?) - Ben Greenmanfind-console-bin-dir
和find-exe
的。 - Ben Greenman