Scheme 将普通球拍头加载到当前顶级

Scheme 将普通球拍头加载到当前顶级,scheme,racket,Scheme,Racket,这里有一个简单的代码部分,我想在我编写的一些racket脚本中与大家分享。我不想(require..)它,但想在顶层运行它(公共代码包括对(当前命令行参数)的调用),等等,这是一个必需的模块不理解的(至少我不知道这是否可能) 我尝试(加载)它,但它不起作用,因为它是当前顶级上下文的一部分-我在加载上下文中得到一个未绑定标识符错误,该错误是在公共头中定义的定义 似乎我仍然不理解racket参考资料第14章的某些部分-我尝试了14.1(名称空间)和14.3(racket/load)的一些示例,但无法

这里有一个简单的代码部分,我想在我编写的一些racket脚本中与大家分享。我不想(require..)它,但想在顶层运行它(公共代码包括对(当前命令行参数)的调用),等等,这是一个必需的模块不理解的(至少我不知道这是否可能)

我尝试(加载)它,但它不起作用,因为它是当前顶级上下文的一部分-我在加载上下文中得到一个未绑定标识符错误,该错误是在公共头中定义的定义

似乎我仍然不理解racket参考资料第14章的某些部分-我尝试了14.1(名称空间)和14.3(racket/load)的一些示例,但无法使其工作

我遗漏了什么?我们如何才能让这样一个看似简单的案例起作用

编辑:以下是我案例中的一个示例:

这是header.rkt:

#lang racket/load

(define-for-syntax args (current-command-line-arguments))
(define-for-syntax PROTOTYPING (or
                            (= (vector-length args) 0)
                            (equal? (vector-ref args 0) "local")))

