Macros 诡计';球拍中的程序来源?

Macros 诡计';球拍中的程序来源?,macros,scheme,racket,Macros,Scheme,Racket,racket是否具有类似guile程序源函数的功能,例如: (定义(加上一个x)(+1个x)) (程序源加一)-->(引用(+1 x)) 我正在尝试为初学者制作一个类似于调试工具的东西,在这个工具中,当他们在2htdp/universe中处理某个特定函数的行为时,他们可以看到该函数的部分或完整评估。所以我可以在这个例子中使用宏,除了在他们的程序中,我仍然希望定义看起来像往常一样,所以我不能让他们先引用它,然后再评估它,除非我重新定义define。。。这可能没问题,但我很想知道如何最好地做到这一点

racket是否具有类似guile程序源函数的功能,例如:

(定义(加上一个x)(+1个x))
(程序源加一)-->(引用(+1 x))


我正在尝试为初学者制作一个类似于调试工具的东西,在这个工具中,当他们在2htdp/universe中处理某个特定函数的行为时,他们可以看到该函数的部分或完整评估。所以我可以在这个例子中使用宏,除了在他们的程序中,我仍然希望定义看起来像往常一样,所以我不能让他们先引用它,然后再评估它,除非我重新定义define。。。这可能没问题,但我很想知道如何最好地做到这一点。

我做过这样的事情:

(provide (rename-out (def/help define)
                     (define-syntax/help define-syntax))
         help)

(define-syntax def/help
  (syntax-rules ()
    ((_ name description signature (λ(vs ...) exps ...))
     (begin
       (add-help! 'name description 'signature '(λ(vs ...)))
       (define name (λ(vs ...) exps ...))))))
...
> (require "working.ss")
> (define (plus a b) (+ a b))
X define: bad syntax in: (define (plus a b) (+ a b))
> (define plus
    "Add two numbers"
    (int int -> int)
    (λ(a b) (+ a b)))
> (help plus)
plus
Add two numbers
(int int -> int)
(λ (a b))

(一些肉不见了,只是给出了一个想法。)它不是如图所示的超级健壮,但这就是你所倾向的方向吗?

这就是我的结论:

(提供(重命名(定义/保存源定义))过程源)

然后在身体里

(define *procedure-name-hash* (make-hash))  
(define *procedure-source-hash* (make-hash))  
(define (save-source! fn name body)  
   (hash-set! *procedure-name-hash* fn name)
   (hash-set! *procedure-source-hash* fn body))

(define (procedure-name fn)
  (hash-ref *procedure-name-hash* fn false))
(define (procedure-source fn)
  (hash-ref *procedure-source-hash* fn false))

(define-syntax define/save-source
  (syntax-rules ()
    ((_ (name formals ...) body-expressions ...)
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name (λ(formals ...) body-expressions ...))
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name value)
     (define name value))))
在答复中:

> (define/save-source (plus-one x) (+ 1 x))
> (procedure-source plus-one)
(λ (x) (+ 1 x))
> (plus-one 3)
4
> 
奇怪的是,在我收到的学生回复中:

> (procedure-source update-target)
(cons 'λ (cons (cons 'x empty) (cons (cons '+ (cons 'x (cons 20 empty))) empty)))
> (update-target 30)
function call: expected a defined function name or a primitive operation name after an open parenthesis, but found something else

您遇到的问题是由于初学者的语言限制:通常,高阶函数是语言中的语法错误,因为初学者还不应该知道它们

有一种方法可以选择退出。通过使用,您的过程源可以被标记为此限制的例外之一,特别是为了与BSL合作

以下是使用它时您的库的外观:

#lang racket/base
(require lang/prim
         racket/bool
         (for-syntax racket/base))

(provide define/save-source)
(provide-higher-order-primitive procedure-name (fn))
(provide-higher-order-primitive procedure-source (fn))


(define *procedure-name-hash* (make-hash))  
(define *procedure-source-hash* (make-hash))  
(define (save-source! fn name body)  
   (hash-set! *procedure-name-hash* fn name)
   (hash-set! *procedure-source-hash* fn body))

(define (procedure-name fn)
  (hash-ref *procedure-name-hash* fn false))
(define (procedure-source fn)
  (hash-ref *procedure-source-hash* fn false))

(define-syntax define/save-source
  (syntax-rules ()
    ((_ (name formals ...) body-expressions ...)
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name (λ(formals ...) body-expressions ...))
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name value)
     (define name value))))

使用此选项的BSL程序应该能够很好地使用过程名称和过程源。

您的想法是正确的。但首先,我必须问:你试过DrRacket的步进机吗?它能满足你的所有要求,还有一些。不完全是所有的:给你背景,这是为了在屏幕上教授Bootstrap?功能——仅仅在屏幕上一步一步地看是不够的?这是真的。当你在游戏中移动角色时,你想在屏幕上看到角色的行为。当函数在宇宙中显示其行为时,对于您当前在宇宙中看到的值,以及当您跨过“屏幕”的边界时,能够看到评估的变化,这是非常关键的一部分。非常奇怪,可能是它自己的错误。我试图提醒自己步进机的不良行为到底是什么,对于运行正常的程序,它说,“默认加载处理程序:无法打开输入文件:”/Teachpacks/bootstrap teachpack.rkt“(没有这样的文件或目录;errno=2)”,使用绝对路径,相对路径应该是有序的。Bug?如果stepper产生的结果不是DrRacket(对于某些基线假设——它是受支持的语言,等等),那么它就是Bug。这看起来像11048()的错误吗?是的,看起来像是同一个错误,尽管这更普遍地表明相对路径被破坏,而不仅仅是同一个目录。如何添加帮助!帮助工作?谢谢,这正是我要找的东西!好的,我有一些代码,它们实际上适用于我的用例。它太长了,不能作为评论发布,所以我会用它来回答。再次感谢!还有,对于前两个语法规则条件,有什么方法可以使两个相同的实体干涸?是的。在一些包括我的模块的东西中,它是用模块语言或大多数其他语言编写的,这很好。问题似乎出在刚开始学习的学生语言上——可能已经有类似的语言了,而我的语言与之冲突。有人知道怎么打得好吗?丹尼,你太棒了。谢谢!:-)