Writing Functions

You can use the attribute macro #[defun] to export Rust functions to the Lisp runtime, so that Lisp code can call them. The exporting process happens when the module is loaded, even if the definitions are inside another function that is never called, or inside a private module.

Input Parameters

Each parameter must be one of the following:

An owned value of a type that implements FromLisp . This is for simple data types that have an equivalent in Lisp. # #![allow(unused_variables)] #fn main() { /// This docstring will appear in Lisp too! #[defun] fn inc(x: i64) -> Result<i64> { Ok(x + 1) } #}

. This is for simple data types that have an equivalent in Lisp. A shared/mutable reference. This gives access to data structures that other module functions have created and embedded in the Lisp runtime (through user-ptr objects). # #![allow(unused_variables)] #fn main() { #[defun] fn stash_pop(repo: &mut git2::Repository) -> Result<()> { repo.stash_pop(0, None)?; Ok(()) } #}

objects). A Lisp Value . This allows holding off the conversion to Rust data structures until necessary, or working with values that don't have a meaningful representation in Rust, like Lisp lambdas. # #![allow(unused_variables)] #fn main() { #[defun] fn maybe_call(lambda: Value<'_>) -> Result<()> { if some_hidden_native_logic() { lambda.env.call("funcall", &[lambda])?; } Ok(()) } #}

. This allows holding off the conversion to Rust data structures until necessary, or working with values that don't have a meaningful representation in Rust, like Lisp lambdas. An &Env . This enables interaction with the Lisp runtime. It does not appear in the function's Lisp signature. This is unnecessary if there is already another parameter with type Value , which allows accessing the runtime through Value.env . # #![allow(unused_variables)] #fn main() { // Note that the function takes an owned `String`, not a reference, which would // have been understood as a `user-ptr` object containing a Rust string. #[defun] fn hello(env: &Env, name: String) -> Result<Value<'_>> { env.message(format!("Hello, {}!", name)) } #}

Return Value

The return type must be Result<T> , where T is one of the following:

A type that implements IntoLisp . This is for simple data types that have an equivalent in Lisp. # #![allow(unused_variables)] #fn main() { /// Return the path to the .git dir. /// Return `nil' if the given path is not in a repo, /// or if the .git path is not valid utf-8. #[defun] fn dot_git_path(path: String) -> Result<Option<String>> { Ok(git2::Repository::discover(&path).ok().and_then(|repo| { repo.path().to_str().map(|s| s.to_owned()) })) } #}

. This is for simple data types that have an equivalent in Lisp. An arbitrary type. This allows embedding a native data structure in a user-ptr object, for read-write use cases. It requires user_ptr option to be specified. If the data is to be shared with background Rust threads, user_ptr(rwlock) or user_ptr(mutex) must be used instead. # #![allow(unused_variables)] #fn main() { #[defun(user_ptr)] fn repo(path: String) -> Result<git2::Repository> { Ok(git2::Repository::discover(&path)?) } #}

object, for read-write use cases. It requires option to be specified. If the data is to be shared with background Rust threads, or must be used instead. A type that implements Transfer . This allows embedding a native data structure in a user-ptr object, for read-only use cases. It requires user_ptr(direct) option to be specified.

. This allows embedding a native data structure in a object, for read-only use cases. It requires option to be specified. Value . This is mostly useful for returning an input parameter unchanged.

See Custom Types for more details on embedding Rust data structures in Lisp's user-ptr objects.

Naming

By default, the function's Lisp name has the form <feature-prefix>[mod-prefix]<base-name> .

feature-prefix is the feature's name, followed by - . This can be customized by the name and separator options on #[emacs::module] .

is the feature's name, followed by . This can be customized by the and options on . mod-prefix is constructed from the function's Rust module path (with _ and :: replaced by - ). This can be turned off crate-wide, or for individual function, using the option mod_in_name .

is constructed from the function's Rust module path (with and replaced by ). This can be turned off crate-wide, or for individual function, using the option . base-name is the function's Rust name (with _ replaced by - ). This can be overridden with the option name .

Examples: