Arc Forumnew | comments | leaders | submitlogin
Quoting function values (awwx.posterous.com)
4 points by aw 5157 days ago | 4 comments


4 points by waterhouse 5157 days ago | link

Niiiiice. Seems you can do this with tables, too.

  arc> (eval `(+ 1 2))
  3
  arc> (eval `(,+ 1 2))
  Error: "Bad object in expression #<procedure:+>"
  arc> (eval `(',+ 1 2))
  3
  arc> (eval `((obj a 1) 'a))
  1
  arc> (eval `(,(obj a 1) 'a))
  Error: "Bad object in expression #hash((a . 1))"
  arc> (eval `(',(obj a 1) 'a))
  1
Probably any object will work. Seems we can cross this one off the list:

  ; compromises in this implementation: 
  ; no objs in code
  --arc.arc
...or, at least, we have a workaround. Ideally you wouldn't need to quote it at all.

-----

3 points by jazzdev 5157 days ago | link

Ideally you wouldn't need to quote it at all.

It works in Jarc without quoting.

  Jarc> (eval `(,+ 1 2))
  3
  Jarc> (eval `(,(obj a 1) 'a))
  1
Not intentional. Just a side-effect of the way Jarc evals objects. Everything except cons, sym and string evals to itself.

-----

2 points by rocketnia 5157 days ago | link

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

-----

2 points by rntz 5156 days ago | link

You can quote anything, literally anything. Why wouldn't you be able to? The only caveat, if you can call it that, is that you can't necessarily 'write out the resulting code sexpr readably (for example, functions are not, as a rule, writable).

The only reason why you need to quote certain things at all is because the arc compiler is very picky about its input -- it cases on the type of the sexpr it's compiling, and if it doesn't recognize the type it throws an error -- but things inside a quotation escape this examination. If this weren't the case, and it instead just passed them through, then functions could be embedded directly instead of quoted; and everything (I think) other than symbols and lists evaluate to themselves in mzscheme.

-----