[rust-dev] [RFC] Functions/methods with generated names
Paul Stansifer
paul.stansifer at gmail.com
Fri Feb 15 08:09:19 PST 2013
Your analysis is solid; those are the main options, as far as I can tell.
TL;DR: Advantages and disadvantages! Implementation concerns! Smurfs! Third
option somewhat preferred by me!
- I agree that macros-in-identifier-position is appealing linguistically,
but it's a bit tricky for internal reasons: the representation of
identifiers would need to be changed. The most natural choice is an `enum {
literal_ident(...), macro_invocation(...) }`, but this change would
probably have a pretty big surface area (it wouldn't touch *everything*,
the way interning identifiers originally did, and the
lookup-the-actual-name-or-fail could be folded into changes that hygiene
requires anyways). An easier-to-implement strategy would be to add an
Option<ast::mac_> to all identifiers, and have the macro system examine and
expand this during expand.rs, as if it were an actual node in the AST. That
would be quite easy to implement, but wouldn't be very clean.
Either way, the result looks would be used like:
macro_rules! define_smurfy_fn(
($name:id, $arg:id, $body:expr) => (
fn concat_idents!(smurf_, $name) ($arg:uint) -> uint {
$body
}
)
)
- I think that there's a modification of your second option that'll be a
bit more general, and could be implemented as a single, ordinary syntax
extension. Replace `concat_idents!(...)` with
`invoke_with_concatted_idents!(...)` (taking a macro name as its first
argument, and a `+`-separated sequence of identifiers as its second, and an
arbitrary number of arguments to be passed through afterwards), to be used
as follows:
macro_rules! define_smurfy_fn_internal(
($smurf_name:id, $arg:id, $body:expr) => (
fn $smurf_name($arg:uint) -> uint {
$body
}
)
)
macro_rules! define_smurfy_fn(
($name:id, $arg:id, $body:expr) => (
invoke_with_concatted_idents!(
define_smurfy_fn_internal,
smurf_ + $name,
$body)
)
)
It's like continuation-passing-style! As portrayed in a horror movie about
functional programming! Actually, aside from the verbosity, it's not too
bad, and the implementation of `invoke_with_concatted_idents!` would be
neatly contained within one file.
- Building identifier concatenation into the macro system wouldn't be too
bad. It has one particular advantage: it might make it easier to
automatically do the Right Thing hygienically when concatenating
identifiers. For example, if you write (using prefix notation, which I
think might be more readable for this) `$+(smurf_, $name)`, the resulting
identifier Ought To have the marks from $name. (I *think* that
`$+($name_left, _, $name_right)` ought to have the union of the marks from
both names, but I'm not sure.)
I don't think that the previous two options could do this (to make
`concat_idents!(...)` hygienic, the programmer would have to pass an
additional argument indicating where to get the marks from, e.g.
`concat_idents!(smurf_, $name <~~ $name)`). The expander could magically
inform the appropriate macro which identifiers are literal and which ones
aren't, but that would be awfully sad.
The big disadvantage of this is that it doesn't naturally extend to other
operations on names. But I think that concatenation ought to be enough for
anybody. (`subidentifier!(...)`? `join_idents!(...)`? `disemvowel!(...)`?).
Implementation-wise, I think that this is not bad: just another case in
transcribe.rs, ast.rs, and parser.rs.
On the whole, now that I've written this all, I think that the third option
is the most appealing, unless we expect
non-concatenation-operations-on-identifiers to be something we want.
Otherwise, I think identifier-position-macros are a one-syntax-extension
pony, so we might as well make concatenation a special operation, and keep
the second option on the shelf for when someone wants something truly
strange.
Paul
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20130215/244c105e/attachment-0001.html>
More information about the Rust-dev
mailing list