如果你在匿名 sub 中调用 shift 会发生什么?
What happens if you call shift inside an anonymous sub?
首先,如果这个问题不恰当,我们深表歉意;我实际上并不知道很多 perl。
我正在尝试调试一些现有代码,这些代码应该将成绩从我们名为 WeBWorK 的在线作业系统发送到 LMS。我 运行 遇到了一个奇怪的错误,我认为某些东西没有正确初始化,或者可能不正确 class。我怀疑问题可能出在这里:
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 中做了什么。就像,如果 sub 有一个名字,那么 shift
给出传递给 sub 的第一个参数会更清楚。但由于是匿名的,我不知道它认为它的论点是什么。
此外,我不太确定为什么需要该行。就像,从我的谷歌搜索中,我了解到匿名子的要点是将周围环境中的所有变量都保留在范围内。那么,为什么我们首先需要在匿名 sub 中重新定义 $grader
?
感谢您帮助 perl 新手! :)
匿名潜艇在这方面没有什么特别之处。
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
以 $grader
作为第一个参数。期望是否正确取决于cleanup_register
和post_connection
的实现,我对此一无所知。
请注意,此处出现了另一种解决方案。当评估 sub
运算符时,Subs 可以访问范围内的词法。
my $prefix = "> ";
my $cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
$cr->("foo"); # Prints "> foo"
即使捕获的词法在调用 sub 时不再存在,上述也是正确的。
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
或 post_connection
).
首先,如果这个问题不恰当,我们深表歉意;我实际上并不知道很多 perl。
我正在尝试调试一些现有代码,这些代码应该将成绩从我们名为 WeBWorK 的在线作业系统发送到 LMS。我 运行 遇到了一个奇怪的错误,我认为某些东西没有正确初始化,或者可能不正确 class。我怀疑问题可能出在这里:
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 中做了什么。就像,如果 sub 有一个名字,那么 shift
给出传递给 sub 的第一个参数会更清楚。但由于是匿名的,我不知道它认为它的论点是什么。
此外,我不太确定为什么需要该行。就像,从我的谷歌搜索中,我了解到匿名子的要点是将周围环境中的所有变量都保留在范围内。那么,为什么我们首先需要在匿名 sub 中重新定义 $grader
?
感谢您帮助 perl 新手! :)
匿名潜艇在这方面没有什么特别之处。
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
以 $grader
作为第一个参数。期望是否正确取决于cleanup_register
和post_connection
的实现,我对此一无所知。
请注意,此处出现了另一种解决方案。当评估 sub
运算符时,Subs 可以访问范围内的词法。
my $prefix = "> ";
my $cr = sub {
my $arg = shift;
say "$prefix$arg"; # Captures $prefix from sub{} scope.
};
$cr->("foo"); # Prints "> foo"
即使捕获的词法在调用 sub 时不再存在,上述也是正确的。
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
或 post_connection
).