use finx::{Finx, Value};
use std::cell::RefCell;
use std::rc::Rc;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Finx Closure Demo ===\n");
let mut engine = Finx::new();
println!("1. Simple Closure with Captured Constant:");
let multiplier = 5.0;
engine.register_function(
"times_five",
Rc::new(move |args| {
if let [Value::Number(n)] = args {
Value::Number(n * multiplier)
} else {
Value::Null
}
}),
1,
);
let result = engine.eval("times_five(7)")?;
println!(" times_five(7) = {}", result);
println!("\n2. Closure with Mutable Captured State:");
let counter = Rc::new(RefCell::new(0));
let counter_clone = counter.clone();
engine.register_function(
"next_id",
Rc::new(move |_args| {
let mut count = counter_clone.borrow_mut();
*count += 1;
Value::Number(*count as f64)
}),
0,
);
for _ in 0..5 {
let result = engine.eval("next_id()")?;
println!(" next_id() = {}", result);
}
println!("\n3. Closure with Configuration:");
let config = "Hello from Rust";
engine.register_function(
"rust_greet",
Rc::new(move |args| {
if let [Value::Str(name)] = args {
Value::Str(format!("{}, {}!", config, name).into())
} else {
Value::Null
}
}),
1,
);
let result = engine.eval(r#"rust_greet("World")"#)?;
println!(" rust_greet(\"World\") = {}", result);
println!("\n4. Multiple Closures Sharing State:");
let shared_data = Rc::new(RefCell::new(vec![1.0, 2.0, 3.0]));
let data_clone = shared_data.clone();
engine.register_function(
"add_to_list",
Rc::new(move |args| {
if let [Value::Number(n)] = args {
data_clone.borrow_mut().push(*n);
Value::Bool(true)
} else {
Value::Bool(false)
}
}),
1,
);
let data_clone2 = shared_data.clone();
engine.register_function(
"list_sum",
Rc::new(move |_args| {
let sum: f64 = data_clone2.borrow().iter().sum();
Value::Number(sum)
}),
0,
);
let data_clone3 = shared_data.clone();
engine.register_function(
"list_len",
Rc::new(move |_args| Value::Number(data_clone3.borrow().len() as f64)),
0,
);
println!(
" Initial: sum = {}, len = {}",
engine.eval("list_sum()")?,
engine.eval("list_len()")?
);
engine.eval("add_to_list(10)")?;
engine.eval("add_to_list(20)")?;
println!(
" After adding 10 and 20: sum = {}, len = {}",
engine.eval("list_sum()")?,
engine.eval("list_len()")?
);
println!("\n5. Using the register_function! Macro:");
let base_value = 100.0;
engine.register_closure(
"add_base",
move |args| {
if let [Value::Number(n)] = args {
Value::Number(n + base_value)
} else {
Value::Null
}
},
1,
);
let result = engine.eval("add_base(42)")?;
println!(" add_base(42) = {}", result);
println!("\n=== Closure Demo completed successfully! ===");
Ok(())
}