(define-syntax (if-prototyping stx)
  (syntax-case stx ()
    ((_ debug-expr non-debug-expr)
     (if PROTOTYPING
         #'debug-expr
         #'non-debug-expr))))

(if-prototyping
 (require (prefix-in "ci:" (file "/debugenvpath/utils.rkt")))
 (require (prefix-in "ci:" (file "/releaseenvpath/utils.rkt"))))

; arrange arguments
(define args (current-command-line-arguments))
(if-prototyping
 (set! args (if (= (vector-length args) 0)
                (vector "arg1")
                (vector (vector-ref args 1))))
 #t)
这是一个使用它的文件(我们称之为test.bat):

运行test.bat会在下面给出文件最后一行的错误:

args: unbound identifier in module in: args
更新2 好的,下面是我的方法的phase1(所谓的宏时间)和phase0(所谓的运行时)扩展的更新:

当所有内容都在一个文件中时,我可以在第1阶段(宏)中运行(当前命令行参数):

#lang racket

(define-for-syntax args (current-command-line-arguments))
(define-for-syntax PROTOTYPING (or
                                (begin
                                  (printf "phase1 expansion, args are: ~a\n" args)
                                  (= (vector-length args) 0))
                                (equal? (vector-ref args 0) "local")))
(begin-for-syntax 
  (printf "phase1, val for PROTOTYPING is: ~a\n" PROTOTYPING))

(define-syntax (if-prototyping stx)
  (syntax-case stx ()
    ((_ debug-expr non-debug-expr)
     (if PROTOTYPING
         #'debug-expr
         #'non-debug-expr))))

(if-prototyping
 (require (prefix-in "ci:" (file "./debug-env/util.rkt")))
 (require (prefix-in "ci:" (file "./release-env/util.rkt"))))

; arrange arguments
(define args (current-command-line-arguments))
(printf "phase0 expansion, args are: ~a\n" args)
(if-prototyping
 (set! args (if (= (vector-length args) 0)
                (vector "my-testing-arg-to-use-from-drracket")
                (vector (vector-ref args 1))))
 #t)

"util func call: "
(ci:f)
具有用于双重检查的util.rkt文件: 调试环境/util.rkt:

#lang racket
(provide f)
(define (f) (display "f from debug"))
#lang racket
(provide f)
(define (f) (display "f from release"))
发布env/util.rkt:

#lang racket
(provide f)
(define (f) (display "f from debug"))
#lang racket
(provide f)
(define (f) (display "f from release"))
这是测试运行的输出:

>test-commonheader.bat local arg1 arg2
phase1 expansion, args are: #(local arg1 arg2)
phase1, val for PROTOTYPING is: #t
phase0 expansion, args are: #(local arg1 arg2)
"util func call: "
f from debug

>test-commonheader.bat arg1 arg2
phase1 expansion, args are: #(arg1 arg2)
phase1, val for PROTOTYPING is: #f
phase0 expansion, args are: #(arg1 arg2)
#t
"util func call: "
f from release
现在的问题是,我不能将整个逻辑放在common-header.rkt文件中重复使用。我只是在阅读Racket Reference 3.2(导入和导出),我应该了解更多关于语法要求或直接到阶段级别并提供到阶段级别的内容。我在require和provide中(语法)有了一些进步,但还没有:/

更新3 似乎我太忙了,无法理解阶段级扩展,我又错过了基础知识。来自header和(require“header.rkt”)的一个简单的(提供如果原型化)实际上正在工作,但并不完美:(.Alex正确地建议require应该工作。我试图(提供语法如果原型化))但这不起作用,因为在导入模块的第0阶段使用了if原型

以下是最新的标题:

#lang racket

(provide if-prototyping)

(define-for-syntax args (current-command-line-arguments))
(define-for-syntax PROTOTYPING (or
                                (begin
                                  (printf "phase1 expansion, args are: ~a\n" args)
                                  (= (vector-length args) 0))
                                (equal? (vector-ref args 0) "local")))
(begin-for-syntax
  (printf "phase1, val for PROTOTYPING is: ~a\n" PROTOTYPING))

(define-syntax (if-prototyping stx)
  (syntax-case stx ()
    ((_ debug-expr non-debug-expr)
     (if PROTOTYPING
         #'debug-expr
         #'non-debug-expr))))

(if-prototyping
 (begin
   (require "debug-env/util.rkt")
   (provide (all-from-out "debug-env/util.rkt")))
 (begin
   (require "release-env/util.rkt")
   (provide (all-from-out "release-env/util.rkt"))))
在test-commonheader.bat中,我需要标题:

(require "header.rkt")
现在,一个新问题是header.rkt phase1定义运行了两次(这在本例中可能没问题-这就是为什么我接受Alex关于使用require的回答):

如果您需要在运行时使用,那么使用应该可以做到这一点。下面是一个简单的示例:

在common-code.rkt中:

#lang racket
(current-command-line-arguments)
(current-command-line-arguments (vector "helloo"))
#lang racket
(provide setup)
(define (setup)
  (println (current-command-line-arguments))
  (current-command-line-arguments (vector "helloo")))
#lang racket
(provide return-f-and-g)
(define (return-f-and-g)
  (define args (current-command-line-arguments))
  (define debug? (or (= (vector-length args) 0)
                     (equal? (vector-ref args 0) "debug")))
  (cond [debug?
         (local-require "debug.rkt")
         (values f g)]
        [else
         (local-require "non-debug.rkt")
         (values f g)]))
#lang racket
(provide f g)
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define debug-on-non-debug (if debug? "debug.rkt" "non-debug.rkt"))
(define f (dynamic-require debug-on-non-debug 'f))
(define g (dynamic-require debug-on-non-debug 'g))
#lang racket
(provide (all-defined-out))
(require "debug-or-non-debug-sig.rkt"
         "debug-unit.rkt"
         "non-debug-unit.rkt")
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define-values/invoke-unit (if debug? debug@ non-debug@)
  (import)
  (export debug-or-non-debug^))
在file.rkt中:

#lang racket
(require "common-code.rkt")
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(setup)
(current-command-line-arguments)
当file.rkt与命令行参数一起运行时,这些是我的参数,它会打印以下内容:

'#("these" "are" "my" "arguments")
'#("helloo")
(f 2)
3
(g 2)
4
3
4
当一个文件需要另一个文件时,它总是在另一个文件运行时运行,并且它的运行时效果(包括类似的内容)在运行时由另一个文件的代码看到。此外,类似的参数用于正在运行的当前脚本,而不是当前文件

或者,稍微好一点的方法是将公共代码作为函数,如下所示:

在common-code.rkt中:

#lang racket
(current-command-line-arguments)
(current-command-line-arguments (vector "helloo"))
#lang racket
(provide setup)
(define (setup)
  (println (current-command-line-arguments))
  (current-command-line-arguments (vector "helloo")))
#lang racket
(provide return-f-and-g)
(define (return-f-and-g)
  (define args (current-command-line-arguments))
  (define debug? (or (= (vector-length args) 0)
                     (equal? (vector-ref args 0) "debug")))
  (cond [debug?
         (local-require "debug.rkt")
         (values f g)]
        [else
         (local-require "non-debug.rkt")
         (values f g)]))
#lang racket
(provide f g)
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define debug-on-non-debug (if debug? "debug.rkt" "non-debug.rkt"))
(define f (dynamic-require debug-on-non-debug 'f))
(define g (dynamic-require debug-on-non-debug 'g))
#lang racket
(provide (all-defined-out))
(require "debug-or-non-debug-sig.rkt"
         "debug-unit.rkt"
         "non-debug-unit.rkt")
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define-values/invoke-unit (if debug? debug@ non-debug@)
  (import)
  (export debug-or-non-debug^))
在file.rkt中:

#lang racket
(require "common-code.rkt")
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(setup)
(current-command-line-arguments)
运行
时,这些是我的参数
也会打印出来

'#("these" "are" "my" "arguments")
'#("helloo")
通过这种方式,file.rkt可以更好地控制调用
(设置)
的时间和上下文,并且还可以将参数传递给函数(如果您将其修改为接受参数),如果您希望公共代码依赖于file.rkt中的某些内容,这将非常有用

更新 对于更新后的问题,真正的问题似乎是您希望根据命令行参数要求不同的文件。如果没有参数,或者如果第一个参数是
debug
,则需要文件的调试版本,如果第一个参数是任何其他参数,则需要fi的非调试版本乐

该文件的两个版本提供了具有相同目的的相同绑定,换句话说,它们具有相同的接口

功能 使用最少魔法的方法是让common-code.rkt提供一个函数,该函数返回调试或非调试版本的所有函数:

non-debug.rkt:

#lang racket
(provide f g)
(define (f x)
  (add1 x))
(define (g x)
  (* 2 x))
#lang racket
(provide f g)
(require (prefix-in - "non-debug.rkt"))
(define (f x)
  (printf "(f ~v)\n" x)
  (-f x))
(define (g x)
  (printf "(g ~v)\n" x)
  (-g x))
debug.rkt:

#lang racket
(provide f g)
(define (f x)
  (add1 x))
(define (g x)
  (* 2 x))
#lang racket
(provide f g)
(require (prefix-in - "non-debug.rkt"))
(define (f x)
  (printf "(f ~v)\n" x)
  (-f x))
(define (g x)
  (printf "(g ~v)\n" x)
  (-g x))
common-code.rkt:

#lang racket
(current-command-line-arguments)
(current-command-line-arguments (vector "helloo"))
#lang racket
(provide setup)
(define (setup)
  (println (current-command-line-arguments))
  (current-command-line-arguments (vector "helloo")))
#lang racket
(provide return-f-and-g)
(define (return-f-and-g)
  (define args (current-command-line-arguments))
  (define debug? (or (= (vector-length args) 0)
                     (equal? (vector-ref args 0) "debug")))
  (cond [debug?
         (local-require "debug.rkt")
         (values f g)]
        [else
         (local-require "non-debug.rkt")
         (values f g)]))
#lang racket
(provide f g)
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define debug-on-non-debug (if debug? "debug.rkt" "non-debug.rkt"))
(define f (dynamic-require debug-on-non-debug 'f))
(define g (dynamic-require debug-on-non-debug 'g))
#lang racket
(provide (all-defined-out))
(require "debug-or-non-debug-sig.rkt"
         "debug-unit.rkt"
         "non-debug-unit.rkt")
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define-values/invoke-unit (if debug? debug@ non-debug@)
  (import)
  (export debug-or-non-debug^))
file.rkt:

#lang racket
(require "common-code.rkt")
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(setup)
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(define-values [f g]
  (return-f-and-g))
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
但是,如果debug.rkt和non-debug.rkt提供了许多函数,则必须在common-code.rkt中枚举所有函数两次,并在使用它们的每个文件中枚举一次

动态要求
功能 另一种方法是使用。它在common-code.rkt中的用法如下:

#lang racket
(current-command-line-arguments)
(current-command-line-arguments (vector "helloo"))
#lang racket
(provide setup)
(define (setup)
  (println (current-command-line-arguments))
  (current-command-line-arguments (vector "helloo")))
#lang racket
(provide return-f-and-g)
(define (return-f-and-g)
  (define args (current-command-line-arguments))
  (define debug? (or (= (vector-length args) 0)
                     (equal? (vector-ref args 0) "debug")))
  (cond [debug?
         (local-require "debug.rkt")
         (values f g)]
        [else
         (local-require "non-debug.rkt")
         (values f g)]))
#lang racket
(provide f g)
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define debug-on-non-debug (if debug? "debug.rkt" "non-debug.rkt"))
(define f (dynamic-require debug-on-non-debug 'f))
(define g (dynamic-require debug-on-non-debug 'g))
#lang racket
(provide (all-defined-out))
(require "debug-or-non-debug-sig.rkt"
         "debug-unit.rkt"
         "non-debug-unit.rkt")
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define-values/invoke-unit (if debug? debug@ non-debug@)
  (import)
  (export debug-or-non-debug^))
file.rkt:

#lang racket
(require "common-code.rkt")
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(setup)
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(define-values [f g]
  (return-f-and-g))
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
但是,这仍然存在枚举每个绑定并为每个绑定编写
(define f(dynamic require debug on non-debug'f))
行的问题

单位 我之前说过,这些方法中的每一种都是可能的,因为debug.rkt和non-debug.rkt提供了相同的接口。在racket中表达这一点的一种方法是使用。它们提供了一种方法,可以将这些内容打包成一级值,可以在运行时选择。它们有自己的接口概念,称为

您可以使用声明调试和非调试文件的接口。因此,在debug-or-non-debug-sig.rkt中,放置:

#lang racket/signature
f ; takes a number and adds 1 to it
g ; takes a number and multiplies it by 2
这定义了接口。最好还写注释,指定
f
g
做什么,它们取什么作为参数,返回什么,等等

然后,您必须声明调试和非调试文件实现该接口。您可以使用和表单来实现该接口

non-debug-unit.rkt:

#lang racket/unit
(require "debug-or-non-debug-sig.rkt")
(import)
(export debug-or-non-debug^)
(define (f x)
  (add1 x))
(define (g x)
  (* 2 x))
#lang racket
(require "debug-or-non-debug-sig.rkt")
(import)
(export debug-or-non-debug^)
(define (f x)
  (printf "(f ~v)\n" x)
  (add1 x))
(define (g x)
  (printf "(g ~v)\n" x)
  (* 2 x))
debug-unit.rkt:

#lang racket/unit
(require "debug-or-non-debug-sig.rkt")
(import)
(export debug-or-non-debug^)
(define (f x)
  (add1 x))
(define (g x)
  (* 2 x))
#lang racket
(require "debug-or-non-debug-sig.rkt")
(import)
(export debug-or-non-debug^)
(define (f x)
  (printf "(f ~v)\n" x)
  (add1 x))
(define (g x)
  (printf "(g ~v)\n" x)
  (* 2 x))
然后,您可以在运行时使用表单选择这些文件中的哪一个

common-code.rkt:

#lang racket
(current-command-line-arguments)
(current-command-line-arguments (vector "helloo"))
#lang racket
(provide setup)
(define (setup)
  (println (current-command-line-arguments))
  (current-command-line-arguments (vector "helloo")))
#lang racket
(provide return-f-and-g)
(define (return-f-and-g)
  (define args (current-command-line-arguments))
  (define debug? (or (= (vector-length args) 0)
                     (equal? (vector-ref args 0) "debug")))
  (cond [debug?
         (local-require "debug.rkt")
         (values f g)]
        [else
         (local-require "non-debug.rkt")
         (values f g)]))
#lang racket
(provide f g)
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define debug-on-non-debug (if debug? "debug.rkt" "non-debug.rkt"))
(define f (dynamic-require debug-on-non-debug 'f))
(define g (dynamic-require debug-on-non-debug 'g))
#lang racket
(provide (all-defined-out))
(require "debug-or-non-debug-sig.rkt"
         "debug-unit.rkt"
         "non-debug-unit.rkt")
(define args (current-command-line-arguments))
(define debug? (or (= (vector-length args) 0)
                   (equal? (vector-ref args 0) "debug")))
(define-values/invoke-unit (if debug? debug@ non-debug@)
  (import)
  (export debug-or-non-debug^))
file.rkt:

#lang racket
(require "common-code.rkt")
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(setup)
(current-command-line-arguments)
#lang racket
(require "common-code.rkt")
(define-values [f g]
  (return-f-and-g))
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
#lang racket
(require "common-code.rkt")
(f 2)
(g 2)
如果file.rkt在运行时没有命令行参数,或者第一个参数是
debug
,它会打印以下内容: