【问题标题】:Programming Languages problem, Procedural Language, Dynamic Scope编程语言问题,过程语言,动态范围
【发布时间】:2021-12-13 02:12:42
【问题描述】:

在我的软件开发课程中,我被分配了这样一个问题。因此,通常的方法是逐个检查每个过程并记住每个子程序的每个调用,但是,我是一个有点懒的程序员,我决定走捷径,用实际的编程语言实现给定的伪代码。

问题陈述:

    procedure Main is
        X, Y, Z : Integer;
        procedure Sub1 is
            A, Y, Z : Integer;
        begin
        ...
        end;

        procedure Sub2 is
            A, B, Z : Integer;
        begin
        ...
            procedure Sub4 is
                A, B, W : Integer;
            begin
            ...
            end;
        end;

        procedure Sub3 is
            A, X, W : Integer;
        begin
        ...
        end;
    begin
    ...
    end;

考虑上面的程序。给定以下调用序列并假设 使用动态作用域,在最后一个子程序的执行过程中哪些变量是可见的 活性?在每个可见变量中包含声明它的单元的名称(例如 Main.X)。

  • 主调用 Sub1; Sub1 调用 Sub3; Sub3 调用 Sub2;

我的尝试:

$x = 10;
$y = 20;
$z = 30;
sub Sub2 
{ 
   return $x; 
}
sub Sub1
{ 
   local $x = 9; 
   local $y = 19; 
   local $z = 29; 
   return Sub2(); 
}
print Sub1()."\n";

我被困在这一点上,不知道如何更改代码以显示变量。我看到这个解决方案很明显,但到目前为止我已经用 C++ 和 Java 编写过代码。

【问题讨论】:

  • 您可以使用PadWalker 之类的东西来检查调用者中的词法变量。可以使用 Devel::Symdump 之类的方式检查包变量
  • @HåkonHægland 我真的不知道什么是 Perl 包。但我肯定会检查 PadWalker 和 Devel::Symdump。谢谢!
  • 由于我们不知道最后调用的是哪个sub(因为我们懒得弄明白),所以我们需要打印所有不调用的subs中的vars其他潜艇。
  • 懒惰的程序员总能找到更好的方法。但我确实找到了正确的(硬)方法。我只是对自动方式感到好奇。
  • 您的讲师所说的“动态范围”与 Perl 中的含义可能不匹配。 local 对全局变量的值进行局部更改。它不会影响变量的可见性(它是全局的,随处可见)。

标签: perl variables procedure pseudocode scopes


【解决方案1】:

如果您花时间在观看教程上提出这个问题,那就太好了。然而,我们都曾经历过一次,对探索新语言感到困惑。下次尽量不要问作业的答案。

所以,我看到您想使用 Perl,这是一个不错的选择。我自己最近也做过类似的任务,这是我的方法。

正如 R. Sebesta (2019) 在名为“编程概念”的书中所写 Languages”(第 12 版),动态范围的最佳示例是 Perl 和 Common Lisp。

基本上,它基于仅在运行时确定的子程序调用顺序。

以下程序显示子程序调用如何影响变量值:

$x = 0;
$y = 0;
$z = 0;
sub sub1
{
    local $a = 1;
    local $y = 1;
    local $z = 1;
    return sub3();
}

sub sub2
{
    local $a = 2;
    local $b = 2;
    local $z = 2;
    sub sub4
    {
        local $a = 4;
        local $b = 4;
        local $w = 4;
    }
    return "Sub".$a.".A, "."Sub".$b.".B, "."Sub".$w.".W, "."Sub".$x.".X,
"."Sub".$y.".Y, "."Sub".$z.".Z";
    
}

sub sub3
{
    local $a = 3;
    local $x = 3;
    local $w = 3;
    return sub2();
}
print sub1()."\n";

输出Sub2.ASub2.BSub3.WSub3.XSub1.YSub2.Z
注意Sub0只是主子程序范围。

【讨论】:

  • 我知道,看教程会解决我的问题。
【解决方案2】:

如果您想检查每个子程序中的变量值,您可以使用 Data::DumpData::Dumper 之类的模块将它们转储出来。

sub foo { 
  printf "foo() current values are %s\n\n", 
    Data::Dumper::Dumper($a, $b, $c, $x, $y, $z);
}

如果您想查看当前子程序的调用堆栈,您可以使用Carp 模块。

use Carp;
sub foo { Carp::cluck("foo() here"); }
sub bar { foo() }

&bar;

# Output
foo() here at (eval 284) line 1.
        W::foo() called at (eval 284) line 1
        W::bar() called at (eval 285) line 1
        eval 'package W; bar' called at script.pl line 116
        console::_console called at script.pl line 473



【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 2017-09-07
    • 2014-10-06
    • 2011-05-17
    相关资源
    最近更新 更多