[Discussion] A perspective on super let: could a related “lift” capability ever belong in Rust’s macro system?
naganohara-yoshino:
It asks the expander to evaluate an expression in an enclosing context
While this is more powerful than super let it begs the question of whether we want something this powerful , to the point that it allows breaking the syntactic order of execution of a program. For example in your Racket snippet:
- the first statement that is executed is
(local-function) - the first statement of
local-functionis(displayln "Local function started.") - I would thus assume that the first string printed is
Local function started. - the program actually prints
Heavy computation!before that
To understand how the program actually behaves you need to read all the code, even the one that syntactically comes after!
On the other hand Rust's super let is limited to allocating a local in the enclosing scope, which you could consider as a "pure" operation. The initializer of that local is still evaluated when the code flow reaches the super let. In other words super let foo = bar() is equivalen to super { let foo }; foo = bar();
Your proposed implementation of the super_let macro does not match this behaviour, since it evaluates the given expression before the current scope started, and even does so unconditionally (e.g. if condition { super_let!(foo()) } would still call foo() if condition is false, which is terrible!). You might not even be able to implement the correct behaviour with an API that exposes only lift_expr, since that really only allows you to implement super { let <lifted_id> = <expr> } and does not allow = <expr> to be omitted.
I also wonder why you need proc macros to be become unpure and expose a lift_expr method to them. A super { ... } syntactic construct would do the same in a much simplier way. This is not to say that I support adding it though, since as I said it seems "too powerful" to me.
Discussion in the ATmosphere