Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I create a static constant closure?

Background

I have a struct that stores a couple of references to closures

struct FnThing<'a, F: Fn()> {
    f: &'a F,
}

I want to implement the Default trait for FnThing where f has default value of a no-op ||{} function.

Since f is a reference, I plan to accomplish this by creating a static no-op closure function so that I can set the defualt value as

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

impl<'a, F: Fn()> Default for FnThing<'a, F> {
    fn default() -> Self {
        Self { f: &NO_OP }
    }
}

First attempt

static NO_OP: impl Fn = ||{};

rust complains that

`impl Trait` only allowed in function and inherent method return types, not in const types

Fair enough

Second attempt

static NO_OP: dyn Fn() = || {};

Now it complains that

the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time

OK, for unknown size, I should use the heap

Third attempt

static NO_OP: Box<dyn Fn()> = Box::new(|| {});

Now it complains

`(dyn Fn() + Send + 'static)` cannot be shared between threads safely

I don’t care about multithreading atm, but it would still be nice if my code was thread safe in case I do in the future. Though I fail understand why this isn’t thread safe.

Fourth attempt

Why not just use a simple function pointer?

static NO_OP: fn() = || {};

impl<'a, F: Fn()> Default for FnThing3<'a, F> {
    fn default() -> Self {
        Self { f: NO_OP }
    }
}

This doesn’t work since fn() and F: Fn() are different types. Following this answer, I try

    fn default() -> Self {
        Self {
            f: (Box::new(NO_OP) as Box<dyn Fn()>).as_ref(),
        }
    }

but it still gives me the error

expected `&F`, found `&dyn Fn()`

Question

I’m out of ideas…
How do I create a static constant closure?

>Solution :

You’re almost there. Your problem right now is that you’re trying to get a generic F: impl Fn(). You can just not write that, since you can’t have a default over every generic type. So just impl Default for the case where F is just fn(), like so:

struct FnThing<'a, F: Fn()> {
    f: &'a F,
}

static NO_OP: fn() = || {};

impl<'a> Default for FnThing<'a, fn()> {
    fn default() -> Self {
        FnThing { f: &NO_OP }
    }
}

I think this is the what you want. Let me know if it works the way you want!

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading