async closure does not implement Fn because it captures state from its environment #684
-
|
Hi, I'm relatively new to Rust, and I'm trying to make a program that allows for Lua scripting to interact with the Twitch API. However, I'm running into a problem with trying to use the shared state object inside of functions created within let state = Arc::new(SMState::new(&twitch.token, &ttv_client, &twitch.userid));
let lua = Lua::new();
{
let lglobal = lua.globals();
let ltwitch = lua.create_table()?;
ltwitch.set("me", state.my_user_id.as_str())?;
let ltwitch_chat = lua.create_table()?;
{
let state_c = state.clone();
ltwitch_chat.set(
"send",
lua.create_async_function(async move |lua, (to_user, msg): (String, String)| { // line 130
let broadcaster = BroadcasterId::from(to_user);
let me = UserId::from(lua.globals().get_path::<String>("twitch.me")?);
if let Err(e) = state_c
.api
.send_chat_message(&broadcaster, &me, &msg)
.json()
.await
{
println!("Message failed to send: {}", e);
}
Ok(())
})?,
)?;
}
ltwitch.set("chat", ltwitch_chat)?;
lglobal.set("twitch", ltwitch)?;
}Maybe MLua provides a solution for this that would work for me, but I'm not familiar enough with all this to really know how to do this. My main concern is that I want to avoid exposing the Twitch access token within the Lua environment. If it matters, |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
|
Try regular closure with async block See https://blog.rust-lang.org/2025/02/20/Rust-1.85.0/#async-closures also https://www.reddit.com/r/rust/comments/1br6e6i/difference_between_async_and_async/ |
Beta Was this translation helpful? Give feedback.
-
|
Thank you for your help. I've now tried doing this, and I get this error and suggestion instead: If I follow the suggestion and move the clone into the closure, I get: So it suggests to add let state = Arc::new(SMState::new(&twitch.token, &ttv_client, &twitch.userid));
let lua = Lua::new();
{
let lglobal = lua.globals();
let ltwitch = lua.create_table()?;
ltwitch.set("me", state.my_user_id.as_str())?;
let ltwitch_chat = lua.create_table()?;
{
let state_c = state.clone();
ltwitch_chat.set(
"send",
lua.create_async_function(move |lua, (to_user, msg): (String, String)| {
let state_cc = state_c.clone();
async move {
let broadcaster = BroadcasterId::from(to_user);
let me =
UserId::from(lua.globals().get_path::<String>("twitch.me")?);
if let Err(e) = state_cc
.api
.send_chat_message(&broadcaster, &me, &msg)
.json()
.await
{
println!("Message failed to send: {}", e);
}
Ok(())
}
})?,
)?;
}
ltwitch.set("chat", ltwitch_chat)?;
lglobal.set("twitch", ltwitch)?;
}Is there a cleaner way to do this? |
Beta Was this translation helpful? Give feedback.
Looks okay to me,
stateisArcso clones are very cheap (just increasing number of references).Another option is saving
statein Lua application dataLua::set_app_datawhich can be retrieved anywhere inside Lua function usingLua::app_data_ref