Racket -D选项和球拍中的#ifdef

Racket -D选项和球拍中的#ifdef,racket,Racket,在C语言中,您可以使用选项进行编译,例如,-DPROMPT。然后,在文件中可以有#ifdef提示符,代码将在编译时转换以包含该块中的内容 球拍里有类似的东西吗?我尝试了racket--help,但没有看到任何有用的选项。使用环境变量在racket世界中公开外部值 是的,但它的工作原理与C语言略有不同。正如Alexis所说,Racket编译是半隐形的。然而,球拍回音系统中有一些工具可以做到这一点,其中最流行的就是 无论何时使用,只要愿意,您都在编写编译器插件。这与C之间的主要区别在于,在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工具配合使用,因为很难知道哪些代码已经编译或没有编译,以及哪些选项/标志被启用或禁用。