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

"$args is an implicit gensym :)"

I wasn't asking a question like that. :-p What I was asking was more along the lines of whether some expression like (compose foo $args) could end up with variable capture issues.

For all I know, maybe it wouldn't. Kernel's approach to evaluating an arg in the caller's scope is to pass scopes around as first-class values. Your approach is to change the scoping rules around in ways I don't really grok yet. Also, the way you're expanding $foo might be a kind of code-walking that essentially takes the form of its own kind of scoping rule.

-

"There's no difference between functions and macros in wart."

I think I already understand what you're trying to clarify here, too. What I'm saying is to use something other than "mac" to define 'compose.

If we forget about "functions" for a moment, what I mean is that instead of doing this...

  mac compose($f $g)
    `(lambda '$args
       eval `(,,$f (,,$g ,@$args)))
...it might be more hygienic to do something like this:

  mac compose($f $g)
    with (f eval.$f g eval.$g)  ; outside the scope of $args
      `(lambda '$args
         eval `(,,f (,,g ,@$args)))
I expect it's easier to make this change by replacing "mac" with "def":

  def compose(f g)
    lambda '$args
      eval `(,f (,g ,@$args))
(Keep in mind that this version still doesn't quote 'f and 'g, which I recommend doing in case they're lists or something.)


2 points by akkartik 4608 days ago | link

Wow, you're right, compose doesn't need to be a macro!

Why was I thinking of it as a macro? Ah, I was blindly copying the arc version. And it looks like that doesn't need to be a macro either:

  (def compose fs
    (if (no cdr.fs)
      car.fs
      (fn args
        (car.fs (apply (apply compose cdr.fs) args)))))
Does that seem right? It seems to be working fine..

---

I still don't follow your arguments about hygiene. I suppose it's conceivable that code could use args2179 directly without going through gensym. Or that compose could call itself recursively and override $args in the caller's scope, and that it would be for some reason undesirable. Is either scenario what you were thinking of?

Thanks a lot for the comments. I think you understand the implications of my design decisions where I've been flailing around writing unit tests as I think up special-cases.

-----

1 point by rocketnia 4606 days ago | link

"Does that seem right?"

Yeah, I don't know why Arc's 'compose is a macro. I think I've tried to (apply compose ...) at least once and gotten bitten by that. ^^

---

"I still don't follow your arguments about hygiene. I suppose it's conceivable that code could use args2179 directly without going through gensym. Or that compose could call itself recursively and override $args in the caller's scope, and that it would be for some reason undesirable. Is either scenario what you were thinking of?"

I don't think so.... What I mean is, is it possible for the value inserted with ",$f" or ",$g" to contain the symbol '$args (assuming $ isn't a reader macro) in a way that causes it to be confused with the lambda's meaning of '$args?

  mac compose($f $g)
    `(lambda '$args
       eval `(,,$f (,,$g ,@$args)))

-----

1 point by akkartik 4606 days ago | link

Ah, I see. The answer is no, there can be no $vars after evaluation. $ is indeed expanded at read time.

-----

1 point by akkartik 4608 days ago | link

"(Keep in mind that this version still doesn't quote 'f and 'g, which I recommend doing in case they're lists or something.)"

You mean for something like:

  (compose '(1 2 3) *)

?

-----

1 point by rocketnia 4606 days ago | link

Yep. Here's a slightly-less-toy toy example:

  (let (foo nil bar nil)
    ; ...build foo and bar up as lists...
    ; ...
    (foo:- len.bar 1)
    ; ...
    )
If 'compose creates (<value of foo> (<value of -> len.bar 1)), then <value of foo>, being a list, might evaluate as an fexpr call.

-----

1 point by akkartik 4606 days ago | link

In wart fexprs either evaluate to a compiled op or to a list with the atom evald-lambda in the car.

You do raise the question of dealing with lists and hashes in function position. Wart doesn't do that yet, and it wasn't even on my todo list so far.

-----

1 point by rocketnia 4606 days ago | link

"You do raise the question of dealing with lists and hashes in function position. Wart doesn't do that yet, and it wasn't even on my todo list so far."

Oh, if you choose not to add that, I don't mind. ^_^

Still, as long as there's no quoting, I'm betting people can inject code in there, like (compose '$args '(while t)). Not that it's wrong to design 'compose with that code-injection feature in mind, but it would surprise me.

-----