Pre-RFC: Raw identifiers

#27

This looks great!

Personally, I was happy when I saw the r#catch syntax. It’s reasonably short, fits decently with other syntax, and doesn’t take up a new sigil that I’d rather keep for a more important use.

I think that having a short syntax is far more important in C# because of reflection and anonymous struct literals. Razor uses things like new { @class = "errorbox" } all over the place as an inefficient associative container, with the field names appearing in the output. I hope Rust doesn’t develop such a pattern.

A possible extension: this could allow both identifier#catch and keyword#catch (probably with shorter prefixes) as a way to also expose catch in Rust 1.0 (or multi-version) code.

#28

Anything except r#… and br#… will break Macros 1.0.

macro_rules! x {
    ($a:ident # $b:ident) => {};
    ($c:ident) => { should error };
}
x!(identifier#catch);
x!(keyword#catch);
#29

Hmm, that macro example also rules out @catch, but \catch and `catch` should still be OK because those characters aren’t yet found in legal tokens. (error: unknown start of token: \)

1 Like
#30

Many C dialects support $ as a character in identifiers (probably for compatibility with VMS), so this might help with FFI if someone uses this particular C feature.

#31

So any new literal kind? That’s a shame, and blocks things like s"foo" for Strings too, I guess.

I often feel like every possible syntax addition is breaking for macros…

If possible, I’d like to keep ` unused so writing docs and posts here stays easy :smile:

2 Likes
#32
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
struct s;

impl std::ops::Div<&'static str> for s {
    type Output = String;
    fn div(self, literal: &'static str) -> String {
        literal.to_owned()
    }
}

fn main() {
    let _strings: &[String] = &[s/"hello", s/"we", s/"are", s/"strings", s/"😛"];
}

But seriously, the syntax "foo"s (a suffix s) is reserved and can be used for this.

6 Likes
#33

True, but you can also rename it locally, like #[link_name = "foo$bar"] fn foo_bar().

Having struggled with it here a few times, I’m with you on that. :slight_smile:

#34

Lisp and Ruby use a leading colon for symbols (e.g. :catch), so maybe that would help make it easier to learn for people who have seen that pattern before?

Stealing @cuviper’s example:

use foo:::catch::bar;
let foo = :catch { bar: 42 };
let foo = Foo { :catch: 42 };
foo.:catch = 42;
foo.:catch(42);

Personally I think the `catch` variant isn’t as visually distracting as @catch or r#catch. Although using a delimited string for idents means a function name can now contain spaces, which looks odd after all these years of only allowing alphanumeric and underscores in an identifier.

#35

Lisp uses them for keyword symbols, which are symbols in a special namespace. Symbol quoting uses |…| quoting.

1 Like
#36

Question: how important is the catch problem in practice? How many crates out there indeed use catch as a name of a field or method?

#37

Unknown – maybe not at all. I think the only reason catch couldn’t be a contextual keyword was for the possibility of a struct catch (which already defies naming conventions) and thus catch { ... } constructing it. But that was enough of a blocker that we now have do catch { ... } for the expression, and the keyword breaking change was discussed in the epoch proposal.

#38

I’ve been reminded (by renewed activity) that there is a competing proposal, Infix notation for function call / invocation, that wants to use \foo for something else.

#39

Thanks, then we can also look at raw identifiers used as such infix operators:

  • a \r#catch b
  • a \`catch` b

(in the realm of “silly but syntactically allowable”)

#40

Among 10165 crates from crates.io, 28 use catch identifier for some definition. At least some of them use catch in public API. Full report is here: https://gist.github.com/matklad/acebc3579fc7c70d02056cd8b3d2bf0a.

5 Likes
#41

As a data point, Dart uses #ident - it also has it for operators, so #+ refers to the method defined as operator+ (borrowed from C++), equivalent to our Add::add.

1 Like
#42

We need to do something like this to ever be able to create new reserved words (necessary for the catch syntax for example). I think @cuviper’s proposed syntax strikes a good balance between sugar and salt, and the point about r# or br# being the only syntaxes that don’t break 1.0 macros seems compelling also.

I’d encourage someone to post an RFC.

1 Like
#43

Ok, I’ll get all the feedback here incorporated and post that soon.

3 Likes
#44

@cuviper Do you have an update on this? We’d love to get an RFC into FCP before the impl block

#45

I apologize for my tardiness, but here it is: https://github.com/rust-lang/rfcs/pull/2151

closed #46

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.