在C中,您可以使用选项编译,例如-DPROMPT
。然后,在文件中,您可以拥有#ifdef PROMPT
,并且代码将在编译时进行转换,以包含该块中的内容。
Racket中有类似的东西吗?我试过racket --help
,但没有看到任何有用的选项。
答案 0 :(得分:2)
是的,但它与C中的有点不同。正如Alexis所说,球拍编辑是半隐形的。但是,Racket echo系统中有一些工具正是这样做的,最受欢迎的是errortrace
。
如果您愿意,只要您使用define-syntax
,就会编写一个编译器插件。这与C之间的主要区别在于,在C中,您需要在称为预处理器指令的半生不熟的DSL中编写这些扩展,在Racket中,您可以使用Racket的全部功能编写这些扩展。
这意味着您在Racket中使用的任何构造与外界交谈,您也可以在这里使用。一个例子,正如Jens所建议的那样是使用环境变量。但是,由于您明确要求传递参数的能力,您可以使用current-command-line-arguments
或更好的command-line
模块,它为您解析命令行参数。
作为其工作原理的示例,以下文件将编译为显示符号'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?)
这与在没有define-syntax
的情况下的if不同之处在于,在第一种情况下,这发生在 compile 时间,而不是在运行时间,可以这么说。
当您使用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
语法,command-line
有一个#:multi
选项,您可以使用该选项设置您希望代码的使用方式编译。
正如最后一点,请注意编译racket文件与编译C文件的不同之处在于生成的zo
文件是瞬态的。它们只适用于当前版本的Racket VM,并且由于它经常更新(一年多次),因此您最好不要分发源代码。如果您想以与分发C二进制文件类似的方式对其进行模糊处理,您还可以分发完全扩展的代码,但这可以解决另一个问题。
答案 1 :(得分:1)
使用环境变量在Racket世界中了解外部值。