Stuart Sierra said:

> It's not covered much.  You get used to it.  Think of it this way -- macros 
> only exist during compilation.  Functions like "apply" get evaluated at 
> run-time.  A macro like "and" has no value at run-time, so you can't use it 
> as an argument to a function.

I'll tell you my current understanding of how Clojure works, so you
can correct me where I may be wrong:

- The compiler has for target a living environment; thus, it's
dynamic.
- There's no interpreter; thus, the following points will be easier to
reason about.
- When code is sent for evaluation, it's first read.
- The reader performs a few substitutions, then gives the resulting
code to the compiler.
- The compiler starts by expanding macros into their substitution.
--- Thus, for functions, there's no such thing as macros.
--- Thus, all that functions see of macros is what came out of macros'
complete expansion.
--- Therefore, like Timothy Pratley wrote so well, a function can have
for parameter a macro call, but not a macro itself.
- After macro expansion, the compiler starts compiling all functions
in need of being compiled, including the functions modified during
macro expansion.
- Then, code is ready for evaluation.

Now, I see that (function macro arg-given-to-macro-by-function) can't
work, because 'function', in its body, during its evaluation, would
have to give 'arg-given...' to 'macro'; but since 'function' is a
function, before eval was inside 'function's body, it needed to
evaluate each one of 'function's parameters; thus, at this precise
moment, 'macro' would have said "hey, now that you're evaluating me,
will you please give me my parameter?", and eval would have answered
"I can't, its 'function's responsibility, but we're not yet inside its
body", and thus, eval would have blocked.

Ok, so although it's a live system, when a new bunch of code is sent
for evaluation, all macros inside it must be expanded before runtime
evaluation can occur. Thus, functions can't act on macros. I thought
that somehow my code could still work because what would have happened
is 'reduce' would have acted on 'and's expansion, but I see and's
expansion couldn't be done because it would have to wait for reduce's
evaluation.

If we were speaking of concurrency, wouldn't this be a deadlock issue?

...I also thought it could be possible that 'and' expands to a partial
application that waits for 'reduce' to provide it its arguments.
Wouldn't this make sense?

Konrad Hinsen said:

> The universal workaround is to define a
> function that contains nothing but the macro, such as
>
>         (fn [x y] (and x y))
>
> which can also be written in Clojure using the shorthand notation
>
>         #(and %1 %2)
>
> Here the macro gets expanded inside the function *body*, but what you
> pass around is the function *object*.

Wouldn't this defeat the purpose of having 'and's arguments short-
circuited when false is found?

Now, why is this workaround possible? For sure, the wrapper function
is ok as a parameter of a function call. And in the called function's
body, when it's going to call the wrapper function, the arguments for
the macro wrapped in the wrapper function will be ready. And the
wrapper function contains the macro's substitution anyways. So if
we're willing to sacrifice macros' lazy parameters evaluation, we can
wrap them inside functions to achieve this effect. We could also say
that as long as macros are either called or wrapped in any function,
they can go anywhere. In other words, the only limitation seems to be
that runtime code can't use the symbol to which a macro is binded.

Phew, does this all make perfect sense?

Chouser said:

>>> Is there anyway to write a macro/function that acts as a function when
>>> necessary (so it can be passed as an argument), but expands into a
>>> macro (for speed) when deemed possible?

>> I don't think this is possible without some sort of support for a
>> macro/function duality in core Clojure.

> Which is one way to describe what's provided by definline.  It's
> marked experimental, has an unusual format and proviso's, but it's
> there get a blend of macro performance and function first-classness.

Cool. Let's see how this develops. It's definitely interesting.

...All those years doing imperative programming, I knew I somehow
wasn't doing what I really always wanted to do. ...Anyways, before I
devote 100% of my programming time to macro-ed functional languages, I
want to get rid of the imperative way of programming as much as
possible, so I thought it might be good for me to do a small detour by
learning Haskell before coming back full strength to Clojure and Qi
+CL. If someone has any opinion about this, I'm all ears open.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to 
clojure+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to