0

我们称这个函数为“动态定义”。

基本上我想编写一个像这样工作的宏或 lambda:

$ (dynamic-define "variable" 123)
$ variable
$ => 123

我尝试过这个:

(define-syntax dynamic-define
    (syntax-rules ()
      ((_ string <body>)
       (eval `(define ,(string->symbol string) <body>)))))

它按预期工作,但似乎不是一个好的解决方案。

我尝试在没有 eval 的情况下使用:

(define-syntax dynamic-define                                           
    (syntax-rules ()                                                            
      ((_ string <body>)                                                        
       (define (string->symbol string) <body>))))

但是当我尝试使用时,我得到了这个错误:

Error: invalid syntax (define (string->symbol "variable") 123)

我应该怎么办?

(请:编辑此问题以适合母语英语并请删除此行)

4

2 回答 2

2

您遇到了一个基本问题:您无法以“干净”的方式进行真正的动态定义,因此您尝试使用eval. 请注意,上面的两个解决方案都不是动态的——它们给你的只是写的能力,"foo"而不是foo. 正如我在其他地方所说,使用eval通常很糟糕,在这种情况下更糟,因为它eval是从宏中使用的,这使得它非常奇怪。这是除了在你的宏中有一个隐式的准引号之外,它会让事情变得更加混乱。您也可以将整个事物定义为普通函数:

(define (dynamic-define string <body>)
  (eval `(define ,(string->symbol string) ,<body>)))

如果你真的需要它来工作,那么最好退后一步,想想你到底需要什么。一方面,上述解决方案不是动态的,因为它们需要使用带有字符串语法的宏

(dynamic-define "foo" 123) ; instead of (define foo 123)

但是如果有一个真正的动态定义,它会是什么样子呢?您可能希望这样定义b

(define a "b")
(dynamic-define a 123)

但是当您考虑它如何与其他绑定交互时,这只会变得更加混乱。例如:

(define y 123)
(define (foo s)
  (define x 456)
  (dynamic-define s 789)
  (+ x y))

现在,假设它dynamic-define做了你想做的事情,想想你会得到什么(foo "x")and (foo "y")。更糟糕的是,考虑(foo "s")(foo "+")。更糟糕的是,那又如何

(foo (random-element '("x" "y" "s" "+" "define")))

? 显然,如果这确实做了一些动态定义,那么在不提前知道将用dynamic-define什么名称调用的情况下编写这段代码是没有意义的。foo如果无法理解,编译就会消失——但更重要的是,正确性(或者通常是代码的含义)会消失。

以我的经验,这种模式用哈希表和类似设备处理得更好。

于 2014-05-03T16:05:40.210 回答
1

使用define-macro

#> (define-macro (dynamic-define varstr val)
      `(define ,(string->symbol varstr) ,val))

#> (dynamic-define "variable" 123)
#> variable
123

使用syntax-case

#> (define-syntax dynamic-define
     (lambda (stx)
       (syntax-case stx ()
         ((k varstr val)
          (with-syntax ([var (datum->syntax-object 
                              #'k
                              (string->symbol (syntax-object->datum #'varstr)))])
            #'(define var val))))))

#> (dynamic-define "variable" 123)
#> variable
123
于 2014-04-26T10:33:23.143 回答