Today I learned that in Rust

Today I learned that in Rust if you have any type and a function of the same name, they are imported and/or reexported as a unit, you can use both.


mod module {
    #[derive(Debug)]
    pub struct Recipes {
        v: Vec<String>,
    }
    
    #[allow(non_snake_case)]
    pub fn Recipes<'a, I>(iter: I) -> Recipes
        where I: IntoIterator<Item=&'a str>
    {
        Recipes {
            v: iter.into_iter().map(String::from).collect()
        }
    }
}

pub mod prelude {
    pub use module::Recipes;
}

use prelude::Recipes;

fn main() {
    let r: Recipes = Recipes(["Carrot Cake & Jam", "Tuna Salad"].iter().cloned());
    println!("{:?}", r);
}

Playground link

It's kind of an oddity. Quiz time: Why?

1 Like

Not only you have learned it today! :slight_smile:

https://github.com/intellij-rust/intellij-rust/issues/661#issuecomment-251098487

1 Like

Here is a real world example from the rustc: https://github.com/rust-lang/rust/blob/ff713464e6530fab2e13d0965929d8189c59ae56/src/libsyntax/ptr.rs#L48-L58

Also, whenever you write a tuple struct, you get this implicity.
struct Foo(i32) creates both a type Foo and a constructor Foo: fn(i32) -> Foo.

6 Likes

Relevant thread from the internals: Rust type/values namespace status - Rust Internals

1 Like

I saw today that rustc uses this by using FnvHashSet as both a type alias and a function. So rust's own internals are using it (I guess the compiler hackers would be the ones to know these corner cases).

Personally I really dislike this pattern because it is very surprising to me, but I think if it were made more normal by documenting it, using it in the standard library, and so on, I would feel more okay with it. Right now I'm much more comfortable using associated functions as constructors.

I was incredulous, so I agree with you.

It's tempting to use it, now that I know it exists! However, I see that rustdoc does not emit any docs for such a punned function.

New day, new learn: The X macro pattern, in Rust!

From alexcrichton we learn how you can use "X macros" neatly in Rust. The idea is that you define list of things in one macro, and make it take another macro's name as a parameter.

2 Likes

Yep, it's also used in Cargo here: cargo/cargo.rs at ebcf0a8f41759717876bca5871137ab48e06f790 · rust-lang/cargo · GitHub (and breaks IntelliJ Rust resolve inside the subcommand modules :frowning: )

1 Like

A post was split to a new topic: Useful tip for benchmarking/testing optional Cargo features

It is very bad to hijack an almost five year old thread. Could you please open a new one (and if you like point to the old one)?

1 Like

Thank you @manfredlotz for your reply. May I ask, why you think it is bad, especially regarding this topic?

I understand that for very specific topics it is better to create a new thread, but this is sort of a "collection" of posts (similar to "Crate of the Week" or "Quote of the Week"), isn't it?

If the general opinion is to create a new thread for this, can someone please close this thread, so others won't post in here anymore.

Thank you. :heart:

1 Like

Perhaps you are right. I didn't view it like this. Especially, as it hasn't been used this way for such a long time.

1 Like

Moved the new post to a separate thread. We try not to keep threads open forever these days (with a few exceptions) because of various confusion when they get bumped, and because they disproportionately attract spam, and because comments in them can generate email notifications to large numbers of people, some of whom are no longer active on the forum.

4 Likes