Racket -D选项和球拍中的#ifdef
在C语言中,您可以使用选项进行编译,例如,Racket -D选项和球拍中的#ifdef,racket,Racket,在C语言中,您可以使用选项进行编译,例如,-DPROMPT。然后,在文件中可以有#ifdef提示符,代码将在编译时转换以包含该块中的内容 球拍里有类似的东西吗?我尝试了racket--help,但没有看到任何有用的选项。使用环境变量在racket世界中公开外部值 是的,但它的工作原理与C语言略有不同。正如Alexis所说,Racket编译是半隐形的。然而,球拍回音系统中有一些工具可以做到这一点,其中最流行的就是 无论何时使用,只要愿意,您都在编写编译器插件。这与C之间的主要区别在于,在C中,您需
-DPROMPT
。然后,在文件中可以有#ifdef提示符
,代码将在编译时转换以包含该块中的内容
球拍里有类似的东西吗?我尝试了
racket--help
,但没有看到任何有用的选项。使用环境变量在racket世界中公开外部值
是的,但它的工作原理与C语言略有不同。正如Alexis所说,Racket编译是半隐形的。然而,球拍回音系统中有一些工具可以做到这一点,其中最流行的就是 无论何时使用,只要愿意,您都在编写编译器插件。这与C之间的主要区别在于,在C中,您需要在称为预处理器指令的半成品DSL中编写这些扩展,而在Racket中,您可以使用Racket的全部功能编写这些扩展 这意味着你在球拍中用来与外界对话的任何构造,你也可以在这里使用。Jens建议的一个例子是使用环境变量。但是,由于您明确要求具有传入参数的功能,因此可以使用模块,或者更好地使用模块,该模块为您解析命令行参数 作为如何工作的示例,以下文件将编译为显示符号
'build
,或'no-build
,具体取决于是否在命令行上传递了任何参数:
#lang racket
(require (for-syntax syntax/parse
racket/cmdline))
(define-syntax (arguments? stx)
(syntax-parse stx
[(_)
(if (null?
(command-line
#:args args
args))
#''no-build
#''build)]))
(arguments?)
与在这里使用if而不使用定义语法不同的是,在第一种情况下,这发生在编译时,而不是运行时
当您使用raco make
命令在与运行代码不同的时间编译代码时,这一点最为明显
首先,让我们尝试同时运行和编译:
$ racket example.rkt
'no-build
$ racket example.rkt an-argument
'build
但是,现在让我们在运行它之前,使用raco make
,尝试编译它:
$ raco make example.rkt
$ racket example.rkt
'build
在这里可以看到,即使我们没有向example.rkt
传递任何参数,它仍然返回'build
。这是因为当运行raco make
时,选择完全在编译时进行。对raco make
的调用有一个参数:文件example.rkt
,因此,它被编译后只显示'build
此操作可以通过删除已编译的文件来撤消:
$ rm compiled/example_rkt.*
然后重新运行示例:
$ racket example.rkt
'no-build
事实上,您甚至可以在编译后删除example.rkt
文件:
$ raco make example.rkt
$ rm example.rkt
$ racket example.rkt
'build
虽然一般情况下不要这样做,因为除非您在某个地方备份了源代码,否则您将无法再检索它
最后,如果您想使用与C中使用的完全相同的-D
语法,则有一个#:multi
选项,您可以使用该选项设置代码的编译方式
然而,正如最后一个注意事项,请注意编译racket文件与编译C文件的不同之处在于生成的zo
文件是瞬态的。它们只能在Racket VM的当前版本上工作,而且由于该版本经常更新(一年几次),因此您最好分发源代码。如果您想以类似于分发C二进制文件的方式混淆它,您也可以分发完全扩展的代码,但这是另一个问题的答案。因为Racket将编译视为一个不可见的阶段,必要时会自动发生(您可以使用raco make
强制预编译,但您仍然在源代码上运行racket
,并且在未编译的源文件上运行racket
将自动强制编译),我认为这个特性不能很好地与现有的Racket工具配合使用,因为很难知道哪些代码已经编译或没有编译,以及哪些选项/标志被启用或禁用。