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

Doesn't this feature mean I have to use quasiquotation to build macro results if I want this behavior? I'm guessing if I try to use any function as I'm building macro results, it'll strip '' on the way into the function. This limits me to fexprs that don't use functions this way. And if I use a typical macro, that macro will probably be prepared for splicing itself, which means it too will intentionally strip '' on the way in.

Now that we're disarmed of functions and of splice-friendly macros (which probably encompasses almost the entire standard library!), we have to see if we can make do with whatever we have left. I don't think that's very much in the spirit of "first-class."



1 point by akkartik 4346 days ago | link

Ah, I figured out what you were getting at:

  wart> (def helper(a b) `(cons ,a ,b))
  wart> (mac foo(a b) (helper a b))
  wart> (foo 1 '(2 3))
  (1 2 3)
  wart> (foo @'(1 (2 3)))
  008eval.cc:79 calling macros with splice can have subtle effects (http://arclanguage.org/item?id=15659)
  005types.cc:263 can't coerce number 2 to function
Eep! You're right, this is a fairly common use case.

The good news is that wart's warning system has held up. If it can't handle it it throws that warning.

-----

1 point by akkartik 4335 days ago | link

macros-calling-functions-generating-backquoted-lists now works!

The cost is a special variant of eval to call inside macros: http://github.com/akkartik/wart/commit/e3124e9559#diff-3

I still emit the warning, because examples like this fail:

  wart> (def helper(a b) `(cons ,a ,b))
  wart> (mac foo args (helper @args))
  wart> (foo @'(1 (2 3)))
  008eval.cc:79 calling macros with splice can have subtle effects (http://arclanguage.org/item?id=15659)
  005types.cc:263 can't coerce number 2 to function

-----

1 point by akkartik 4347 days ago | link

I'm not sure I understand you, so let me show a few examples:

  ; function calls inside macros?
  wart> (def f(x) x)
  wart> (mac foo(a b) `(cons ,a ,f.b))
  wart> (foo @'(1 (2 3)))
  (1 2 3)

  ; splice friendly macros?
  wart> (foo @(foo @'(1 ((2 3)))))
  (1 2 3)

  ; splice friendly macros?
  wart> (mac bar(a b) `(cons 3 ,@(foo a b)))
  wart> (bar @'(1 (2 3)))
  (3 . 1)
Do these address any concerns?

-----

1 point by rocketnia 4347 days ago | link

It does tell me I don't understand your system yet, at least. :-p

So if x is a variable containing ''abc, when we say (bar x x) we wind up evaluating (cons 3 ''(cons ''x ''x))?

When we evaluate (cons ''x ''x), it strips off the '' to get (cons foo foo), and then we end up with (''abc . ''abc)?

Then, altogether, we end up with a result of (3 . (''abc . ''abc)), which appears at the REPL complete with ''?

Let me know if I'm getting anything wrong.

-----

1 point by akkartik 4346 days ago | link

Almost:

  wart> (mac foo(a b) `(cons ,a ,b))
  wart> (mac bar(a b) (prn `(cons 3 ,@(foo a b)))) ; prn for debugging
  wart> ((fn(x) (bar x x)) 'abc)
  (cons 3 x . x)
  004cell.cc:158 car of non-cons: x
  004cell.cc:158 car of non-cons: x
  (3 . abc)
My bar example is poorly constructed; besides that I think you're right.

-----

1 point by rocketnia 4344 days ago | link

Oh, I see. Would you mind showing me what happens with (mac bar(a b) `(cons 3 ,(foo a b)))?

-----

1 point by akkartik 4344 days ago | link

  wart> (mac foo(a b) `(cons ,a ,b))
  wart> (mac bar(a b) `(cons 3 ,(foo a b)))
  wart> ((fn(x) (bar x x)) 'abc)
  005types.cc:263 can't coerce symbol abc to function
There was a typo in grandparent, so let me summarize the correct versions:

  wart> (mac foo(a b) `(cons ,a ,b))
  wart> (mac bar(a b) `(cons 3 ,@(foo a b)))
  wart> ((fn(x) (bar x x)) @'(abc))
  (3 . abc)

  wart> (mac foo(a b) `(cons ,a ,b))
  wart> (mac bar(a b) `(cons 3 ,(foo a b)))
  wart> ((fn(x) (bar x x)) @'(abc))
  005types.cc:263 can't coerce symbol abc to function   ; no change
I think you're asking what happens to (''a b c). Hmm, I don't translate that to ''(a b c). It seems to be acting like (a b c). Does that seem right?

---

Another potential concern: I'm using a single boolean to track whether we encounter a '', and I reset it before unquote's eval and check it after. I think it might need to be a stack of booleans to handle nested expressions, but I've not been able to come up with a failing test case.

http://github.com/akkartik/wart/blob/6d5d5a845c/007scope.cc#...

-----

1 point by akkartik 4343 days ago | link

Ah, I answered my own question. It turns out this doesn't work:

  (all present? '((1) (2 4 6)))
if you define all as:

  def all(f seq)
    (and @(map f seq))
For precisely this reason.

(present? is a synonym for idfn.)

-----

1 point by rocketnia 4343 days ago | link

Hmm, what happens when you say `,(write `,'foo)? ^_^

-----

1 point by akkartik 4343 days ago | link

  wart> `,(write `,'foo)
  foo005types.cc:263 can't coerce symbol foo to function
Is that what you expect? I'm not sure what you're trying.

-----

1 point by rocketnia 4343 days ago | link

Something bugs me about this claim:

" '' is an internal detail. The reader provides no way to type it in. If you ever see it printed at the REPL, that's a bug."

If unquote adds a '', then `,'foo should return ''foo, right? Then 'write should write ''foo at the REPL.

In order to weasel out of anything that stripped '' from the arguments to a function, I tried putting `, around the whole command, in the hopes that it would somehow manipulate the state of the don't-strip-'' flag(s) for the duration of the command.

In any case, there's no reason foo should be called, is there? O_o

In other news, this might be an easy test case for the scope of the don't-strip-'' flag. If your implementation sets it to true on the way in and false on the way out, then it'll become false on the way out of the inner `, , rather than recovering its previous value of true.

-----

1 point by akkartik 4334 days ago | link

"If unquote adds a '', then `,'foo should return ''foo, right?"

Unquote doesn't add '', @ does. Perhaps that changes your example?

"In any case, there's no reason foo should be called, is there? O_o"

:) Yeah that's a bug with my paren inference; it was implicitly wrapping the expression in parens. I'd never seen backquote-comma before. Here's a temporary workaround:

  wart> (list `,(write `,'foo))
  foo(foo)  ; ignore the (foo) -- it's the return value
Update: fixed (http://github.com/akkartik/wart/commit/70cfb18504)

  wart> `,(write `,'foo)
  foofoo

-----

1 point by akkartik 4343 days ago | link

Hmm, I haven't fully digested this, but I do have a passing test on nested unquote: http://github.com/akkartik/wart/blob/a5a9f2ffcd/030.test#L35

-----