String::from("...") => d"..."


#21

Ok, I think we’re pretty much on the same page, barring some minor potential misunderstandings that I won’t waste time on. Thanks for your patience. I do have this ridiculous compulsion to yak on.

Though I would like to point out that, with this issue specifically, I don’t personally see any horses in any races. Compare s"" to r""… At the end of the day, does r"" seem like a mistake? Does it really even matter how many times it is used, or how specialized the applications using it are? Or how beginner unfriendly the #-syntax is?

People will get used to the convenience until they can’t live without it. Or at least, until after a short-yet-frustrating period of relearning to live without it. In either case, I think there’s no real damage being done whether this syntax is available or not. (Assuming it doesn’t cause breakage problems in practice.)

EDIT: On second thought, there is something that would irk me bit. A String literal syntax would make std::String a little more special, and introduce a kind of ergonomic penalty for using non-std string types.


#22

In a sense, this problem already exists for all the other literal types. In my current project, I use a lot of r32 and r64s. I can’t construct them with literals, which is an incessant pain.

I’d really like to see implicit literal coercion in general. If combined with the ability to construct heap-allocated values at compile time, String literals would be both free, and something that could be added to std.


#23

Extending that slightly to include panics at compile time (which are—as far as I know—closer to stabilisation) (EDIT: and const traits, which is… not anywhere near stabilization) there could be a very simple macro to handle this for arbitrary types:

// No idea what to call it, so...
macro_rules! d {
    ($($tt:tt)*) => {{
        ::std::str::parse(stringify!($($tt)*)).unwrap()
    }}
}

// Just a guess at what you're referring to
type r32 = ::num::rational::Rational32;

const STRING: String = d!(foo);
const RATIONAL: r32 = d!(2 / 10);

Whether this is good enough, or needs some language level sugar ¯\_(ツ)_/¯


#24

This is getting off-topic, but just to clarify:

  • Make literal types like {integer} actual types that can be accepted by const fns, but which cannot exist at runtime (“ephemeral” types).
  • Implicitly invoked trait: trait FromLiteral<T: Ephemeral> { const fn from_literal(_: T) -> Self; }. This then retroactively becomes how an integer literal turns into a concrete i32, for example.
  • Some kind of scheme where you could say #[freeze_safe] pub struct String { #[follow] ptr: *mut u8, ... } to indicate that it’s safe to just dump a type’s contents into a binary and never drop it. Such types could be returned from const fn and stored in consts or statics.

At that point, you could implement FromLiteral<{str}> for String and Robert’s your mother’s brother.

(Incidentally: r32 is my "f32 sans NaN" type; “r” is for “real” (yes, I know that infinity is not in ℝ, I don’t care).)


#25

Why isn’t this the default case for all statics? I’ve got this nagging feeling it has to do with concurrency and data races, but can’t make it concrete atm.


#26

No opinion on the subject, but I just want to know what d would stand for & I’m confused why no one has asked yet, is this obvious to everyone else?


#27

I assume it stands for “dynamic”; I think no one has brought it up because there are more interesting semantic questions :wink: Presumably we would bikeshed this and come up with an appropriate prefix if we wanted to do it.