【问题标题】:How can I unsplice a list of expression into code?如何将表达式列表拆分为代码?
【发布时间】:2012-11-18 14:27:12
【问题描述】:

我的项目有一个实验,基本上,我需要在代码中嵌入一些s-expression并使其运行,就像这样,

(define (test lst)
    (define num 1)
    (define l (list))
    `@lst) ; oh, this is not the right way to go.

  (define lst
    `( (define num2 (add1 num))
      (displayln num2)))

我希望test 函数在球拍代码中的test(lst) 之后:

(define (test lst)
    (define num 1)
    (define l (list))
    (define num2 (add1 num)
    (displayln num2))

我怎样才能在球拍中做到这一点?

更新 我想使用eval 或之前的问题的原因是我正在使用 Z3 球拍绑定,我需要生成公式(使用球拍绑定 API),然后我会在某个时候触发查询,那是我需要评估这些代码。 在我的情况下,我还没有想出其他方法...... 一个超级简单的例子是,想象一下
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))

我有一些模型来分析结构(所以我没有直接使用racketZ3),在每个分析点的过程中,我都会将程序中的数据类型映射到Z3类型中,并做出一些断言,

我会生成类似的东西:

  • 在分配现场,我需要制定以下公式:

    (smt:declare-fun arr_z3 () IntList)
    (define len (make-length 10))

  • 然后在数组设置站点,我将有以下断言并检查 3 是否小于长度

    (smt:assert (</s 3 (len arr_z3)))
    (smt:check-sat)

  • 最后,我将收集如上生成的公式,并将它们包装在能够触发 Z3 绑定的形式中,以将以下收集的信息作为代码运行:

    (smt:with-context
    (smt:new-context)
    (define len (make-length 10))
    (smt:assert (</s 3 (len arr_z3))) (smt:check-sat))

这是我能想到的超级简单的例子……有意义吗?
旁注。 Z3 Racket binding 在 5.3.1 版本上会因为某种原因崩溃,但它在 5.2.1 版本上大部分都可以工作

【问题讨论】:

  • 从这个加上你关于使用eval 的另一个问题stackoverflow.com/questions/13428091/…,听起来你想在运行时编写代码?你能帮助我们了解你想要做什么吗? eval 可能不是最好的方法。
  • @GregHendershott 问题中的编辑是否清楚?
  • 我只是快速浏览了github.com/sid0/z3.rkt/blob/master/examples/nqueens.rkt 的 Z3 包的 N-Queens 示例,我看不出有什么理由需要在这里使用语法级别的东西;为什么生成查询需要 eval?您能否提供一个超级简单的示例来说明您想要制定查询的方式?
  • @JohnClements 我更新了一个简单的示例来说明为什么以及如何需要生成公式并对其进行评估。
  • 我看到你交叉发布到球拍语言列表,我认为这是一个优秀的想法。我也会把你的解释拖到那里,我认为你会得到很好的反馈。

标签: scheme racket


【解决方案1】:

老实说,我不明白你到底想要达到什么目标。引用 N. Holm,Sketchy Scheme,第 4.5 版,p。 108:»准引用的主要目的是构建仅包含几个可变部分的固定列表结构«。我不认为 quasiquotation 会在您所针对的上下文中使用。

对于准引用的典型上下文,请考虑以下示例:

(define (square x)
  (* x x))

(define sentence
  '(The square of))

(define (quasiquotes-unquotes-splicing x)
  `(,@sentence ,x is ,(square x)))

(quasiquotes-unquotes-splicing 2)
===> (The square of 2 is 4)

【讨论】:

    【解决方案2】:

    警告:如果您不熟悉 Scheme 中函数的工作原理,请忽略答案!宏是一种高级技术,您需要先了解函数。

    听起来你在问宏。这是一些将test定义为打印2的函数的代码:

     (define-syntax-rule (show-one-more-than num)
       (begin 
         (define num2 (add1 num))   
         (displayln num2)))
    
     (define (test) 
       (define num1 1)
       (show-one-more-than num1))
    

    现在,我可以(而且应该!)将show-one-more-than 写成函数而不是宏(如果将define-syntax-rule 更改为define,代码仍然可以工作),但宏实际上是通过产生代码在他们的呼叫站点。所以上面的代码展开为:

     (define (test)
       (define num1 1)
       (begin 
         (define num2 (add1 num1))
         (displayln num2)))
    

    【讨论】:

      【解决方案3】:

      如果不更好地了解问题,很难说解决这个问题的正确方法是什么。蛮力方法,例如:

      #lang racket
      
      (define (make-test-body lst)
      
        (define source `(define (test)
                          (define num 1)
                          (define l (list))
                          ,@lst))
        source)
      
      
      (define lst
        `((define num2 (add1 num))
          (displayln num2)))
      
      (define test-source
        (make-test-body lst))
      
      (define test
        (parameterize ([current-namespace (make-base-namespace)])
          (eval `(let ()
                   ,test-source
                   test))))
      
      (test)
      

      可能是你想要的,但可能不是。

      【讨论】:

        猜你喜欢
        • 2016-10-28
        • 2020-02-15
        • 2018-04-06
        • 2020-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-22
        • 1970-01-01
        相关资源
        最近更新 更多