neektza
neektza

Reputation: 533

What is a function signature and type?

I found the type alias below in an Scheme interpreter I'm studying. While evaluating the AST, it recognizes a function either as a natively supported function, or as a user defined function. I understand the second part of the Enum definition, but the first part eludes me.

pub enum Function {
    Native(ValueOperation),
    Scheme(Vec<String>, Vec<Value>, Rc<RefCell<Environment>>),
}


type ValueOperation = fn(&[Value], Rc<RefCell<Environment>>) -> Result<Value, RuntimeError>;

How does this type alias work? Does this definition say that a ValueOperation is just a shorthand for a function signature? I was unable to find any mention of this idiom in the official docs/books.

What's the purpose of defining a type alias for a function signature? What can you "do" with it? Is it some sort of a function pointer?

Upvotes: 4

Views: 7950

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299930

The signature of a function describes:

  • its name
  • its arguments
  • its result
  • in the case of generic functions, its generic parameters, with potentially specific bounds

For example, if you define:

fn hello(s: &str) {
    println!("Hello {}", s);
}

The function signature is fn hello(&str).


In Rust, each function has a unique type, which cannot be named.

However, if you have a function, you can also coerce it into a generic fn type which does not care about the identity of the function, but only about how it can be used.

For the above function, this generic type is: fn(&str) (or fn(&str) -> () if we wish to be explicit).


This generic type is useful to abstract over multiple functions with a similar signature. For example:

fn add(left: i32, right: i32) -> i32 { left + right }
fn sub(left: i32, right: i32) -> i32 { left - right }

fn select(name: &str) -> fn(i32, i32) -> i32 {
    match name {
        "add" => add,
        "sub" => sub,
        _ => unimplemented!(),
    }
}

fn main() {
    let fun = select("add");
    println!("{} + {} = {}", 1, 2, fun(1, 2));
}

It is close to function pointers in C or C++, however unlike function pointers it cannot be null.

If you need a nullable function, you can use Option<fn(i32, i32) -> i32> instead.


And thus finally we come to this type alias: it's simply a shortcut because the generic fn type is long. Like any other type alias.

Upvotes: 11

Related Questions