В моем скрипте rhai есть две функции, direct
и indirect
, и я хотел бы предоставить переменные с помощью Scope
. (Т.е. я не хотел бы передавать их в качестве аргументов функциям.) Когда я вызываю direct
с областью видимости, скрипт, по-видимому, может получить доступ к переменной из области.
Однако, когда я вызываю indirect
(который делегаты работают с direct
), выполнение завершается ошибкой, потому что не может найти переменные в Scope
.
Эта программа демонстрирует мою проблему. (Обратите внимание на последний вызов expect_err
, который показывает, что indirect
не может получить доступ к x
из scope
.)
use rhai::{Engine, Scope};
#[allow(unused_must_use)]
fn main() {
let engine = Engine::new();
let ast = engine.compile(r"
fn direct() {
print(x); // <----- Note: This uses x, which is assumed to be supplied by Scope
}
fn indirect() {
direct();
}
").unwrap();
// I understand this (x not in scope)
engine.call_fn::<()>(&mut Scope::new(), &ast, "direct", ())
.expect_err("Because of missing 'x'");
let mut scope = Scope::new();
scope.push("x", 1);
engine.call_fn::<()>(&mut scope, &ast, "direct", ())
.expect("Works as expected as 'x' is supplied by scope.");
engine.call_fn::<()>(&mut scope, &ast, "indirect", ())
.expect_err("This returns Err although 'x' is supplied by scope - why?"); // <--- Can I make this call work?
}
Из здесь и здесь Я ожидал, что даже вызов indirect
позволит вызываемому direct
получить доступ к переменным из scope
. Моя интерпретация здесь неверна?
Или, альтернативно: есть ли способ, который позволил бы мне успешно вызвать indirect
, указав значение x
в Scope
?
@SvenMarnach Спасибо. Я не ожидал, что это будет "продвинутая тема". Если вы хотите добавить ответ, я с радостью приму его.
Я действительно не знаю, о чем говорю, и не чувствую себя вправе отвечать. Я только что потратил 30 секунд на гугление и случайно наткнулся на эту страницу — я даже не заметил, что она находится в разделе «расширенные темы».
Из Rhai Book вы можете Вызвать функцию в пределах области действия вызывающей стороны:
Функции Rhai являются чистыми, что означает, что они зависят от своих аргументов и не имеют доступа к вызывающей среде.
Когда функция обращается к переменной, которая не определена в области видимости этой функции, возникает ошибка оценки.
С помощью специального синтаксиса можно фактически запустить вызов функции в пределах области действия родительского вызывающего объекта, т. е. области действия, в которой выполняется вызов функции, и получить доступ/изменять определенные там переменные.
fn foo(y) { // function accesses 'x' and 'y', but 'x' is not defined x += y; // 'x' is modified in this function let z = 0; // 'z' is defined in this function's scope x } let x = 1; // 'x' is defined here in the parent scope foo(41); // error: variable 'x' not found // Calling a function with a '!' causes it to run within the caller's scope foo!(41) == 42; // the function can access and mutate the value of 'x'! x == 42; // 'x' is changed!
Таким образом, вы должны быть в состоянии сделать это с помощью direct!()
.
Никогда не слышал о Rhai, но, судя по документации, это просто семантика языка. Область, которую вы передаете, назначается вызываемой вами функции, но она не передается вложенным вызовам, если вы не используете специальный синтаксис. Я не могу больше сказать вам, так как я никогда не использовал язык. :)