Description
Would it make sense to enable the @body
macros to use the function bodies? Let there be such a code:
fn int foo(int x) {
@pool() {
return string::tformat("%d", x).len;
};
}
Many functions only need an array or string only for their lifetime, so I suppose this kind of functions are not that rare to write in C3. However, this creates a new scope just for the @pool
macro. This is reasonable, but collapsing these two scopes may be nice, like this:
fn int foo(int x) @pool() {
return string::tformat("%d", x).len;
}
This also enables short function declarations to be used with such patterns:
fn int foo(int x) @pool() => string::tformat("%d", x).len;
which is possible without this, but then we would need another feature such as trailing blocks in macros returning values, since all bodies currently return void
. I saw that there is a discussion about this feature in issue #1889. Macros in macros can solve this problem, but I think they do not look as clean as trailing bodies directly being able to return values:
fn int foo(int x) => @pool(macro() => string::tformat("%d", x).len);
where the hypothetical @pool
takes a macro argument instead of a trailing body unlike the current one.
With the function attribute-ish macro syntax, it is also cleaner to chain multiple such macros. For example, say we have a @synchronized
macro, which takes a mutex as #
parameter and a body to run while locked.
struct MyMonitor {
Mutex mutex;
int number;
}
macro @synchronized(#lock; @body()) {
var lock = &#lock;
lock.lock()!!;
defer lock.unlock()!!;
@body();
}
fn int MyMonitor.increase(&self) @synchronized(self.mutex) => self.number += 1;
Say we also want to create a memory pool for this function. Then this would be possible:
fn int MyMonitor.digit_count(&self) @pool() @synchronized(self.mutex) => string::tformat("%d", self.number).len;
I guess that this can be translated to the following code trivially by the compiler if it sees a macro usage between the function parameters and function body:
fn int MyMonitor.digit_count(&self) {
@pool() {
@synchronized(self.mutex) {
return string::tformat("%d", self.number).len;
}
};
}