Not that I know of. The foo(some_arg) syntax is rewritten to call the call() method from the relevant Fn trait, so unless you figure out some voodoo magic to generate a callable, nameable closure, it won't be possible.
It seems to me you would be better off relaxing requirement 1 – you can still do everything by calling a regular method that you could do by relying on () sugar.
Oh, if your struct has a field which is a closure, you can simply deref to it indeed!
mod lib {
pub
struct FunctionIsh<ImplFn> {
f: ImplFn,
/* … */
}
impl<ImplFn> ::core::ops::Deref for FunctionIsh<ImplFn> {
type Target = ImplFn;
fn deref (self: &'_ Self)
-> &'_ Self::Target
{
&self.f
}
}
#[allow(dead_code)]
mod private { pub enum ImplFn {} }
impl FunctionIsh<private::ImplFn> { // <- this could be using any type, but we use a hidden one named `ImplFn` to make it look nicer in the documentation
pub
fn new ()
-> FunctionIsh<impl Fn()> // The key hack is that this ≠ Self
{
FunctionIsh {
f: || println!("printing"), // No alloc!
}
}
}
}
fn main ()
{
use lib::FunctionIsh;
let f: FunctionIsh<_> = FunctionIsh::new();
f();
}
But obviously the cost to pay for that is that every usage of Functionish will need to be generic / of the form FunctionIsh<impl Fn()>, so in practice you won't see this pattern that much. We'd need, at the very least, the existential types feature to make this ergonomic (the good news is that that feature ought to be stabilized way faster than the Fn traits):
#![feature(type_alias_impl_trait)]
mod lib {
pub
struct FunctionIsh {
f: ImplFn,
/* … */
}
// where:
pub type ImplFn = impl Fn();
// defined by:
fn make_function () -> ImplFn
{
|| println!("printing")
}
impl FunctionIsh {
pub
fn new ()
-> Self
{
FunctionIsh {
f: make_function(), // No alloc!
}
}
}
impl ::core::ops::Deref for FunctionIsh {
type Target = ImplFn;
fn deref (self: &'_ Self)
-> &'_ Self::Target
{
&self.f
}
}
}
fn main ()
{
use lib::FunctionIsh;
let f: FunctionIsh = FunctionIsh::new();
f();
}
But neither solution allows to have a closure whose captured state can be mutated by something different than its own () call. For that, you either need the fn_traits / unboxed_closures features as @nologik showed, or you'll need to let go of the () sugar, as @H2CO3 suggested, which is way simpler and cleaner than most of these hacky-or-nightly-only patterns:
if you want the sugar to type less, you can have a one-long method: .c();
if you want the sugar to have a consistent syntax to call both closures and FunctionIsh-like entities, and/or to have a generic function accepting both kind of parameters, you can actually make closures use your own calling syntax / implement your own trait:
trait MyFn {
fn c (self: &'_ Self);
}
impl<F : Fn()> MyFn for F {
fn c (self: &'_ Self)
{
self()
}
}
impl MyFn for FunctionIsh { … }