Arc Forumnew | comments | leaders | submitlogin
2 points by rocketnia 5129 days ago | link | parent

Yep. ^_^ I like to use the pattern `(... (',(fn () x)) ...) to refer to all kinds of values from within generated code. I think it was http://arclanguage.org/item?id=11612 that prodded me into doing this.

Usually ',x is enough, but (',(fn () x)) has the benefit that it preserves the identity of something that has mutable state. Racket copies many data structures if they appear as syntax, even inside 'quote forms, but lambdas are data structures that escape that wrath.

  arc> (is is (eval `',is))
  t
  arc> (mac thunk body `(fn () ,@body))
  #(tagged mac #<procedure: thunk>)
  arc> (is thunk (eval `',thunk))
  nil
  arc> (is thunk (eval `(',thunk.thunk)))
  t
  arc> (= foo '(1 2 3))
  (1 2 3)
  arc> (is foo (eval `',foo))
  nil
  arc> (is foo (eval `(',thunk.foo)))
  t
I think the copying happens at the moment the Racket (quote ...) form is compiled:

  Welcome to Racket v5.0.1.
  > (define vec (vector 'a 'b 'c))
  > (vector-set! vec 1 'r)
  > vec
  '#(a r c)
  > (eval `(define (get-vec) ',vec))
  > (vector-set! (get-vec) 2 't)
  vector-set!: expects type <mutable vector> as 1st argument, given: '#(a r c); other arguments were: 2 't
  
   === context ===
  C:\Program Files\Racket\collects\racket\private\misc.rkt:74:7
  
  > (eq? (get-vec) (get-vec))
  #t
  > (eq? (get-vec) (eval `',(get-vec)))
  #f
  > (eq? (get-vec) (eval `(',get-vec)))
  #t
If you want to work around this in your version of Arc, you can probably just have 'ac generate ((quote <procedure-returning-x>)) wherever it would normally generate (quote <x>). ^_^

Depending on the rest of your code, quasiquotation may need changes too. Maybe `(1 ,x 3) should compile to ((quote #<cons>) 1 ((quote #<cons>) value-of-x ((quote <procedure-returning-(3)>))))? If you're using fallintothis's code, this is probably relatively easy to accomplish.

If you don't work around Racket's copying, that's fine too. :-p