首先,如果这个问题不合适,请道歉;我实际上并不知道很多perl。
我正在尝试调试一些现有的代码,这些代码应该从我们的在线作业系统WeBWorK发送成绩到LMS。我遇到了一个奇怪的错误,我认为某些东西没有被正确初始化,或者可能不是正确的类。我怀疑问题可能在这里:
sub go {
my $self = shift;
my $r = $self->r;
my $ce = $r->ce;
# If grades are begin passed back to the lti then we peroidically
# update all of the grades because things can get out of sync if
# instructors add or modify sets.
if ($ce->{LTIGradeMode}) {
my $grader = WeBWorK::Authen::LTIAdvanced::SubmitGrade->new($r);
my $post_connection_action = sub {
my $grader = shift;
# catch exceptions generated during the sending process
my $result_message = eval { $grader->mass_update() };
if ($@) {
# add the die message to the result message
$result_message .= "An error occurred while trying to update grades via LTI.\n"
. "The error message is:\n\n$@\n\n";
# and also write it to the apache log
$r->log->error("An error occurred while trying to update grades via LTI: $@\n");
}
};
if (MP2) {
$r->connection->pool->cleanup_register($post_connection_action, $grader);
} else {
$r->post_connection($post_connection_action, $grader);
}
}
... # a bunch of other stuff happens in the "go" sub
我有点怀疑问题出在$grader
变量上;特别是,我不知道匿名子内部my $grader = shift;
做了什么。就像,如果sub有一个名字,那么shift
给出传递给sub的第一个参数就更清楚了。但由于它是匿名的,我不知道它认为它的论点是什么。
此外,我不确定为什么需要这条线。就像,从我的谷歌搜索,我被理解,匿名子的意义是保持范围内的周围环境的所有变量。那么为什么我们需要首先在匿名子内部重新定义$grader
?
感谢您帮助perl noob! :)
答案 0 :(得分:4)
在这方面没有什么特别的关于anon潜艇。
my $cr = sub {
my $arg = shift;
say $arg;
};
$cr->("foo"); # Prints "foo"
$cr->("bar"); # Prints "bar"
在您的情况下,您将$post_connection_action
和$grader
传递给cleanup_register
或post_connection
,期望它会导致&$post_connection_action
调用{ {1}}作为它的第一个参数。期望是否正确取决于$grader
和cleanup_register
的实施,我对此一无所知。
请注意,另一种解决方案出现在这里。在评估post_connection
运算符时,Subs可以访问范围内的词汇。
sub
即使被调用的词汇在被调用时不再存在,上述情况也是如此。
my $prefix = "> ";
my $cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
$cr->("foo"); # Prints "> foo"
这意味着您不需要将my $cr;
{
my $prefix = "> ";
$cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
} # $prefix would normally stop existing here.
$cr->("foo"); # Prints "> foo"
作为参数传递。它可以简单地捕获。只需忽略$grader
(并且不要将my $grader = shift;
传递给
$grader
或cleanup_register
)。