You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: ez.rs
    path of file: ./repos/fasteval/src
    
    the code of the file until where you have to start completion: //! An easy API for single-function-call expression evaluation.

use crate::error::Error;
use crate::parser::Parser;
use crate::evaler::Evaler;
use crate::slab::Slab;
use crate::evalns::EvalNamespace;

/// The `ez_eval()` function provides a very simple way to perform expression evaluation with just one function call.
///
/// If you only need to evaluate an expression on
    
pub fn ez_eval(expr_str:&str, ns:&mut impl EvalNamespace) -> Result<f64,Error> {
    let mut slab = Slab::new();  // A big block of memory, so we don't need to perform many tiny (and slow!) allocations.

    // Here is a one-liner that performs the entire parse-and-eval process:
    // Parser::new().parse(expr_str, &mut slab.ps)?.from(&slab.ps).eval(&mut slab, &mut ns)

    // Here is the same process, broken into steps:

    // First, parse the string:
    // We use the 'parse_noclear' function instead of 'parse' because we know the slab is empty.
    let expr_i = Parser::new().parse_noclear(expr_str, &mut slab.ps)?;

    // 'expr_i' is an index into the Slab.  You can extract the Expression object with either of these:
    //     slab.get_expr(expr_i)  ...OR...  expr_i.from(&slab.ps)
    // The first is more direct.  The second is a convenience built on top of the first.
    let expr_ref = slab.ps.get_expr(expr_i);

    // Use the reference to the Expression object to perform the evaluation:
    expr_ref.eval(&slab, ns)
}