Blog post: View types for Rust

If we really want to lean into the "kinda like they were macros", then macro fn makes a lot of sense.

Semantically, I would describe macro fn as expanding similar to the following:

macro fn mul_add(x, y, z) { x * y + z }

mul_add(f(), g(), h())

// roughly semantically equivalent to 

match (f(), g(), h()) {
    (x, y, z) => { x * y + z }
}

though with mul_add (maybe? maybe not?) having its own call stack entry, its own monomorphized function site rather than strictly being always 100% inlined.

If the argument patterns are partial patterns (e.g. WonkaChocolateFactory { golden_tickets, .. }), then this would semantically define macro fn to disjointly capture the named fields only.

However, with that definition with the early-evaluation rebinding, the whole binding is always taken, rather than field wise usage being possible (without a partial pattern in the signature). This is IIUC a fundamental limitation of the surface language as it exists today; there's no way to both only evaluate a (place) expression once and do disjoint captures with its usages.

If we do add macro fn/inline fn/whatever, I expect the function-interface semantics where the arguments are evaluated once to be met (unlike with bang-macros, which can freely do expression rewriting), so I'm not exactly sure how macro fn would exactly help the disjoint captures problem without supporting disjoint captures across a normal function interface first.

2 Likes