-D选项和Racket中的#ifdef

时间:2017-01-01 10:45:56

标签: racket

在C中,您可以使用选项编译,例如-DPROMPT。然后,在文件中,您可以拥有#ifdef PROMPT,并且代码将在编译时进行转换,以包含该块中的内容。

Racket中有类似的东西吗?我试过racket --help,但没有看到任何有用的选项。

2 个答案:

答案 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世界中了解外部值。

https://docs.racket-lang.org/reference/envvars.html