Arc Forumnew | comments | leaders | submitlogin
1 point by cchooper 6110 days ago | link | parent

Something like this would be a starting point:

  (mac def-with-prefix (prefix name args . body)
    `(eval (list 'def
            (read (+ (coerce ,prefix 'string)
                     "-"
                     (coerce ',name 'string)))
            ,args
            ,@body)))
called like this:

  (= prefix 'blub)
  (def-with-prefix prefix foo (x) (+ 1 x))
produces this:

  (def blub-foo (x) (+ 1 x)))
Note this is quite clunky because I couldn't find a better way to bind a dynamically determined variable in Arc. Set only takes a symbol as a first argument.


1 point by cooldude127 6110 days ago | link

what is the point of the eval thing? isn't that what macros are supposed to do by themselves?

-----

2 points by cchooper 6110 days ago | link

You mean like this?

  (mac def-with-prefix (prefix name args . body)
    `(def
        (read (+ (coerce ,prefix 'string)
                 "-"
                 (coerce ',name 'string)))
        ,args
        ,@body))
It doesn't work, because

  (def-with-prefix 'blub 'foo (x) (+ 1 x))
expands to

  (def (read (+ ...blah...blah...)) (x) (+ 1 x))
and def will only take a literal symbol as the first argument. That's also the problem with set I mentioned before.

-----

2 points by shiro 6110 days ago | link

How about

    `(def ,(read (+ (coerce prefix 'string) "-" (coerce name 'string))) ,args ,@body)

-----

1 point by cchooper 6110 days ago | link

Doesn't work I'm afraid:

  (= pre 'blub)

  (your-def-with-prefix pre foo (x) (+ 1 x))
  => #<procedure: pre-foo>

  (my-def-with-prefix pre foo (x) (+ 1 x))
  => #<procedure: blub-foo>
Without being able to take the prefix from the value of a variable, the whole macro is pointless.

-----

1 point by eds 6110 days ago | link

Then why don't you just eval prefix?

  `(def ,(read (+ (coerce (eval prefix) 'string) "-" (coerce name 'string))) ,args ,@body)
It's still much less clunky than expanding the whole def under an eval.

-----

1 point by cchooper 6110 days ago | link

Still has a bug:

  (let pre2 'blub (your-def-with-prefix pre2 foo (x) (+ 1 x)))
  => Error: "reference to undefined identifier: _pre2"

-----

2 points by cooldude127 6110 days ago | link

that's because the macro gets expanded (and thus eval is called on pre2) before the let form is evaluated.

-----

1 point by eds 6110 days ago | link

Yeah, I see the problem with that.

cchooper, did you actually ever run your version? I can't make your orginal version work.

  arc> (def-with-prefix pre foo (x) (+ 1 x))
  Error: "reference to undefined identifier: _x"
And looking at the macro expansion, I'm not at all surprised:

  arc> (macex '(def-with-prefix pre foo (x) (+ 1 x)))
  (eval (list (quote def) ; my indentation
              (read (+ (coerce pre (quote string)) "-" (coerce (quote foo) (quote string))))
              (x) (+ 1 x)))
args and body would need to be quoted for this to work properly. And then it admittedly does what it is supposed to, but it becomes even uglier.

  (mac def-with-prefix (prefix name args . body)
    `(eval (list 'def
            (read (+ (coerce ,prefix 'string)
                     "-"
                     (coerce ',name 'string)))
            ',args
            ,@(map [list 'quote _] body))))

-----

1 point by cchooper 6109 days ago | link

Hmmm... it worked last night. I must have made a mistake when I copied it into the comment. Thanks for catching it.

Here's a slightly less clunky version:

  (mac def-with-prefix (prefix name args . body)
    `(eval (join (list 'def 
                  (sym (+ (coerce ,prefix 'string)
                          "-"
                          (coerce ',name 'string)))
                  ',args)
            ',body)))
I also tried doing it with nested quasiquotes but that just looked worse.

-----

1 point by shiro 6110 days ago | link

Ah, I got it.

-----

1 point by cooldude127 6110 days ago | link

yes, like that. there is no reason i can see for a macro to have to call eval except in the MOST EXTREME cases.

-----

2 points by cchooper 6110 days ago | link

Unfortunately, Arc makes this an extreme case. There's just no way to get the exact required behaviour in Arc without using eval.

In Arc:

  arc> (= foo 's)
  s
  arc> (set foo 4)
  4
  arc> foo
  4
  arc> s
  Error: "reference to undefined identifier: _s"
In Common Lisp:

  CL-USER> (setf foo 's)
  S
  CL-USER> (set foo 4)
  4
  CL-USER> foo
  S
  CL-USER> s
  4

-----