1

我需要一些函数,其中包括定义一个新的全局符号。这样我就可以像这样使用它:

(define (func-prototype symbol value comment)
  (define symbol value) ; this should somehow be reformulated
  (format "~a=~a   !~a\n" symbol value comment))

(define string-list (map func-prototype
                         '((s1 1 "first value")
                           (s2 20 "second value")
                           (s3 300 "third value))))

并能够得到以下结果:

> string-list
'("s1=1  !first value\n"
  "s2=20  !second value\n"
  "s3=300  !third value\n")
> s1
1
> s2
20
> s3
300

这可以作为一个函数实现,还是只能在宏的帮助下实现?您能否建议任何可能的实现或至少提供一些可能有用的提示/参考?

4

3 回答 3

3

我会重新考虑一般方法,使其更简单。我的建议:定义一个全局哈希表并在函数内部添加绑定,例如:

(define value-map (make-hash))

(define (func-prototype symbol value comment)
  (hash-set! value-map symbol value)
  (format "~a=~a   !~a\n" symbol value comment))

像这样使用它:

(define string-list
  (map (lambda (lst)
         (apply func-prototype lst))
       '((s1 1   "first  value")
         (s2 20  "second value")
         (s3 300 "third  value"))))

string-list
=> '("s1=1   !first  value\n"
     "s2=20   !second value\n"
     "s3=300   !third  value\n")

在需要引用哈希表中的符号之一的地方,请执行以下操作:

(define (get key)
  (hash-ref value-map key))

(get 's1)
=> 1
(get 's2)
=> 20
(get 's3)
=> 300
于 2013-03-11T16:54:07.750 回答
2

首先,考虑您是否真的想要这样做,或者不同的解决方案(如哈希表)是否也可以工作。

您可以使用该过程通过反射和动态评估eval来做到这一点。

;; define-variable-with-value! : symbol any -> void
(define (define-variable-with-value! name value)
  (eval `(define ,name (quote ,value))))

quote很重要;否则,您可能会将重新解释为要评估的表达式。要查看差异,请考虑示例

(define-variable-with-value! 'x (list 'error "kaboom"))
于 2013-03-11T20:41:51.007 回答
2

一般来说,不可能以您描述的方式完成您想要完成的事情。您唯一的希望是将内容写入文件,然后load将该文件写入交互式会话。但即便如此。

在方案中,您不能引入顶级名称,例如您想要s1s2、 和s3,除非在顶级。为此,您可以将宏定义为:

>(define-syntax define-foo
  (syntax-rules ()
    ((_ name value)
     (define name value))))

>(define-foo s1 1)
<undefined>
> s1
1

如果您尝试在函数中使用该宏,这不是骰子,因为函数的主体必须以表达式结尾,并且任何定义形式(如上述宏将扩展成的形式)都将成为局部变量。那是:

(define (func-prototype name value comment)
   (define-foo name value)
   name)

>(func-prototype 's1 1 "com")
1
> s1
<error>

如果您的字符串列表是常量,您可以采用的一种方法是这样的:

> (define-syntax declare-variables
    (syntax-rules ()
      ((_ (name value comment) ...)
       (begin
         (define name value)
         ...))))

> (declare-variables (s1 1 "com") (s2 20 "com") (s3 300 "com"))
> s1
1

这样就完成了(我已经忽略了使用'comment')但是,正如我所说,需要一个编译时字符串列表。

您可能认为可行但行不通的一种可能性是eval用作:

   (eval '(define s1 1) (environment ...))

但 'eval' 仅适用于表达式,不适用于声明。这让我有可能回到“加载”。

于 2013-03-11T18:48:56.343 回答