How can I unsplice a list of expression into code?

2019-08-02 11:58发布

I have an experiment for my project, basically, I need to embedded some s-expression into the code and make it run, like this,

(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)))

I want the test function be like after test(lst) in racket code:

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

How can I do this in racket?

Update The reason I would like to use eval or the previous questions is that I am using Z3 racket binding, I need to generate formulas (which uses racket binding APIs), and then I will fire the query at some point, that's when I need to evaluate those code. I have not figured out other ways to go in my case... One super simple example is, imagine
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))

I have some model to analyze the constructs (so I am not using racketZ3 directly), during each analyzing point, I will map the data types in the program into the Z3 types, and made some assertions,

I will generate something like:

  • At allocation site, I will need to make the following formula:

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

  • Then at the array set site, I will have the following assertions and to check whether the 3 is less then the length

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

  • Then finally, I will gather the formulas generated as above, and wrap them in the form which is able to fire Z3 binding to run the following gathered information as code:

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

This is the super simple example I can think of... making sense?
side note. Z3 Racket binding will crash for some reason on version 5.3.1, but it mostly can work on version 5.2.1

标签: scheme racket
3条回答
Root(大扎)
2楼-- · 2019-08-02 12:12

Warning: if you're not familiar with how functions work in Scheme, ignore the answer! Macros are an advanced technique, and you need to understand functions first.

It sounds like you're asking about macros. Here's some code that defines test to be a function that prints 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))

Now, I could (and should!) have written show-one-more-than as a function instead of a macro (the code will still work if you change define-syntax-rule to define), but macros do in fact operate by producing code at their call sites. So the above code expands to:

 (define (test)
   (define num1 1)
   (begin 
     (define num2 (add1 num1))
     (displayln num2)))
查看更多
我命由我不由天
3楼-- · 2019-08-02 12:19

Honestly, I don’t understand what exactly you would like to achieve. To quote N. Holm, Sketchy Scheme, 4.5th edition, p. 108: »The major purpose of quasiquotation is the construction of fixed list structures that contain only a few variable parts«. I don’t think that quasiquotation would be used in a context like you are aiming at.

For a typical context of quasiquotation consider the following example:

(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)
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-08-02 12:21

Without knowing the problem better, it's hard to say what the correct approach to this problem is. A brute force approach, such as the following:

#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)

may be what you want, but probably not.

查看更多
登录 后发表回答