A problem about programming with macros vs Kernel F-exprs

I love Kernel F-exprs which looks better than ordinary macro in almost every ways,
especially the elimination for the need of a reflective tower, or separation of phases, if I understand correctly.

However, I have trouble trying to implement the following using F-expr

(defmacro f () 
 (make-array 1)) ;; Common Lisp style macro
(define g (lambda () (list (f) (f))))

The two (f) above each expand into a different array instance.
Calling (g) will then return a list every time, with the same two different array instances.

I can't think of a way to replicate this behavior using Kernel F-exprs.
It seems that when an F-expr f is called there's no way to know where
in the source code is it called.
If f accepts some arguments, a dirty hack is to have a hash table mapping
f's unevaluated argument to array instances and hope the implementation
doesn't hash-cons the source code, but in this case the argument is just
one unique #nil, so that doesn't work.

Any ideas?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Syntactically distinct macro calls

Is it that each syntactically distinct call (f) is expanded to an array instance before the program is evaluated? If so, that behavior cannot be duplicated by a fexpr. A call to a fexpr happens at a time determined by the logic of the code in which it is embedded. One could arrange to construct a procedure with two particular array instances built into it; but what is built into it would be determined at the time the procedure is constructed.

Expressive power

Does that mean F-expr doesn't have the same or more expressive power comparing to
some homoiconic macro system (like CL macros)?

I wonder how we could extend F-exprs to have the same or more expressive power.

At least in this example, if F-expr accept some argument like &whole
in CL (bind to the combiner CONS that cause the call to the F-expr), that will help it.
However, the F-expr will need to use a hashtable to distinguish lexical position and
it relies on implementation not hash-consing. It would also need the implementation
to propagate the "source combiner" information when evaluating CAR of CONSes.
Overall looks like a dirty hack.

Hmm

This sort of syntax-location-dependent behavior appears to me to —in technical parlance— screw over the equational theory. Seriously. Unlike fexprs, which don't actually deserve the besmirching of their good name on this point. I'm not convinced the behavior should be considered desirable.

The formal definition of expressive power, due to Felleisen, deals in copying expressions around and expecting them to behave the same way, which doesn't work for syntax-location-dependence, hence my expectation it would spike equational theory.

Use macros

If you want it fixed at compile time why not evaluate it at compile time?

If this is just a thought exercise to see whether it's possible to mimick compile time then each distinct function invocation in the source text could get a unique number and you know what to do from there