gpt4 book ai didi

具有深/浅绑定(bind)的动态/静态范围(练习)

转载 作者:行者123 更新时间:2023-12-02 21:11:49 46 4
gpt4 key购买 nike

我正在研究具有深/浅绑定(bind)的动态/静态作用域,并手动运行代码以了解这些不同的作用域/绑定(bind)实际上是如何工作的。我阅读了理论并在谷歌上搜索了一些示例练习,我发现这些练习非常简单(例如 this one 这对动态作用域非常有帮助)但是我无法理解静态作用域的工作原理。

在这里,我发布了一个练习,以检查我是否获得了正确的解决方案:

考虑以下用伪代码编写的程序:

int u = 42; 
int v = 69;
int w = 17;
proc add( z:int )
u := v + u + z
proc bar( fun:proc )
int u := w;
fun(v)
proc foo( x:int, w:int )
int v := x;
bar(add)
main
foo(u,13)
print(u)
end;

屏幕上打印的内容

a) 使用静态作用域?答案=180

b) 使用动态作用域和深度绑定(bind)?答案=69(u的总和=126,但它是foo的本地v,对吧?)

c) 使用动态作用域和浅绑定(bind)? answer=69(u 的总和 = 101,但它是 foo 的本地 v,对吧?)

PS:我正在尝试做一些这样的练习,如果你知道我在哪里可以找到这些类型的问题(最好有解决方案),请提供链接,谢谢!

最佳答案

您对词法(静态)范围的回答是正确的。您对动态范围的回答是错误的,但如果我正确地阅读了您的解释,那是因为您在 uv 之间感到困惑,而不是因为对深度和浅层绑定(bind)的工作原理。 (我假设您的 u/v 混淆只是偶然的,而不是由于对 foo< 的调用中的值与引用的奇怪混淆。)

a) using static scope? answer=180

正确。

b) using dynamic scope and deep binding? answer=69 (sum for u = 126 but it's foo's local v, right?)

您的括号解释是正确的,但您的答案是错误的:u确实设置为126,并且foo确实本地化了 v,但由于 main 打印 u,而不是 v,所以答案是 126

c) using dynamic scope and shallow binding? answer=69 (sum for u = 101 but it's foo's local v, right?)

u 的总和实际上是 97 (42+13+42),但由于 bar 本地化u,答案是42。 (您的括号解释对此是错误的 - 您似乎在解释语句 int u := w 时使用了全局变量 w,即 17 bar 的定义中;但该语句实际上引用了 foo 的局部变量 w,它的第二个参数,即13。但这实际上并不影响答案。您的答案对于这个答案是错误的,只是因为 main 打印 u,而不是 v。)

<小时/>

对于词法范围,通过将伪代码翻译成具有词法范围的语言来检查您的答案非常容易。同样具有浅绑定(bind)的动态作用域。 (事实上​​,如果您使用 Perl,您几乎可以同时测试这两种方式,因为它支持这两种方式;只需使用 my 作为词法范围,然后执行查找和替换将其更改为 local 表示动态作用域。但是,即使您使用 JavaScript 表示词法作用域,使用 Bash 表示动态作用域,也应该可以快速测试两者。)

具有深度绑定(bind)的动态作用域要棘手得多,因为很少有广泛部署的语言支持它。如果您使用 Perl,则可以通过使用从变量名映射到标量引用的哈希(关联数组)并将此哈希从一个函数传递到另一个函数来手动实现它。在伪代码声明局部变量的任何地方,您都将现有的标量引用保存在 Perl 词法变量中,然后将新的映射放入哈希中;在函数结束时,恢复原始标量引用。为了支持绑定(bind),您可以创建一个包装函数,该函数创建哈希的副本,并将传递给其包装函数。下面是使用该方法在 Perl 中动态范围、深度绑定(bind)的程序实现:

#!/usr/bin/perl -w

use warnings;
use strict;

# Create a new scalar, initialize it to the specified value,
# and return a reference to it:
sub new_scalar($)
{ return \(shift); }

# Bind the specified procedure to the specified environment:
sub bind_proc(\%$)
{
my $V = { %{+shift} };
my $f = shift;
return sub { $f->($V, @_); };
}

my $V = {};

$V->{u} = new_scalar 42; # int u := 42
$V->{v} = new_scalar 69; # int v := 69
$V->{w} = new_scalar 17; # int w := 17

sub add(\%$)
{
my $V = shift;
my $z = $V->{z}; # save existing z
$V->{z} = new_scalar shift; # create & initialize new z
${$V->{u}} = ${$V->{v}} + ${$V->{u}} + ${$V->{z}};
$V->{z} = $z; # restore old z
}

sub bar(\%$)
{
my $V = shift;
my $fun = shift;
my $u = $V->{u}; # save existing u
$V->{u} = new_scalar ${$V->{w}}; # create & initialize new u
$fun->(${$V->{v}});
$V->{u} = $u; # restore old u
}

sub foo(\%$$)
{
my $V = shift;
my $x = $V->{x}; # save existing x
$V->{x} = new_scalar shift; # create & initialize new x
my $w = $V->{w}; # save existing w
$V->{w} = new_scalar shift; # create & initialize new w
my $v = $V->{v}; # save existing v
$V->{v} = new_scalar ${$V->{x}}; # create & initialize new v
bar %$V, bind_proc %$V, \&add;
$V->{v} = $v; # restore old v
$V->{w} = $w; # restore old w
$V->{x} = $x; # restore old x
}

foo %$V, ${$V->{u}}, 13;
print "${$V->{u}}\n";

__END__

实际上它打印了126。这显然很困惑且容易出错,但它也确实可以帮助您了解正在发生的事情,因此出于教育目的,我认为这是值得的!

关于具有深/浅绑定(bind)的动态/静态范围(练习),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3869040/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com