Skip to content

Functions provided in a vector to a vec::each can't be called #3550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
AngryLawyer opened this issue Sep 21, 2012 · 6 comments
Closed

Functions provided in a vector to a vec::each can't be called #3550

AngryLawyer opened this issue Sep 21, 2012 · 6 comments

Comments

@AngryLawyer
Copy link

This may turn out to me being a plonker, but while maintaining rust-sdl to match the latest version of Master, I had to swap out vec::iter for vec::each, as the former has vanished.

I have code similar to this:

fn first() {
    io::println("LOL FIRST");
}

fn second() {
    io::println("LOL SECOND");
}

fn main() {
    let functions = [
        first,
        second
    ];

    for functions.each |func| { func(); };
}

And I'm getting this in response.

first_class_test.rs:15:32: 15:39 error: mismatched types: expected function or foreign function but found &fn()
first_class_test.rs:15     for functions.each |func| { func(); };
                                                       ^~~~~~~

Any ideas?

@bstrie
Copy link
Contributor

bstrie commented Sep 21, 2012

We were so close to figuring it out! That vec::each change has, in fact, made it in, and it also turns out that () binds more tightly than *. So this works:

fn main() {
    let functions = [
        || io::println("LOL FIRST"),
        || io::println("LOL SECOND")
    ];

    for functions.each |func| {
        (*func)();
    }
}

Though if you're calling func multiple times inside the loop you should probably reassign it for convenience:

    for functions.each |func| {
        let func = *func;
        func();
    }

This still feels a little grody, though. Niko has noted a potential solution for this in rust-lang/prev.rust-lang.org#1, via supporting infallible matching in parameter lists. That would enable you to write it a bit more naturally:

    for functions.each |&func| {
        func();
    }

@nikomatsakis, would you mind opening an issue for infallible matching in parameter lists, so it doesn't get forgotten? I get the feeling that people are going to keep stumbling/grumbling over this.

@AngryLawyer
Copy link
Author

That looks like it has fixed it - you're a star.

The latter syntax would indeed make life a lot more pleasant, but I'm happy to call this closed.

@brson
Copy link
Contributor

brson commented Sep 21, 2012

@AngryLawyer using named functions as values is wonky right now and needs to be rethought. Wrapping them in explicit closures per @bstrie is the best workaround.

@bstrie
Copy link
Contributor

bstrie commented Sep 21, 2012

@brson Actually, using named functions in this case wasn't an issue. Changing func() to (*func)() fixes the problem in either case, and when using func() you even get the same error message whether you're using named functions or closures. Is there something else you're referring to that we should be aware of?

@nikomatsakis
Copy link
Contributor

as @bstrie pointed out, this is related to demoding... each gives you a ptr to the thing in the list, hence a ptr to a fn, so you have to manually dereference the pointer to call it.

@brson
Copy link
Contributor

brson commented Sep 21, 2012

@bstrie no

RalfJung pushed a commit to RalfJung/rust that referenced this issue May 4, 2024
tls dtors: treat all unixes uniformly
RalfJung pushed a commit to RalfJung/rust that referenced this issue May 4, 2024
tls dtors: treat all unixes uniformly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants